安卓c语言hook,Hook Android C代码(Cydia Substrate)

本帖最后由 PJ头狼 于 2016-9-26 18:00 编辑

之前对于Cydia Substrate这个框架的使用及如何hook到Android的Java层,是在学习了鬼哥的Hook Android Java

这几天自己开始深入来学习Cydia Substrate这个框架在Hook Android C上的使用,但一开始对Android native的开发不怎么了解,所以直接通过学习这方面的博文容易碰壁,碰到的问题没有相应的思路来很好解决、实现。便先学习了Android native开发方面的知识,这里给大家推荐一篇Android native的学习博文,讲的很详细:

http://blog.csdn.net/shulianghan/article/details/18964835

下边是我学习Hook Android C的知识总结,希望可以给学习这方面的初学者有些帮助,也希望大牛们可以多多指点。参考学习的英文博文https://koz.io/android-substrate-c-hooking/

创建一个目标apk

编写目标项目,用于本次实操过程的hook对象

1.创建项目

android create project--target android-23 --path targetapp --package com.example.targetapp --activityMainactivity

//执行命令,在当前目录下创建Android项目

我这次是在Ubuntu12.04上以命令行的方式完成Android项目的构建的,也可以使用Eclipse或Android Studio来完成

2.编写C程序在项目下创建jni目录,并新建targetlib.c文件,其代码如下:

55fd2b2273b5a8b4531f72773c469d6e.gif

c14.png (66.16 KB, 下载次数: 20)

2016-9-25 10:48 上传

其中doThings()方法将对应Java层中的声明的native daThings(),而arc4random()是系统上的仿生标准库(bionic standardlibrary),生成随机数

3.编写Android.mk

55fd2b2273b5a8b4531f72773c469d6e.gif

c15.png (22.29 KB, 下载次数: 15)

2016-9-25 10:51 上传

用于编译生成targetlib库文件

4.Java层编写

55fd2b2273b5a8b4531f72773c469d6e.gif

c17.png (80.22 KB, 下载次数: 16)

2016-9-25 10:34 上传

5.编译、调试运行、安装程序在jni目录下,执行ndk-build进行库文件的编译

55fd2b2273b5a8b4531f72773c469d6e.gif

c19.png (24.88 KB, 下载次数: 18)

2016-9-25 10:35 上传

然后在项目目录下,执行ant debug进行项目的调试运行,生成apkadb install ./bin/Mainactivity-debug.apk  //安装apk程序打印结果如下:

55fd2b2273b5a8b4531f72773c469d6e.gif

c20.png (86.78 KB, 下载次数: 17)

2016-9-25 10:35 上传

6.查看库文件中的exported symbolsnm-aDC --defined-only libs/armeabi-v7a/libtargetLib.so //显示库文件所暴露的符号

55fd2b2273b5a8b4531f72773c469d6e.gif

c21.png (55.86 KB, 下载次数: 16)

2016-9-25 10:37 上传

忽略其中_的符号,该库文件暴露了下边两个方法00000e95 TJava_com_example_targetapp_Mainactivity_doThings00000e6d T getAge这些暴露出来的方法将可以直接被其他程序或库文件

调用nm -aDCulibs/armeabi-v7a/libtargetLib.so  //显示库文件中未定义的请求符号

55fd2b2273b5a8b4531f72773c469d6e.gif

c22.png (34.46 KB, 下载次数: 16)

2016-9-25 10:37 上传

这样可以查看库文件所调用其他库的符号,可以看到库文件调用了arc4random()创建Substrate模块

编写Substrate扩展模块来hook上边库文件中的arc4random()方法,修改其返回值,使其返回固定值

1.创建项目android create project--target android-23 --name Hooknative --package com.example.hooknative --pathHooknative --activity Mainactivity//创建hook项目

2.修改AndroidManifest.xml声明权限:cydia.permission.SUBSTRATE,设置android:installLocation和android:hasCode

55fd2b2273b5a8b4531f72773c469d6e.gif

c23.png (46.34 KB, 下载次数: 17)

2016-9-25 10:38 上传

3.编写C++程序在项目目录下,创建jni目录并新建***.cy.cpp文件,以最后编译生成.cy.so文件才能被Substrate框架所链接到。代码如下:

