首页
论坛
课程
招聘
[分享]Hook Android C代码基础总结
2016-9-25 20:51 11824

[分享]Hook Android C代码基础总结

2016-9-25 20:51
11824
这几天自己开始深入来学习Cydia Substrate这个框架在Hook Android C上的使用,但一开始对Android native的开发不怎么了解,所以直接通过学习这方面的博文容易碰壁,碰到的问题没有相应的思路来很好解决、实现。便先学习了Android native开发方面的知识,这里给大家推荐一篇Android native的学习博文,讲的很详细:Android 开发 之 JNI入门
下边是我学习Hook Android C的知识总结,希望可以给学习这方面的初学者有些帮助,也希望大牛们可以多多指点。
参考学习的英文博文:Substrate - hooking C on Android

实验apk在附件中
hook Android C代码
  
  创建一个目标apk
  编写目标项目,用于本次实操过程的hook对象
  1.创建项目
  android create project --target android-23 --path targetapp --package com.example.targetapp --activity Mainactivity
  //执行命令,在当前目录下创建Android项目
  

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

  其中doThings()方法将对应Java层中的声明的native daThings(),而arc4random()是系统上的仿生标准库(bionic standard library),生成随机数
  3.编写Android.mk
  

  用于编译生成targetlib库文件
  4.Java层编写
  

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

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

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

  忽略其中_的符号,该库文件暴露了下边两个方法
  00000e95 T Java_com_example_targetapp_Mainactivity_doThings
  00000e6d T getAge
  这些暴露出来的方法将可以直接被其他程序或库文件调用
  nm -aDCu libs/armeabi-v7a/libtargetLib.so  //显示库文件中未定义的请求符号
  

  这样可以查看库文件所调用其他库的符号,可以看到库文件调用了arc4random()
  
  创建Substrate模块
  编写Substrate扩展模块来hook上边库文件中的arc4random()方法,修改其返回值,使其返回固定值
  1.创建项目
  android create project --target android-23 --name Hooknative --package com.example.hooknative --path Hooknative --activity Mainactivity
  //创建hook项目
  2.修改AndroidManifest.xml
  声明权限:cydia.permission.SUBSTRATE,设置android:installLocation和android:hasCode
  

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

  通过MSConfig()方法来配置过滤对象,这里是可执行文件,参数2应为文件的绝对路径,再调用MSHookFunction()方法来hook其中的arc4random()方法
  4.编译、调试运行、安装模块
  在jni目录下,执行ndk-build进行库文件的编译
  然后在项目目录下,执行ant debug进行项目的调试运行,生成apk
  adb install ./bin/Hooknative-debug.apk  //安装apk
  然后通过Substrate链接模块,重启系统,或执行下边命令重启zygote
  adb shell setprop ctl.restart zygote
  修改后,打印结果如下:
  

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

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

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

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

  其中的sub_E48就是对于getAge(),由图可得出sub_E48对应的地址为0xE48,但这不是方法getAge()在库文件中的地址,而是基于库文件基地址的偏移量,所以应先找出库文件的基地址,然后加上方法的偏移量便可确定方法的地址。
  3.获取库文件的基地址
  通过将库文件加载到zygote的内存空间,然后通过/proc/self/maps来读取其基地址
  
   
  4.hook non-exported方法
  

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

  

第五届安全开发者峰会(SDC 2021)10月23日上海召开!限时2.5折门票(含自助午餐1份)

上传的附件:
收藏
点赞0
打赏
分享
最新回复 (17)
雪    币: 325
活跃值: 活跃值 (34)
能力值: ( LV7,RANK:110 )
在线值:
发帖
回帖
粉丝
地狱怪客 活跃值 2 2016-9-25 21:21
2
0
学习。。。
雪    币: 1044
活跃值: 活跃值 (305)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
bengou 活跃值 2016-9-25 21:23
3
0
谢谢分享
雪    币: 260
活跃值: 活跃值 (28)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
小豆芽 活跃值 2016-9-26 09:02
4
0
感谢分享~
雪    币: 330
活跃值: 活跃值 (251)
能力值: ( LV2,RANK:15 )
在线值:
发帖
回帖
粉丝
Loopher 活跃值 2016-9-26 10:35
5
0
感谢分享~
雪    币: 7
活跃值: 活跃值 (20)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
jlvsjp 活跃值 2016-9-26 11:49
6
0
感谢分享,很大帮助
雪    币: 201
活跃值: 活跃值 (22)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
cladey 活跃值 2016-9-27 10:21
7
0
多谢,请问5.1以上有什么类似比较好的工具
雪    币: 51
活跃值: 活跃值 (16)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
KX头狼 活跃值 2016-9-27 14:01
8
0
5.1以上的hook可以用Xposed,但这个框架不能hook native层
雪    币: 51
活跃值: 活跃值 (144)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
金奔腾 活跃值 2016-9-28 08:45
9
0
多谢分享!
雪    币: 345
活跃值: 活跃值 (10)
能力值: ( LV3,RANK:30 )
在线值:
发帖
回帖
粉丝
OnlyForU 活跃值 2016-9-29 10:20
10
0
感谢分享!
雪    币: 30
活跃值: 活跃值 (25)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
keeslient 活跃值 2016-12-26 18:33
11
0
学习了 先马克一下
雪    币: 2
活跃值: 活跃值 (15)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
黑夜破解 活跃值 2016-12-30 17:46
12
0
这样的文章都能优秀额,substrate的使用早几年前网上就有了好吧,看雪没技术了?
雪    币: 13
活跃值: 活跃值 (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
狂奔的鸡骨架 活跃值 2017-1-2 16:43
13
0
mark
雪    币: 146
活跃值: 活跃值 (15)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
hackce 活跃值 2017-1-11 17:12
14
0
感谢分享~
雪    币: 101
活跃值: 活跃值 (310)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
xxRea 活跃值 2017-3-26 11:01
15
0
写的很好,清晰明了。。
雪    币: 101
活跃值: 活跃值 (310)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
xxRea 活跃值 2017-3-26 23:30
16
0
请教一个问题,我在Hook非系统的so库时,出现一个错误 dlerror:Cannot load library: load_library(linker.cpp:761): not a valid ELF executable: /data/app-lib/com.xxxx.xxx-1/xxx.so 请问这个问题要如何解决,谢谢
雪    币: 69
活跃值: 活跃值 (95)
能力值: ( LV5,RANK:70 )
在线值:
发帖
回帖
粉丝
pedies 活跃值 2017-7-13 16:07
17
0
你这是翻译国外的文档吧
雪    币: 14
活跃值: 活跃值 (30)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
Lemonr 活跃值 2018-6-8 16:13
18
0
学习了
游客
登录 | 注册 方可回帖
返回