一、内容的由来
最近做了一些反编译的工作,对反编译的理解从模糊到入门,再到感到敬畏。到现在我竟然不确定我是在门外还是在门内,但我对这件事感到兴趣浓厚,所以准备写几篇入门文章记录一下,也顺便梳理一下最近做的事情。
二、反编译的目的
- 学习对方的框架、研究实现逻辑
- 找到想要的数据,爬对方的数据
- hook特殊的方法,进行app的功能拓展
- 快速熟悉新工程,找到对应的Activity或方法调用栈
- 研究对方的加固及加密方案,提高自身的安全性等级
三、需要准备的工具
1、apk-tools
主要作用:
- 将apk包解开,查看资源文件、manifest文件等
- 将解开的apk修改内容后再进行打包,此时需要加一步签名apk
下载地址:https://ibotpeaches.github.io/Apktool/
2、d2j-dex2jar
主要作用:将dex文件翻译为jar文件,其中会有smali文件转成.class文件的过程
下载地址:https://github.com/pxb1988/dex2jar
3、JD-GUI
主要作用:查看dex2jar生成的jar文件的内容,查找需要的代码逻辑
下载地址:https://github.com/java-decompiler/jd-gui
4、Xposed
主要作用:hook住对应方法。通过动态代理或者反射调用来实现自己想做的事情。这里classloader的获取当然是最关键的。
下载地址:https://forum.xda-developers.com/showthread.php?t=3034811
注意事项:一定要找到手机对应版本的apk,否则是不能运行的
四、做些有意思的事情
1、简单的事:打开某个APP的LOG开关?
*为了避免不必要的麻烦,我随机选了一个APP,并全程打码,只是示意,没有恶意。
主要步骤:
1、通过apk-tools确定包名等相关信息。
命令为:java -jar apktool_2.4.0.jar d xxx.apk
结果图:
打开AndroidManifest.xml,查看其中内容:
轻松得到包名和主入口之类的东西。
在<Application>标签里面会有android:debuggable的属性值,可以修改为true,然后进行重新打包。就相当于打开的debuggable的开关。
重新打包的命令为:
java -jar apktool_2.4.0.jar b 需要编译的文件夹名 -o 输出的对应apk文件名(xxx.apk)
此时就生成了一个没有签名的,debuggable是true的apk包了。因为没有签名所以安装不上,接下来就需要给apk签名。
命令为:
jarsigner -verbose -sigalg SHA1withRSA -digestalg SHA1 -keystore keystore文件 -storepass 密码 对应的apk(xxx.apk) key名(key0)
然后装机运行,如果没有sign验证的apk现在你已经成功打开debug开关了,不过一般是不行的。?
我使用apktools一般就只是进行包名和结构的查看...
2、刚才的apk我们通过dex2jar和JD-GUI进行查看,找到LOG的管理类
(1)解压apk文件,找到对应的dex文件
(2)用dex2jar将dex文件反编为jar
命令为:
sh d2j-dex2jar.sh dex文件的路径
生成出来一个dex.jar文件
用JD-GUI打开对应的jar文件,这时会两种情况。
- 加固
- 未加固
现在先只讨论未加固状态的输出,加固的在之后介绍。
3、接下来就是看源码咯~
这时候你可能需要的一些工具,我基本都是自己用Xposed写的工具,主要有:
(1)查看Activity、Fragment的调用栈(当然有些人喜欢看方法的调用栈,但是我觉得有点乱...)
(2)网络请求的抓包工具
(3)OkHttp的LoggingInterceptor的HOOK
还有一些你需要知道的指令知识,因为JD-GUI并不一定能都给你翻译的明明白白(有内部类,内部类又不在同一个dex包中时就不会给你翻译),掌握一点指令知识也是应该的,你主要需要的指令有:
aload_0 | 将this压入栈,每个当前类方法调用前都得压入一个this才能调用 |
aload_1 | 将位置为1的对象引用局部变量压入栈 |
astore_1 | 从栈中弹出对象引用,然后将其存到位置为1的局部变量中 |
… | … |
其他的 | 猜一下,猜不出来查一下 |
然后举个例子:
// 34: aload_3
// 35: aload_1
// 36: invokevirtual handleState : (Lcom/package/bean/Message;)V
这个意思就是aload_3出来的对象的handleState方法,参数是aload_1的内容,返回值是个com/package/bean/Message。然后找对应的astore_3是什么类的对象就可以看懂了。
这不是smali的指令,smali的指令是这样的
.local v0, args:Landroid/os/Message;
const/4 v1, 0x12
iput v1, v0, Landroid/os/Message;->what:I
相当于:args.what = 18;
4、这时候找到了对应的LOGGER文件了,查看一下逻辑,然后看看打开开关需要把什么参数给改掉,例如enable啥的
5、Xposed登场,进行hook,修改enable的值
这一步内容比较多,在下一篇文章中进行详细介绍吧~