首页
社区
课程
招聘
[原创]获取jni函数地址
发表于: 2小时前 153

[原创]获取jni函数地址

2小时前
153

在ART中,每一个Java方法在虚拟机内部都对应着一个C++对象:Artmethod。对native方法来说在Artmethod中有两个很关键的指针:

一个是entry_point_from_jni:专门用于JNI调用的入口点。当Java层不论是静态注册还是动态注册最终都是这个入口。

再一个就是entry_point_from_quick_compiled_code_:这个就是ART 执行代码的通用入口

我们重点关注entry_point_from_jni

image

Android 11 起,ART 把 JNI ID 从裸指针改造成了可切换的间接寻址体系,Android 12 沿用了这套设计

kindices是Debuggable App 默认的模式 在这个模式下entry_point_from_jni存放的就不是函数地址 而是一个索引。真正的函数地址被放在了一个全局的间接寻址表中。

kPointer则是Release App 默认的模式 在这里就是直接存储的是函数的内存地址

image

在一个Native方法被实际调用之前,ART并不知道它对应的C/C++函数在哪里。为了处理这种未决的状态,ART使用了跳板桩。

当类被加载的时候,ArtMethod被创建,他的Native入口点被统一设置为一个名为GetJniDlsymLookupStub的跳板地址。当Java代码第一次调用这个native方法时,执行流跳到了这个Stub。这个Stub的内部逻辑是拿着方法名和签名,去通过dlsym在已加载的.so库中寻找真实的C++函数。找到真实的函数后,Stub会修改ArtMethod的内部指针,将入口点更新为真实的函数地址。这样在下一次再调用这个方法的时候,就直接跳入真实的函数了 不再去走Stub。这被称为延迟绑定image

根据上面的内容不难看出 要实现目标需要解决kindices模式 懒加载 还需要向外提供一个接口 方便随时frida查看绑定状态

Patch 1 关掉 kIndices,保证 data_ 里存的是真实函数指针;Patch 2 在 SetDataPtrSize 这个唯一写入口下钩,抓绑定发生的瞬间;Patch 3 和 Patch 4 提供 dumpNativeBindings 接口,任意时刻把 data_ 读出来并用 dladdr 解析成 so!symbol+offset。

art/runtime/runtime.cc 原本根据 App 是否 debuggable 切换 JNI ID 模式:

Debuggable App 走 kIndices,直接改成一律 kPointer:

这样 data_ 里一定是真实函数指针。

ArtMethod::data_ 的写入路径很多,但最后都会走到 ArtMethod::SetDataPtrSize。在这里做处理,所有绑定行为都能抓到。


[内核课程]《Windows内核攻防实战》!从零到实战,融合AI与Windows内核攻防全技术栈,打造具备自动化能力的内核开发高手。

收藏
免费 8
打赏
分享
最新回复 (5)
雪    币: 8979
活跃值: (5723)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
2
看看
2小时前
0
雪    币: 158
活跃值: (5051)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
3
看看 
2小时前
0
雪    币: 411
活跃值: (331)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
4
66
1小时前
0
雪    币: 292
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
5
66666
1小时前
0
雪    币: 0
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
6
66
1小时前
0
游客
登录 | 注册 方可回帖
返回