首页
社区
课程
招聘
[原创]开源Hook框架-epic-实现浅析(1)
发表于: 2019-3-27 23:19 13964

[原创]开源Hook框架-epic-实现浅析(1)

2019-3-27 23:19
13964

epic是weishu大神开源的一个Hook框架,支持ART上的Java方法HOOK。

实现原理:http://weishu.me/2017/11/23/dexposed-on-art/

本文走马观花一下。

epic相当于ART上的Dexposed,所以也是Xposed-Style Method Hook。

从DexposedBridge.findAndHookMethod开始跟踪代码:


取出最后一个参数callback,然后调用XposedHelpers.findMethodExact得到想要Hook的method,最后调用DexposedBridge.hookMethod进行Hook。

XposedHelpers.findMethodExact的实现在之前的笔记中已经看过了,这里不看了。

直接看DexposedBridge.hookMethod:


所有已经Hook过的method及其对应的callbacks,全部存储在hookedMethodCallbacks中,这是一个HashMap。如果该method已经Hook过,那直接把callback回调对象加入到其对应的callbacks集合中就可以了。这样在该method被调用时,callbacks集合中所有回调都会被遍历执行。

如果该method没有被Hook过,那就调用Epic.hookMethod进行Hook。

(这里以Method为例,Constructor的Hook大同小异)


先看一下ArtMethod.of:



ArtMethod.of是以Method对象作为参数,创建一个me.weishu.epic.art.Epic.ArtMethod对象。

artOrigin. method保存原始的Java Method对象。

artOrigin. address保存的是原始的Method对象在ART中对应的art::mirror::ArtMethod对象的地址。

artOrigin. objectAddress保存的是原始的Java Method对象(Java Object)在内存中的地址。

(EpicNative.getMethodAddress和Unsafe.getObjectAddress的实现代码先不贴了。getMethodAddress的实现很简单,getObjectAddress的实现稍复杂,但也不难理解。这里先跟踪主要代码,忽略旁枝末节。)

继续看Epic.hookMethod(ArtMethod artOrigin):

(这个函数的实现有点长,分段贴)


首先创建一个MethodInfo对象,用于保存方法信息。其中methodInfo.method保存了原始的Method对象对应的me.weishu.epic.art.method.ArtMethod对象。

然后将MethodInfo对象保存到originSigs中。originSigs是一个Map对象,key是Method对象对应的art::mirror::ArtMethod对象的地址,value是MethodInfo。


调用setAccessible(true),取消Java方法调用时的访问权限检查。


调用ensureResolved,保证静态方法完成解析。为什么要这么干,已经写在注释里了。


如果要Hook的方法还未编译,则调用ArtMethod.compile主动进行编译,这么做也是因为epic是“dynamic callee-side rewriting”。

ArtMethod.compile是通过调用JIT的jit_compile_method来完成方法编译的。

最后,compiled_code入口点会保存到originEntry变量中。


为原Method创建一个备份,保存到Epic.backupMethodsMapping中。


前面是铺垫,最重要的一步来了,具体看注释。

哪些不同的Java方法会具有相同的compiled_code入口点呢?

1、所有ART版本上未被resolve的static函数

2、Android N 以上的未被编译的所有函数

3、代码逻辑一模一样的函数

4、JNI函数

其中,情况1和2在上面已经处理过了,应该不会遇到了,剩下3和4。

对于JNI函数,因为不会涉及到字节码编译,也没有对应的compiled_code,所以其compiled_code入口点会统一设置为GetQuickGenericJniStub,即art_quick_generic_jni_trampoline。

继续跟Trampoline.install,看看是如何安装跳板代码来最终完成Hook的。


这个函数的功能描述已经写到注释里了。核心操作有两点:

1)创建Trampoline(包括“二段跳板”BridgeJump,和CallOrigin)

2)创建和安装“一段跳板”,完成Hook。


[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课

最后于 2019-3-27 23:24 被十八垧编辑 ,原因:
收藏
免费 4
支持
分享
最新回复 (10)
雪    币: 14855
活跃值: (6083)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
2
兼容xposed hook?这个好。
但是看了半天只知道怎么hook函数,但是没说修改了操作系统什么才能进行hook?我们都知道xposed必须在root模式下修改了libart.so文件才能进行hook或者借用虚拟app免root进行hook
最后于 2019-3-28 14:34 被tDasm编辑 ,原因:
2019-3-28 14:26
0
雪    币: 2039
活跃值: (1468)
能力值: ( LV6,RANK:80 )
在线值:
发帖
回帖
粉丝
3
tDasm 兼容xposed hook?这个好。但是看了半天只知道怎么hook函数,但是没说修改了操作系统什么才能进行hook?我们都知道xposed必须在root模式下修改了libart.so ...
场景是进程内免root,不需要修改操作系统。
2019-3-28 16:19
0
雪    币: 14855
活跃值: (6083)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
4
十八垧 场景是进程内免root,不需要修改操作系统。
举个例子,比如进程a.apk需要hook某函数,写个hook代码b.apk,b.apk怎么注入到进程a.apk?
好像现在免root注入hook都是利用virtualAPP吧?
进程内免root,意思就是在a.apk代码中先就包含了b.apk?这样hook感觉意义不大,我自己写的apk难道不知道每个函数参数及其作用?还需要hook吗?唯一的作用就是操作系统某个函数有bug可以通过hook来修复这个函数的bug。
最后于 2019-3-29 15:35 被tDasm编辑 ,原因:
2019-3-29 10:22
0
雪    币: 456
活跃值: (76)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
5
tDasm 十八垧 场景是进程内免root,不需要修改操作系统。 举个例子,比如进程a.apk需要hook某函数,写个hook代码b.apk,b.apk怎么注入到进 ...
可以从新打包目标app,把自己的hook 跟目标程序 打包到一起
2019-4-4 16:45
0
雪    币: 14855
活跃值: (6083)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
6
刘彬 可以从新打包目标app,把自己的hook 跟目标程序 打包到一起
如何进行2次打包?应该写一个工具自动进行2次打包?
好像太极也是这个作者开发的。
最后于 2019-4-5 11:46 被tDasm编辑 ,原因:
2019-4-5 11:45
0
雪    币: 729
活跃值: (1306)
能力值: ( LV9,RANK:160 )
在线值:
发帖
回帖
粉丝
7
大哥顶你.写的不错
2019-4-9 10:19
1
雪    币: 2089
活跃值: (3933)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
8
似乎开源的不支持Android P,需要自己修改。
2019-4-14 03:45
0
雪    币:
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
9

在方法备份的时候。Method newMethod =

Method.class.getDeclaredConstructor()

;   这个会抛异常
java.lang.NoSuchMethodException: java.lang.reflect.Method.<init> []。希望大佬解答一下

最后于 2020-7-22 15:53 被wx_浅伤莫亿编辑 ,原因:
2020-7-22 14:59
0
雪    币: 0
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
10
2020-12-2 12:53
0
雪    币: 0
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
11
artOrigin. address保存的是原始的Method对象在ART中对应的art::mirror::ArtMethod对象的地址。

artOrigin. objectAddress保存的是原始的Java Method对象(Java Object)在内存中的地址。 这两个地址有啥区别
2020-12-2 13:03
0
游客
登录 | 注册 方可回帖
返回
//