55fd2b2273b5a8b4531f72773c469d6e.gif

c33.png (47.91 KB, 下载次数: 16)

2016-9-25 10:39 上传

通过MSConfig()方法来配置过滤对象,这里是可执行文件,参数2应为文件的绝对路径,再调用MSHookFunction()方法来hook其中的arc4random()方法

4.编译、调试运行、安装模块在jni目录下,执行ndk-build进行库文件的编译然后在项目目录下,执行ant debug进行项目的调试运行,生成apkadb install./bin/Hooknative-debug.apk  //安装apk然后通过Substrate链接模块,重启系统,或执行下边命令重启zygoteadb shell setprop ctl.restartzygote修改后,打印结果如下:

55fd2b2273b5a8b4531f72773c469d6e.gif

c24.png (80.6 KB, 下载次数: 15)

2016-9-25 10:40 上传

hook库文件内部暴露方法编写Substrate模块来hook库文件中暴露的内部方法,进行修改返回值操作可在上边C++源文件中添加下边代码,进行hook操作

55fd2b2273b5a8b4531f72773c469d6e.gif

c34.png (92.65 KB, 下载次数: 17)

2016-9-25 10:41 上传

这里我们使用lookup_symbol()这个定义的方法来查找getAge()方法在库文件libtargetLib.so在的地址,需要注意的是我们的Substrate模块将会在作为所有进程初始化的孵化器zygote中第一个被加载,这时候库文件libtargetLib.so还没被加载到进程空间,直接查找其暴露的方法是行不通的。这里通过dlopen()方法人为的打开和加载在zygote的内存中的ELF二进制文件,并通过dlsym()方法来找到库文件中的暴露方法。同时Substrate也提供MSGetImageByName()和MSFindSymbol()来实现相同的功能。hook结果输出如下:

55fd2b2273b5a8b4531f72773c469d6e.gif

c25.png (58.35 KB, 下载次数: 16)

2016-9-25 10:42 上传

hook内部non-exported方法1.将内部方法getAge()设置为non-exported在C++程序中将getAge()设置为static,则方法就不会暴露出来给其他程序直接调用通过nm -aDC --defined-onlylibs/armeabi-v7a/libtargetLib.so将不会打印出:00000e6d T getAge当然由于doThings()方法要被Java层调用,所以仍是暴露的。由于getAge()设置为static,所以上边的模块将不再hook到该方法,结果输出如下:

55fd2b2273b5a8b4531f72773c469d6e.gif

c26.png (62.13 KB, 下载次数: 15)

2016-9-25 10:42 上传

2.静态分析定位non-exported方法使用IDA pro工具打开libtargetLib.so库文件,可以定位到其中getAge()方法对应的汇编程序如下:

55fd2b2273b5a8b4531f72773c469d6e.gif

c28.png (65.84 KB, 下载次数: 18)

2016-9-25 10:43 上传

其中的sub_E48就是对于getAge(),由图可得出sub_E48对应的地址为0xE48,但这不是方法getAge()在库文件中的地址,而是基于库文件基地址的偏移量,所以应先找出库文件的基地址,然后加上方法的偏移量便可确定方法的地址。

3.获取库文件的基地址通过将库文件加载到zygote的内存空间,然后通过/proc/self/maps来读取其基地址

55fd2b2273b5a8b4531f72773c469d6e.gif

c29.png (82.23 KB, 下载次数: 17)

2016-9-25 10:44 上传

55fd2b2273b5a8b4531f72773c469d6e.gif

c30.png (47.39 KB, 下载次数: 17)

2016-9-25 10:44 上传

4.hooknon-exported方法

55fd2b2273b5a8b4531f72773c469d6e.gif

c32.png (64.91 KB, 下载次数: 15)

2016-9-25 10:46 上传

其中之所以在基地址上加上0xE48+1,是因为这里在运行在thumb体系下,+1使地址为奇数对应thumb

5.hook结果如下:

55fd2b2273b5a8b4531f72773c469d6e.gif

c27.png (36.77 KB, 下载次数: 16)

2016-9-25 10:46 上传

好啦,分享了,技术才能价值。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值