写在前面的话
写了这么多章的废话,今天终于开始可以算进入主题了.当然了,之后的故事发展也是我个人觉得比较激动人心的部分.因为,我们今天开始讲解的部分是架构部分.
从今以后你需要准备的东西就是你的大脑,恩,感觉说道跟动脑有关的时候有的人就会觉得好痛苦.放心把,我会尽力写的只要脑袋在头上都能看的懂的.
申明
此文章请勿转载,谢谢合作
系统架构
在这里我们说了,将会使用资源来判断Android是不是存在重打包的现象.在这一章我们将会说说这个系统的架构.
我们说过,之前有人是这么处理重打包问题,当然了,都是俺大中国同胞们的办法.想一想Android的APP为什么会出现重打包的现象.或许恶意软件的制作者就是想通过某些流行的APP让更多的人蒙受经济损失.我就听人跟我抱怨过,说我能不能写个程序判断一下那个愤怒的小鸟是不是有问题,他对我说他儿子玩着玩着不知道点了那个奇葩的按钮然后,duang~20块钱就没了.我们这么区分这种被动了手脚的APP和没有被动了手脚的APP.
然后呢,有人脑袋一亮,就想出了这么一招:
重打包软件的制作者在重打包APP软件的时候,总会考虑一下性价比的吧.就如说你重打包一个APP,都没有人用,你用来损害谁呢?正常的坏蛋这个时候瞄准的肯定是各大APP市场上面下载率比较高的,排名比较高的APP.比如说1000个,检测一下这些个APP的安全性,然后提取出出身干净的APP的签名.构建一个APP的数据库,当检查到签名不一致的时候我们就认定这个APP是重打包的.
我们之前有提过一点它的缺点, Android的开发更新换代实在是太快了,你只要交25美金你就可以往市场上上传你开发出来的APP,面向大众的低门槛开发环境使得APP的增长是光速级别的.三十年河东,三十年河西.今天了流行愤怒的小鸟,明天流行开心消消乐,后天又是什么what's up?这样的一些因素就使得这样的一种检测方式存在了一些缺陷.再加上另一方面,各个市场的审查机制不严格.重打包就成了Android的APP市场的重灾区.
那是不是我写的这种方式就很好了呢,当然不可能了.只是换个方法思考问题罢了.这个方法要解决的问题是什么呢,在大量的样本中找到可以的重打包.因此,要做的事情就是在大批的样本中找相似.
既然要找相似,那么我们就需要提取出这些样本的特征,根据这些特征来判断出大量样本的相似性.把大量的没有标记的东西,根据他们的相似性归为一类,这里我们会要用到聚类算法.
看到聚类算法,这是一个机器学习的概念,在机器学习中有分类算法和聚类算法这两种算法,分类算法是有标签的算法,聚类算法是无标签的算法.说完好像是废话.如果你已经知道一些分类,这个时候有一个样本,可能属于其中一类,你要把这个样本正确的分类这个问题就是分类问题.一堆样本,根据他们的相似性来分类,你不知道可能会分出多少,最后根据某个标准把他们都归类了,那么这个问题就是聚类问题.
原先我们分析的那一种方法,比如说1000个不同的样本,这时候来一个样本,他们拥有相同的包名,这个时候判断签名来做归类.那这里应该是属于分类问题.
首先,先从不同的Android应用市场上爬取大量的APP作为我们的实验数据集.之后找出存在加固的APP,脱壳之后在做后续的处理.
我们使用apktool对APP进行反编译,之后我们会的到一个res文件夹,这个里面存放的就是我们APP使用到的大量资源,对其进行分析处理,提取出对我们有用信息.我们在这里要进行特征提取,这些信息将在后续作为我们分类的条件,最后帮我们找出可疑的重打包对. 特征的提取分为两步,一个是统计特征的提取,另一个是结构特征的提取. 根据统计特征我们找出含有相近资源数量的APP,最后根据APP的结构特征缩小我们根据统计特征得到的结果.
在前面的章节中我们已经说过资源的概念,一个button算资源,一个activity, receiver, service这些都算资源,一张图片是资源,xml 文件是资源,字符串是资源,每个控件的id是资源,整型变量是资源,文件夹是资源.一个intent-filter,权限,布局文件,用到的颜色这些都是归一个APP所有,所以这些都是资源. 我们将这些资源按照类别归类,统计出他们之间的个数,把他们的特征值作为我们判别的第一个标准,之后在根据 每一个的结构特征来做细化判别.找出我们的疑似重打包对.
聊聊资源
既然要分析资源,我们先来看看一个Android的APP中的资源是些什么.
下图是APK格式的文件用apktool 反编译之后得出的res文件,我们APP用到的资源文件都在这里,要从资源入手,我们就要对资源有一个透彻的认识
图 1
这图片是随便选取的,不同的APP的资源文件可能会有一些差别.当然还有像下面这位大哥这样的:
图 2
麻雀虽小但是五脏俱全,我们就用图1中的资源文件来说事
1. anim
anim 是animation动画这个单词的缩写.这个文件定义的是一些特殊的动画效果.比如说你在玩手机的时候,有没有发现一些特效,页面之间的切换效果,是平滑的消失还是淡出淡入,是旋转的出现还是消失. 在没有概念,玩过PPT么.做幻灯片的时候出现的切换的动画,这个文件夹的文件就负责定义这些内容.这个文件夹不是一定要存在的,也不是我们程序分析的对象,你只要知道有这么个东西就可以了
2.color
这个文件夹里定义的不是这个APP中用到的颜色,而往往是某个控件被选中之后一些微妙的颜色变化.比如说点击按钮之后这个按钮的颜色变化,某个输入框说的地道一点叫本文框,这些控件的颜色的变化定义全部都在这个文件夹里定义的.
亲们,开发个APP不容易啊,尤其是要开发那种动画体验好,用起来让你感觉效果又酷又帅的APP,往往是一个团队开发的,UI设计,动画设计,代码不同部分的功能总是一波一波的人来共同完成的. 我觉得开发的动画又搞笑又好的UC浏览器啊.玩手机的时候记得在心里默默感激一下这些程序猿同志们啊.不过您也别太沉迷了,做个地铁无聊打发打发玩玩使可以的,别把自己的孩子丢地铁站就行了.
打个岔,有一次和闺蜜一起去吃饭,我们好久没见了,聊得特别欢乐.这个时候一家三口进来了,正好坐在我们旁边的桌子.从点菜到吃饭到离开,一家三口之间相互交流的话不超过3句,全程一家人都在低着头玩手机.小孩子真的不超过4岁,然后也拿着手机目不转睛的看.我们两个人当时真的是惊呆了,生活一定要像这个样子么?其实这事不新鲜,到处都可以看见, 像这样的人不在少数,而且越来越多. 作为一个程序猿, 我看到这个状况很痛心啊.非常痛心 难道一家人吃饭的时候有说有笑,其乐融融不是最快乐最简单幸福的事情么?我们可以为您开发出炫酷的手机软件但是并不是意味着我们需要大家沉迷于此.金星说的有句话挺好的:一个民族要强大,总要多一些仰望星空的人,少一些低头玩手机的人.这话讲得有些大,但是被手机支配的人生难道不可悲么. 一秒秒钟变愤青了.接着回正题
3.drawable*
这个里面有什么?图片呗. 但是,为什么有这么多drawable开头的文件夹呢.亲们,Android手机的型号有这么多,大小有这么多.除了手机,像Android系统的PAD也很多的,他们的屏幕大小尺寸是不一样的.为了满足尺寸屏幕的分辨率,所以就有这么多的不同分辨率的图片了.android系统会根据屏幕的尺寸自动选择合适的图片加载出来.所以android系统上的软件手机端和PAD是通用的. IOS的上面的大部分软件可就不是这样的, iPAD上面的软件有部分软件和iphone是不可用,用户体验也不一样.主力军大部分在iphone软件上的APP开发.为什么要这样呢,同一个软件买两次,赚钱呗. 当然了layout布局文件也是如此的.
4.layout(重点)
layout布局文件.这个文件不是所有APP都有的.这个文件夹里面的内容我们以后还要细细分析.
在Android应用开发的一项重要内容就是炫酷的界面,就算不炫酷也要让用户觉得玩的爽,用的方便.在Android中有两种方式来定义用户界面.
- 一种就是MVC机制,通过定义一个XML布局文件来定义用户界面
- 一种就是在java程序代码中通过调用方法进行控制
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout android:paddingLeft="?android:expandableListPreferredItemPaddingLeft" android:paddingTop="2.0dip" android:paddingBottom="2.0dip" android:layout_width="wrap_content" android:layout_height="wrap_content"
xmlns:android="http://schemas.android.com/apk/res/android">
<TextView android:textAppearance="?android:textAppearanceLarge" android:id="@*android:id/text1" android:layout_width="fill_parent" android:layout_height="wrap_content" android:layout_marginTop="6.0dip" />
<TextView android:textAppearance="?android:textAppearanceSmall" android:id="@*android:id/text2" android:layout_width="fill_parent" android:layout_height="wrap_content" android:layout_below="@*android:id/text1" android:layout_alignLeft="@*android:id/text1" />
</RelativeLayout>
在这里的TextView我们把它叫做一个控件.我们可以通过该UI组件指定android:id属性, 该属性的属性值代表该组件的唯一标识.在java代码中我们通过findViewById(R.id.android.id属性值来访问它)
当然,加载控件和布局文件的方式绝对不止这两种.以后的文章还会细细来讲解这部分,恩,那个是这个系统的大招,绝对的大招,当然我也是写了两个星期才完成的.不过需要您对java非常熟悉,尤其是各种数据结构,否则看起代码可能会比较吃力.
****在代码中控制UI界面*****
Android中推荐使用XML布局文件来控制UI界面,但是在Android中是完全支持开发者想开发Swing应用一样,完全抛弃XML文件布局的.
注: 以上代码来自李阳的<<疯狂Android讲义>>
5. values
在values这个文件夹中包含了一些文件.我们来仔细的分析一下他们:
5.1. dimens.xml 文件这个文件定义了一些控件尺寸的大小
</pre><p></p><p><pre name="code" class="html"><?xml version="1.0" encoding="utf-8"?>
<resources>
<dimen name="textview_height">25dp</dimen>
<dimen name="textview_width">150dp</dimen>
<dimen name="ball_radius">30dp</dimen>
<dimen name="font_size">16sp</dimen>
</resources>
当我们希望控制这个APP要显示的字体大小的尺寸的时候我们可以调用以下的代码来获取一个dimension
Resources res = getResources();
float fontSize = res.getDimension(R.dimen.font_size);
当一个layout的布局文件要使用这个dimensions的属性的时候我们可以使用如下的代码调用来实现:
<TextView
android:layout_height="@dimen/textview_height"
android:layout_width="@dimen/textview_width"
android:textSize="@dimen/font_size"/>
这样我们就根据dimens定义的大小来确定了我们这个TextView控件的尺寸
具体的例子和详细的分析你可以参考这篇文章android中使用dimen定义尺寸
5.2.在colors.xml
这个文件定义了各种颜色的值
5.3 strings.xml 文件定义了使用到的字符串的常量
我们可以发现有个时候在资源文件夹里面有很多以values开头的文件夹,这些文件夹中主要变换的东西就是他们的字符串常量.开发者在实现同一个功能,比如说按钮上面的字的时候,需要这个APP支持不同的语言,这个时候Android就可以通过下面这种方式下面代码的例子实现出来
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="me">Me</string>
<string name="draft">Draft</string>
<string name="drafts">Drafts</string>
</resources>
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="me">我</string>
<string name="draft">草稿</string>
<string name="drafts">草稿</string>
</resources>
通过这样的一个设计使得Android的APP可以支持不同的语言版本.
5.4 ids.xml
在这个文件中我们定义的是唯一的资源的ID.
一般的使用如下:
<?xml version="1.0" encoding="utf-8"?>
<resources>
<item type="id" name="button_ok" />
<item type="id" name="dialog_exit" />
</resources>
这个时候我们如果在我们的布局文件layout中定义了一个控件Button,当我们需要给这个控件赋值一个id的时候我们就可以使用下面的代码
<Button android:id="@id/button_ok"
style="@style/button_style" />
同志们,注意哦,在这里我们发现id前面是没有一个+号的,因为这个时候这个id是已经定义在ids.xml文件当中的,如果我们使用android:id="@+id/name" 这个时候意味这个id并没有存在我们要使用它的时候必须要先创建它这个时候我们就可以使用这个方式来之间在我们的布局文件中创建一个按钮在给它赋值而不需要在ids.xml文件当中在申明.因为这样书写之后,我们这个控件的id会被自动加到R.java文件这类当中
5.5 public.xml 文件
在说明之前, 我们先来对比一下ids.xml 和public.xml 文件这两个文件当中内容
<?xml version="1.0" encoding="utf-8"?>
<resources>
<public type="attr" name="absListViewStyle" id="0x7f010000" />
<public type="attr" name="direction" id="0x7f010001" />
<public type="attr" name="defaultScreen" id="0x7f010002" />
<public type="attr" name="cellWidth" id="0x7f010003" />
<public type="attr" name="cellHeight" id="0x7f010004" />
<public type="attr" name="longAxisStartPadding" id="0x7f010005" />
<public type="attr" name="longAxisEndPadding" id="0x7f010006" />
<public type="attr" name="shortAxisStartPadding" id="0x7f010007" />
<public type="attr" name="shortAxisEndPadding" id="0x7f010008" />
<public type="attr" name="shortAxisCells" id="0x7f010009" />
<public type="attr" name="longAxisCells" id="0x7f01000a" />
<public type="attr" name="isPortrait" id="0x7f01000b" />
<public type="attr" name="texture" id="0x7f01000c" />
<public type="attr" name="landscape" id="0x7f01000d" />
<public type="attr" name="position" id="0x7f01000e" />
<public type="attr" name="className" id="0x7f01000f" />
<public type="attr" name="packageName" id="0x7f010010" />
<public type="attr" name="screen" id="0x7f010011" />
<public type="attr" name="x" id="0x7f010012" />
<public type="attr" name="y" id="0x7f010013" />
<public type="attr" name="icon" id="0x7f010014" />
<public type="attr" name="title" id="0x7f010015" />
<public type="attr" name="uri" id="0x7f010016" />
<public type="drawable" name="add_button" id="0x7f020000" />
<public type="drawable" name="all_apps_button" id="0x7f020002" />
<public type="drawable" name="all_apps_icon" id="0x7f020004" />
<public type="drawable" name="box_launcher_bottom_old" id="0x7f020009" />
<public type="drawable" name="box_launcher_top" id="0x7f02000a" />
<public type="drawable" name="browser_button" id="0x7f02000e" />
<public type="drawable" name="btn_search_dialog_voice" id="0x7f020010" />
<public type="drawable" name="calendar_button" id="0x7f020015" />
<public type="drawable" name="camera_button" id="0x7f020017" />
<public type="drawable" name="contacts_button" id="0x7f020019" />
<public type="drawable" name="delete_zone_selector" id="0x7f02001b" />
<public type="drawable" name="dots_left_1_6" id="0x7f020023" />
<public type="drawable" name="dots_left_1_7" id="0x7f020025" />
<public type="drawable" name="dots_left_2_6" id="0x7f020027" />
<public type="drawable" name="dots_left_2_7" id="0x7f020029" />
<public type="drawable" name="dots_left_3_6" id="0x7f02002c" />
<public type="drawable" name="dots_left_3_7" id="0x7f02002e" />
<public type="drawable" name="dots_left_4_6" id="0x7f020030" />
<public type="drawable" name="dots_left_4_7" id="0x7f020033" />
<public type="drawable" name="dots_left_5_6" id="0x7f020035" />
<public type="drawable" name="dots_left_5_7" id="0x7f020037" />
<public type="drawable" name="dots_left_6" id="0x7f020039" />
<public type="drawable" name="dots_left_6_7" id="0x7f02003a" />
<public type="drawable" name="dots_left_7" id="0x7f02003c" />
<public type="drawable" name="dots_right_1_6" id="0x7f02003d" />
<public type="drawable" name="dots_right_1_7" id="0x7f02003f" />
<public type="drawable" name="dots_right_2_6" id="0x7f020041" />
<public type="drawable" name="dots_right_2_7" id="0x7f020043" />
<public type="drawable" name="dots_right_3_6" id="0x7f020046" />
<public type="drawable" name="dots_right_3_7" id="0x7f020048" />
<public type="drawable" name="dots_right_4_6" id="0x7f02004a" />
<public type="drawable" name="dots_right_4_7" id="0x7f02004c" />
<public type="drawable" name="dots_right_5_6" id="0x7f02004e" />
<public type="drawable" name="dots_right_5_7" id="0x7f020050" />
<public type="drawable" name="dots_right_6" id="0x7f020052" />
<public type="drawable" name="dots_right_6_7" id="0x7f020053" />
<public type="drawable" name="dots_right_7" id="0x7f020055" />
<public type="drawable" name="drawer_bottom_bg" id="0x7f020056" />
<public type="drawable" name="email_button" id="0x7f020058" />
<public type="drawable" name="facebook_button" id="0x7f02005a" />
<public type="drawable" name="facebook_icon" id="0x7f02005c" />
<public type="drawable" name="gmail_button" id="0x7f020062" />
<public type="drawable" name="grid_selector" id="0x7f020065" />
<public type="drawable" name="home_button" id="0x7f020066" />
<public type="drawable" name="list_selector_background" id="0x7f02007b" />
<public type="drawable" name="list_selector_background_transition" id="0x7f020080" />
<public type="drawable" name="maps_button" id="0x7f020081" />
<public type="drawable" name="market_button" id="0x7f020083" />
<public type="drawable" name="music_button" id="0x7f020086" />
<public type="drawable" name="navigation_button" id="0x7f020088" />
<public type="drawable" name="phone_button" id="0x7f02008a" />
<public type="drawable" name="pressed_application_background" id="0x7f020090" />
<public type="drawable" name="shortcut_selector" id="0x7f020096" />
<public type="drawable" name="sms_button" id="0x7f020097" />
<public type="drawable" name="talk_button" id="0x7f020099" />
<public type="drawable" name="textfield_searchwidget" id="0x7f02009b" />
<public type="drawable" name="twitter_button" id="0x7f0200a2" />
<public type="drawable" name="voice_button" id="0x7f0200a4" />
<public type="drawable" name="widget_calendar_add_button" id="0x7f0200b0" />
<public type="drawable" name="widget_calendar_agenda_button" id="0x7f0200b4" />
<public type="drawable" name="widget_calendar_calendar_button" id="0x7f0200b8" />
<public type="drawable" name="widget_calendar_grid_day" id="0x7f0200be" />
<public type="drawable" name="widget_calendar_grid_today" id="0x7f0200c0" />
<public type="drawable" name="widget_chooser_middle_selector" id="0x7f0200c8" />
<public type="drawable" name="widget_chooser_next_selector" id="0x7f0200cc" />
<public type="drawable" name="widget_chooser_previous_selector" id="0x7f0200d0" />
<public type="drawable" name="widget_facebook_newsfeed_button" id="0x7f0200d2" />
<public type="drawable" name="widget_facebook_wall_button" id="0x7f0200d3" />
<public type="drawable" name="widget_footer_bg" id="0x7f0200d6" />
<public type="drawable" name="widget_friends_newsfeed_button" id="0x7f0200dc" />
<public type="drawable" name="widget_friends_wall_button" id="0x7f0200de" />
<public type="drawable" name="widget_selector" id="0x7f0200ea" />
<public type="drawable" name="widget_sms_card_delete_button" id="0x7f0200ec" />
<public type="drawable" name="widget_sms_card_reply_button" id="0x7f0200f1" />
<public type="drawable" name="widget_sms_compose_button" id="0x7f0200f5" />
<public type="drawable" name="widget_sms_mark_button" id="0x7f0200fa" />
<public type="drawable" name="widget_twitter_dm_button" id="0x7f020102" />
<public type="drawable" name="widget_twitter_mentions_button" id="0x7f020105" />
<public type="drawable" name="widget_twitter_timeline_button" id="0x7f020109" />
<public type="drawable" name="widget_white_selector" id="0x7f02010c" />
<public type="drawable" name="dock_background_froyo" id="0x7f02001c" />
<public type="drawable" name="dock_background_froyo_wide" id="0x7f02001d" />
<public type="drawable" name="dock_background_glass" id="0x7f02001e" />
<public type="drawable" name="all_apps_button_normal" id="0x7f020003" />
<public type="drawable" name="bg_appwidget_error" id="0x7f020006" />
<public type="drawable" name="box_launcher_bottom" id="0x7f020008" />
<public type="drawable" name="box_launcher_top_normal" id="0x7f02000b" />
<public type="drawable" name="box_launcher_top_pressed" id="0x7f02000c" />
<public type="drawable" name="box_launcher_top_selected" id="0x7f02000d" />
<public type="drawable" name="focused_application_background" id="0x7f02005e" />
<public type="drawable" name="message_header" id="0x7f020085" />
<public type="drawable" name="placeholder_google" id="0x7f02008c" />
<public type="drawable" name="search_button_bg" id="0x7f020093" />
<public type="drawable" name="search_button_voice" id="0x7f020094" />
<public type="drawable" name="search_floater" id="0x7f020095" />
<public type="drawable" name="textfield_searchwidget_default" id="0x7f02009c" />
<public type="drawable" name="textfield_searchwidget_pressed" id="0x7f02009d" />
<public type="drawable" name="textfield_searchwidget_selected" id="0x7f02009e" />
<public type="drawable" name="wallpaper_dark" id="0x7f0200a6" />
<public type="drawable" name="wallpaper_dark_small" id="0x7f0200a7" />
<public type="drawable" name="wallpaper_rainbokeh" id="0x7f0200a8" />
<public type="drawable" name="wallpaper_rainbokeh_small" id="0x7f0200a9" />
<public type="drawable" name="widget_bookmark_nothumbnail" id="0x7f0200ab" />
<public type="drawable" name="widget_people_unknown_contact" id="0x7f0200e8" />
<public type="drawable" name="add_button_normal" id="0x7f020001" />
<public type="drawable" name="appwidget_bg" id="0x7f020005" />
<public type="drawable" name="bookmarks_button_normal" id="0x7f020007" />
<public type="drawable" name="browser_button_normal" id="0x7f02000f" />
<public type="drawable" name="btn_search_dialog_voice_default" id="0x7f020011" />
<public type="drawable" name="btn_search_dialog_voice_pressed" id="0x7f020012" />
<public type="drawable" name="btn_search_dialog_voice_selected" id="0x7f020013" />
<public type="drawable" name="calendar_agenda_day_background" id="0x7f020014" />
<public type="drawable" name="calendar_button_normal" id="0x7f020016" />
<public type="drawable" name="camera_button_normal" id="0x7f020018" />
<public type="drawable" name="contacts_button_normal" id="0x7f02001a" />
<public type="drawable" name="dots_left_2_7_pressed" id="0x7f02002b" />
<public type="drawable" name="dots_left_4_6_pressed" id="0x7f020032" />
<public type="drawable" name="dots_right_2_7_pressed" id="0x7f020045" />
<public type="drawable" name="drawer_fade" id="0x7f020057" />
<public type="drawable" name="email_button_normal" id="0x7f020059" />
<public type="drawable" name="facebook_button_normal" id="0x7f02005b" />
<public type="drawable" name="facebook_widget_like_icon" id="0x7f02005d" />
<public type="drawable" name="friends_button" id="0x7f02005f" />
<public type="drawable" name="friends_widget_facebook_logo_big" id="0x7f020060" />
<public type="drawable" name="friends_widget_twitter_logo_big" id="0x7f020061" />
<public type="drawable" name="gmail_button_normal" id="0x7f020063" />
<public type="drawable" name="gmail_widget_message_header" id="0x7f020064" />
<public type="drawable" name="home_button_focused" id="0x7f020067" />
<public type="drawable" name="home_button_normal" id="0x7f020068" />
<public type="drawable" name="home_button_pressed" id="0x7f020069" />
<public type="drawable" name="ic_btn_speak_now" id="0x7f02006a" />
<public type="drawable" name="ic_launcher_add_folder" id="0x7f02006b" />
<public type="drawable" name="ic_launcher_application" id="0x7f02006c" />
<public type="drawable" name="ic_launcher_appwidget" id="0x7f02006d" />
<public type="drawable" name="ic_launcher_blank" id="0x7f02006e" />
<public type="drawable" name="ic_launcher_folder" id="0x7f02006f" />
<public type="drawable" name="ic_launcher_folder_live" id="0x7f020070" />
<public type="drawable" name="ic_launcher_folder_open" id=&#