手把手教你逆向分析 Android 程序(连载一)

手把手教你逆向分析 Android 程序(连载一)_第1张图片

很多人写文章,喜欢把什么行业现状啊,研究现状啊什么的写了一大通,感觉好像在写毕业论文似的,我这不废话,先直接上几个图,感受一下。

手把手教你逆向分析 Android 程序(连载一)_第2张图片
第一张图是在把代码注入到地图里面,启动首页的时候弹出个浮窗,下载网络的图片,苍老师你们不会不认识吧?

第二张图是微信运动步数作弊,6不6?

ok,那我们从头说起……

1.反编译

Android 的反编译,相信大家都应该有所了解,apktool、JEB 等工具。

我们先看一下 Apk 文件的结构吧,如下图:

1.META-INF:签名文件(这个是如何生成的后面会提到)。

2.res:资源文件,里面的 xml 格式文件在编译过程中由文本格式转化为二进制的 AXML 文件格式。

3.AndroidManifest.xml:Android 配置文件,编译过程依然被转换为 AXML 格式。

4.classes.dex:java 代码编译后产生的类似字节码的文件(dalvik 字节码)。

5.resources.arsc:具有 id 值资源的索引表(asserts 文件夹中的资源不会生成索引)。

6.其他文件:可由开发者自己添加,诸如 assets 等,或者 lib(native so 代码)等目录。

(Android 编译打包过程分析参看:http://blog.csdn.net/luoshengyang/article/details/8744683


手把手教你逆向分析 Android 程序(连载一)_第3张图片

Apk 的核心逻辑主要在 classes.dex 中,破解和二次打包也基本上对这个文件做手脚,所以对这个文件的保护也尤为重要。


手把手教你逆向分析 Android 程序(连载一)_第4张图片
上图为一般 Apk 的破解过程(windows 画图工具画的比较搓)。

我们首先用 apktool 工具反编译:java -jar apktool.jar d -f xxx.apk outDir(PS:outDir 不写会在当前目录输出)。

反编译后的目录结构如下:


手把手教你逆向分析 Android 程序(连载一)_第5张图片

这里,res 里的 xml 和 manifset.xml 都已经是解出后的 xml 了,不是 axml 格式了,res 目录里的 values 目录下的 public.xml 可以看到资源对应的 id。

如果命令 java -jar apktool.jar d -f再加入 -r 代表资源文件不反编译,上图的目录中将依然有resources.arsc,xml 都是 axml 格式的,也找不到 public.xml。

其实我们主要关注的是 smali 这个目录,里面是按照 android 程序编写的时候 java 文件的目录格式生成的,但是里面的文件并不是 java 格式的,而是 smali 格式的,类似 MainActivity.smali。

那么什么是 smali 文件呢?

1.Smali 是 Android 的 Dalvik 虚拟机所使用的一种 dex 格式的中间语言。

2.可以理解为,C 语言和汇编语言的编译与反编译,把 smali 理解为一种汇编语言。

我们可以打开一个 smali 文件看看,我们可以使用 notepad++ 打开,然后定一下 smali 语法的高亮显示。

将下面内容保存到 C:\Users\用户名\AppData\Roaming\Notepad++下,文件名为 userDefineLang.xml。


手把手教你逆向分析 Android 程序(连载一)_第6张图片

可以参看http://www.ourunix.org/post/117.html操作。打开 MainActivity.smali 文件,头三行代码大致如下:

[C]纯文本查看复制代码

?

1

2

3.classpublicLcom/example/hacktest/MainActivity;

.super Landroid/app/Activity;

.source"MainActivity.java"

smali 语法这里就不介绍了,自己查资料就好 smali 文件语法参考:http://my.oschina.net/xiahuawuyu/blog/57146

这里举个例子,我们写个程序,一个 edittext 一个 button,当 edit 里面输入正确的文字的时候,点击 button 才会弹出正确的 toast。

我们看一下,反编译后的关键代码:


手把手教你逆向分析 Android 程序(连载一)_第7张图片
可以看到这是一个参数为 string,返回值为 boolean 名叫 check 的函数,当输入为“11”的时候才返回 true。

我们可以把第一个红框位置的 if-eqz 改成 if-nez,这样你输入除了11的任何字符都会返回 true。

或者把第二个红框位置的 0x1,改成 0x0,(0代表 true),这样这个函数不管输入什么都返回 true。

OK,这样我们就改完了,我们重新编译:java -jar apktool.jar b -f outDir xxx.apk(PS:xxx.apk 可以不写,会在 outDir 里生成 dist 目录,编译好的 Apk 在这里面)。

签名:可以网上下载工具 autoSign,使用方法略…


安装 Apk 后验证,通过。

但是事情并不总是如我们所愿,有些 Apk 会做一些盗版检测机制,就是为了防止二次重打包。

以手机XX应用为例,当你按照上述步骤反编译,重新编译,签名之后,进入 APP 会出现这个页面,无法正常使用。

因为你并没有这个 APP 的正版签名文件(关于签名相关的东西,在后面我再仔细讲)。


手把手教你逆向分析 Android 程序(连载一)_第8张图片

那么这个原理是什么呢,我们大胆猜测一下,无非就是和上一个例子类似的check函数,两个值的对比,那么这个值一定是签名。

我们先通过方法拿到正版的签名md5,然后在反编译后的代码中搜索一下这个值。


手把手教你逆向分析 Android 程序(连载一)_第9张图片

然而并没有搜到,再换个思路,我们搜索获取签名的这个函数,从而定位关键代码,获取应用签名的java代码类似是:

[Java]纯文本查看复制代码

?

1

2

3PackageInfo pi = context.getPackageManager.().getPackageInfo(packname,packageManager.GET_SIGNATURES);

对应的smali代码类似是:

Landroid/content/pm/PackageInfo;->signatures:[Landroid/content/pm/Signature

我们再搜用这段代码搜索,在 StormUtils2.smali 里面找到了,发现在函数 getSignInfo 里面,继续跟踪到 checkPiracy 函数。

看到这个函数发现就和上例中的 check 函数类似了,改一下返回值为 true 就好了。

我们再仔细看看这个函数,发现关键的签名 md5 值被拆开存放了,所以我们才没有搜到,这也是防范搜索的一个举措吧(虽然我觉得并没什么用)。

[Java]纯文本查看复制代码

?

1

2const-string/jumbo v3,"dbbf****96b326003"

const-string/jumbo v0,"c388a****1578d5"

好的,修改后,我们再重新编译、签名,验证通过。

(PS:关于签名检测的除了 java 层的,可能还有再 so 里面校验的和服务器验证的方式,在 so 里的用 IDA 打开 so 跟踪修改,服务器验证的抓包查看,再模拟发包重放攻击就好了,这里就不具体介绍了)

未完待续。。。。。。。


更多内容相关内容请阅读:手把手教你逆向分析 Android 程序(连载二)

你可能感兴趣的:(手把手教你逆向分析 Android 程序(连载一))