- 对本书的赞誉
- 前言
- 基础篇
- 第 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 样本分析
19.3 Hook Native 层功能
下面继续来看如何 Hook Native 层的功能,也是本章的重点。
第一步:创建一个 Native 项目
这里用 Eclipse 操作,简单便捷,有很多人问为什么不用 AS,这要看每个人的使用习惯。虽然 AS 工具是主流,不过本人还是习惯用 Eclipse,如图 19-5 所示。
第二步:导入 Substrate 的 Native 功能包
需要导入一个 substrate.h 头文件,和两个 so 功能包。Native 层应用都是这么操作的,提供一个头文件告诉你 API,具体实现在 so 包中。
图 19-5 创建 Native 项目
第三步:寻找 Hook 的函数名
这里网上没有好的 hook 代码,为了更好的了解这个工具的厉害之处,弄一个比较实际的案例就是 hook 系统加载 dex 的函数,这样就可以获取到每个应用的 dex 文件了,这种方式对于早期加固是一个比较好的脱壳方案。在之前介绍脱壳会使用 IDA 在指定函数处下个断点,这里如果要 hook 的话,就需要找到这个加载 dex 的函数名称,一定要记的是导出的函数名。
下面就用 IDA 来查找需要 Hook 的函数名,首先导出设备的 libdvm.so 文件:system/lib/libdvm.so
然后使用 IDA 打开,寻找加载 dex 函数,如图 19-6 所示。
图 19-6 寻找加载 dex 函数
切换到 Exports 视图页面,然后搜索 dexFileParse 函数,点进去:
需要得到的是 EXPORT 函数,需要 Hook 的是它,一定要注意函数,不然 Hook 没效果的。找到函数之后还得获取函数的参数类型和返回类型,这个也好办,因为有 Android 源码,所以直接在源码中找这个函数参数说明、已经返回值说明即可。因为 Native 层 Hook 的其实是函数指针的替换,所以如果想 Hook 原来的函数,必须新建一个和原来一样的函数功能,然后传递函数指针即可。这个函数的参数和返回值定义如下:
参数含义非常简单,第一个参数表示 dex 文件的起始地址,第二个参数是 dex 文件的长度,有这两个参数就可以写入文件了。这里需要获取 DexFile 类型,这个直接在 Android 源码目录下找到这个头文件 DexFile.h 即可。然后导入工程中。这样就找到了需要 hook 的函数,下面就开始编写 hook 代码了。
第四步:编写 hook 代码
在编写 hook 代码之前,需要考虑这几件事:
·hook 之后的 dex 存在哪?怎么存?这里直接通过当前的 pid 值获取进程名,然后将其作为 dex 的文件名,这样每个进程的 dex 文件名就不会冲突了。这里要理解一点:一个进程对应一个 DVM,加载一个 dex 文件。所以这里 hook 其实就是注入每个进程,在每个进程中 hook 每个函数功能。
·需要过滤系统进程,并不是所有的进程都是想要 hook 的,而且这些进程未必有 dex 文件,比如鼻祖进程 zygote,而这些进程过滤规则,需要自己打印看结果,然后构造。
下面开始写代码了,首先定义想要 hook 的 so 文件:
主要是第二个参数,是需要 hook 的 so 路径。然后在入口处开始 hook 代码:
这里找到 so 中需要 hook 函数符号,然后直接调用 MSHookFunction 传入符号,新函数地址,旧函数地址。可以看到在 C 中指针是多么强大,实现了函数的回调机制,而且非常方便。然后继续来看新定义的 hook 函数功能:
这里先获取当前进程名称,然后构造 dex 文件名,保存 dex 文件,最后一定要记得返回原始的函数功能,不能影响正常的流程。还要记得过滤规则,不要对每个进程都进行操作,并不是每个进程都是有效的。而这些过滤规则是根据自己打印进程名来自行添加即可。
第五步:编写 MK 文件
上面代码已经编写完成了,下面来编写编译脚本吧。注意编译之后的文件名一定要以 cy 结尾,不然是 hook 是失败的,然后就是需要导入 substrate 的 so 库文件:
第六步:安装并运行
和之前一样,运行之后,需要重启设备,然后先看看 native 层的 log 信息:
然后再去目录中查看保存的 dex 文件信息,如图 19-7 所示。
图 19-7 dex 文件
dex 文件都保存成功了,这样会发现如果对于早期的加壳应用,可以采用这种方式进行脱壳操作。也不需要用 IDA 进行调试 dump 出 dex 文件了。
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论