- 对本书的赞誉
- 前言
- 基础篇
- 第 1 章 Android 中锁屏密码加密算法分析
- 第 2 章 Android 中 NDK 开发
- 第 3 章 Android 中开发与逆向常用命令总结
- 第 4 章 so 文件格式解析
- 第 5 章 AndroidManifest.xml 文件格式解析
- 第 6 章 resource.arsc 文件格式解析
- 第 7 章 dex 文件格式解析
- 防护篇
- 第 8 章 Android 应用安全防护的基本策略
- 第 9 章 Android 中常用权限分析
- 第 10 章 Android 中的 run-as 命令
- 第 11 章 Android 中的 allowBackup 属性
- 第 12 章 Android 中的签名机制
- 第 13 章 Android 应用加固原理
- 第 14 章 Android 中的 so 加固原理
- 工具篇
- 第 15 章 Android 逆向分析基础
- 第 16 章 反编译神器 apktool 和 Jadx
- 第 17 章 Hook 神器 Xposed
- 第 18 章 脱壳神器 ZjDroid
- 第 19 章 Native 层 Hook 神器 Cydia Substrate
- 操作篇
- 第 20 章 静态方式逆向应用
- 第 21 章 动态调试 smali 源码
- 第 22 章 IDA 工具调试 so 源码
- 第 23 章 逆向加固应用
- 第 24 章 逆向应用经典案例分析
- 第 25 章 Android 中常见漏洞分析
- 第 26 章 文件加密病毒 Wannacry 样本分析
20.5 案例分析
本节通过一个例子来看看如何使用静态分析技术进行破解。
20.5.1 静态分析 smali 代码
首先拿到需要破解的 apk,使用 apktool.jar 工具来反编译:
这个 apk 很容易就被反编译了,看来并没有进行任何的加固,那就好办了。这里改一下它的 AndroidManifest.xml 中的信息,改成可调式模式,这是后面进行动态调试的基础,当然也可以不用修改,在之前章节介绍了如何修改系统的调试总开关,如果把系统的调试总开关打开,这里就不用修改了。一个正式的 apk 在 AndroidManifest.xml 中这个值是 false 的。看看它的 AndroidManifest.xml 文件,如下所示:
把这个值改成 true,再回编译,这时候就可以动态调试 apk 了。所以在这点上可以看到,静态分析是动态分析的前提,这个值不修改的话,是没有办法进行后续的动态调试的。修改成功之后,进行回编译:
这里是为了简化内容,写了一个批处理,首先进入到目录,然后使用命令进行回编译:
sq 是之前反编译的目录,debug.apk 是回编译之后的文件,这时,debug.apk 是不能安装运行的,因为没有签名,Android 中是不允许安装一个没有签名的 apk。
下面还要继续签名,用系统自带的签名文件即可签名:
后面就直接安装这个 apk,然后运行 apk。这个过程中只需要知道应用的包名和入口 Activity 名称即可,这个信息在 AndroidManifest.xml 中也是可以获取到的,当然可以使用如下命令得到:
回编译之后,运行程序,发现有问题,即点击程序的 icon 没反应,运行不起来。查看 log 中的异常信息,发现也没有抛出任何异常,那么这时就可以判断,它内部肯定做了什么校验工作。校验方式一般有两种:
·对 dex 做校验,防止修改 dex。
·对 apk 的签名做校验,防止重新打包。
这需要重新看看它的代码,看是否做了校验。在分析代码的时候,要先看看它有没有自己定义 Application,如果有定义的话,就需要看它自己的 Application 类,这里看到它定了自己的 Application:com.shuqi.application.ShuqiApplication。
解压 apk,得到 dex,然后用 dex2jar 进行转化,得到 jar,再用 jd-gui 查看这个类,如图 20-6 所示。
图 20-6 jd-gui 查看源码
这里看到它的代码做混淆了,但是一些系统回调方法肯定不能混淆的,比如 onCreate 方法。这里一般找问题的方法是:
1)首先看这个类有没有静态方法和静态代码块,因为这类的代码会在对象初始化之前运行,可能在这里加载 so 文件,或者是加密校验等操作。
2)再看看这个类的构造方法。
3)最后再看生命周期方法。
看到它的核心代码在 onCreate 中,调用了很多类的方法,猜想这里的某个方法做工作了。这时可注入代码来跟踪是哪个方法出现问题了。
下面来看看怎么添加日志信息,就是添加日志,需要修改 smali 文件,再去查看 smali 源码:
这里可以很清晰地看到调用了这些方法,那么就在每个方法中加上日志信息,这里加日志有两种方式。一种方式就是直接在这里调用系统的 log 方法,但是有两个问题:
·需要导入包,在 smali 中修改。
·需要定义两个参数:tag、msg,才能正常打印 log。
明显这个方法有点麻烦。另外一种方式就自己定义一个 MyLog 类,然后反编译,得到 MyLog 的 smali 文件,添加到这个 ShuqiApplication.smali 的 root 目录下,然后在代码中直接调用即可。放到 root 目录下的目的是在代码中调用就不需要导入包了,比如 SuqiApplication.smali 中的一些静态方法调用,如图 20-7 所示。
图 20-7 静态方法调用
编写日志类 MyLog,这里就不粘贴代码了,新建一个项目之后,反编译得到 MyLog.smail 文件,放到目录中:
得到这个文件的时候,一定要注意,把 MyLog.smali 的包名信息删除,因为放到 root 目录下的,意味着这个 MyLog 类是没有任何包名的,这需要注意,不然最后加也是报错的。
在 ShuqiApplication 的 onCreate 方法中插入的日志方法,如下所示:
在加代码的时候需要注意,要找对地方加,就是在上个方法调用完之后添加,比如:invoke-virtual,invoke-static 等,而且这些指令后面不能有 move-result-object,因为这个指令是获取方法的返回值,所以一般是这么加代码的:
·在 invoke-static/invoke-virtual 指令返回类型是 V 之后可以加入。
·在 invoke-static/invoke-virtual 指令返回类型不是 V,那么在 move-result-object 命令之后可以加入。
加好了日志代码之后就回编译执行,在这个过程中可能会遇到 samli 语法错误,针对指定的文件修改就可以了,得到回编译的 apk 之后,可以再反编译一下,看看它的 Java 代码,如图 20-8 所示。
图 20-8 添加日志之后的代码
可以看到添加的代码,在每个方法之后打印信息。下面运行程序,同时开启 log 的 tag:
看到打印的日志了,发现打印了三个 log,这里需要注意的是,虽然打印了三个 log,但是都是在不同的进程中,一个进程中的 log 只打印了一个,所以判断,问题出现在 vr.h 这个方法,如下所示:
查看这个方法源码如下所示:
果然,这个方法做了签名验证,校验不正确的话,直接退出程序。那么现在要想正常运行程序的话,直接注释用“#”,注释 smali 对应的这行代码:vr.h(this)。
然后回编译,再运行,果然不报错了,这里就不再演示了:
上面是通过注入代码来跟踪问题,这个方法很常用,也很实在。
20.5.2 静态分析 native 代码
下面介绍如何使用 IDA 来静态分析 native 代码。在反编译之后,看到它的 onCreate 方法中有一个加载 so 的代码,如下所示:
看看这个代码,如下所示:
获取密码的方法是 native 的,就来看看 getDbPassword 方法。用 IDA 打开 libpsProcess.so 文件,如图 20-9 所示。
图 20-9 IDA 打开 so 文件内容
看看这个函数的实现,一般直接看 BL/BLX 等信息,跳转逻辑,还有就是返回值。在函数的最后部分发现一个重点,就是 BL__android_log_print。这是在 native 层调用 log 的函数。再往上看,发现 tag 是 System.out.c。
运行程序看起 log,此时也可以在 Java 层添加日志的:全局搜索这个方法,发现在 yi 这个类中调用,如图 20-10 所示。
图 20-10 获取数据库密码代码
修改 yi.smali 代码:
可以看到,这个应用使用了 sqlcipher 框架进行了数据库的加密。其实现在很多应用加密数据库都是使用这个框架的,微信也是使用这个框架对本地通讯信息数据库进行加密的,这个加密工具对应的有一个 Window 程序可以打开它,不过需要密码,如图 20-11 所示。
图 20-11 打开加密的数据文件
如果想破解加密的数据库内容,只要得到加密数据库密码即可,而这个密码一般是保存在本地的,只要在本地就有办法获取的。
回编译,再运行程序,开启 log,如图 20-12 所示。
图 20-12 打印日志信息
发现,返回的密码 Java 层和 native 层是一样的。说明静态分析 native 还是有效的。
提示:案例下载地址为 http://download.csdn.net/detail/jiangwei0910410003/9308217。
案例中有个说明文件,运行前请阅读。
本节通过案例介绍了如何使用静态方式去破解一个 apk,在破解一个 apk 的时候,其实就是改点代码,然后能够运行起来,达到想要的功能,一般步骤如下:
1)注释特定功能,比如广告展示等。
2)得到方法的返回值,比如获取用户的密码。
3)添加指定的代码,比如加入自己的监测代码和广告等。
在静态分析代码的时候,需要遵循的大体路线如下:首先能够反编译,得到 AndroidManifest.xml 文件,找到程序入口代码。找到想要的代码逻辑,一般会结合界面分析,比如要想登录成功,肯定想要得到用户登录界面 Activity,这时可以用 adb shell dumpsys activity top 命令得到 Activity 名称,然后用 Eclipse 自带的程序当前视图分析工具得到控件名称,或者在代码中获取 layout 布局文件,一般是 setContentView 方法的调用地方,然后用布局文件结合代码得到用户登录的逻辑,进行修改。
·在关键的地方通过代码注入技术来跟踪代码执行逻辑。
·注意方法的返回值,条件判断等比较显眼的代码。
有些 apk 中的源码可能有自己的加密算法,这时候需要获取到这个加密方法,如果加密方法比较复杂,就需要大批的测试数据来获取这个加密方法的逻辑,一般是输入和输出作为一个测试用例。
对于 System.loadLibrary 加载 so 文件的代码,只需要找到这个 so 文件,然后用 IDA 打开进行静态分析,因为有些 apk 中把加密算法放到了 so 中了,这时候也可以通过测试数据来获取加密算法。
通过上面的例子,可以得出一个经验,就是现在很多 apk 会做一些校验工作,因为一般在代码中包含“signature”字符串信息,所以可以全局搜索一下,也许能获取一些重要信息,如图 20-13 所示。
图 20-13 签名校验关键字搜索结果
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论