很多人写文章,喜欢把什么行业现状啊,研究现状啊什么的写了一大通,感觉好像在写毕业论文似的,我这不废话,先直接上几个图,感受一下。
第二张图是微信运动步数作弊,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
Apk 的核心逻辑主要在 classes.dex 中,破解和二次打包也基本上对这个文件做手脚,所以对这个文件的保护也尤为重要。
我们首先用 apktool 工具反编译:java -jar apktool.jar d -f xxx.apk outDir(PS:outDir 不写会在当前目录输出)。
反编译后的目录结构如下:
这里,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。
可以参看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。
我们看一下,反编译后的关键代码:
我们可以把第一个红框位置的 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 会做一些盗版检测机制,就是为了防止二次重打包。
以手机XX应用为例,当你按照上述步骤反编译,重新编译,签名之后,进入 APP 会出现这个页面,无法正常使用。
因为你并没有这个 APP 的正版签名文件(关于签名相关的东西,在后面我再仔细讲)。
那么这个原理是什么呢,我们大胆猜测一下,无非就是和上一个例子类似的check函数,两个值的对比,那么这个值一定是签名。
我们先通过方法拿到正版的签名md5,然后在反编译后的代码中搜索一下这个值。
然而并没有搜到,再换个思路,我们搜索获取签名的这个函数,从而定位关键代码,获取应用签名的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 程序(连载二)