Skip to content

Commit

Permalink
frida脚本,自动化寻址JNI方法
Browse files Browse the repository at this point in the history
  • Loading branch information
CYRUS-STUDIO committed Oct 25, 2024
1 parent 59e7980 commit 4c7a0c0
Show file tree
Hide file tree
Showing 12 changed files with 767 additions and 72 deletions.
194 changes: 194 additions & 0 deletions content/posts/frida脚本,自动化寻址JNI方法.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,194 @@
+++
title = 'frida脚本,自动化寻址JNI方法'
date = 2024-10-25T22:39:53.725659+08:00
draft = false
+++

> 版权归作者所有,如有转发,请注明文章出处:<https://cyrus-studio.github.io/blog/>

1\. 通过 ArtMethod 结构体找到 jni 方法在内存中的地址,并把寻址方法通过 rpc.exports 暴露给 Python 脚本调用

jni_addr.js
```
let entry_point_from_jni_offset = -1;
/**
* 找到 entry_point_from_jni_ 在 ArtMethod 结构体中的偏移量(根据 Android 版本不同可能会变化)
*
* @returns {number} 返回 entry_point_from_jni_ 的偏移量,若未找到返回 -1
*/
function get_jni_offset() {
// 如果偏移量已经计算过(不为 -1),直接返回已保存的偏移量
if (entry_point_from_jni_offset !== -1) {
return entry_point_from_jni_offset;
}
// 获取 getUidForName JNI 方法的内存地址,该方法位于 "libandroid_runtime.so" 中
let native_addr = Module.findExportByName("libandroid_runtime.so", "_Z32android_os_Process_getUidForNameP7_JNIEnvP8_jobjectP8_jstring");
// console.log("native_addr:",native_addr);
// 目标类名 "android.os.Process"
let className = "android.os.Process";
// 使用 Java.use 获取该类的 Java 类对象,并访问其 Class 对象
let clazz = Java.use(className).class;
// 获取该类的所有声明的方法
let methods = clazz.getDeclaredMethods();
// 遍历类中的所有方法
for (let i = 0; i < methods.length; i++) {
// 获取方法的字符串表示形式(如方法的完整签名)
let methodName = methods[i].toString();
// 获取方法的修饰符,flags 是该方法的访问标志(修饰符),如 public、private、static、native 等
let flags = methods[i].getModifiers();
// 通过与 256 位运算判断方法是否为 native 方法(256 代表 native 修饰符)
if (flags & 256) {
// 如果方法名中包含 "getUidForName",说明找到了目标方法
if (methodName.indexOf("getUidForName") != -1) {
// 获取该方法的 ArtMethod 对象(ArtMethod 是方法的内部表示,包含了方法的很多底层信息)
let art_method = methods[i].getArtMethod();
// 遍历从 ArtMethod 开始的内存地址,以找到与 native_addr 相等的 JNI 函数地址
for (let j = 0; j < 30; j = j + 1) {
// 读取 ArtMethod 的内存偏移位置,尝试获取 JNI 函数地址
let jni_native_addr = Memory.readPointer(ptr(art_method + j));
// 比较 JNI 函数地址是否与我们查找到的 native_addr 相等
if (native_addr.equals(jni_native_addr)) {
// 找到正确的偏移量,将其保存并返回
entry_point_from_jni_offset = j;
return j;
}
}
}
}
}
// 如果未找到 JNI 方法对应的偏移量,返回 -1
return -1;
}
/**
* 遍历类中的 native 方法,打印 JNI 函数的地址、所属模块,以及模块中的偏移量。
*
* 调用示例:get_jni_method_addr("lte.NCall")
*
* @param className 类名
*/
function get_jni_method_addr(className) {
Java.perform(function () {
// 获取指定类的 Class 对象
let obj = Java.use(className);
let clazz = obj.class;
// 获取当前系统的 JNI 偏移量
let jni_offset = get_jni_offset();
// 获取该类中的所有声明的方法
let methods = clazz.getDeclaredMethods();
// 遍历类中的所有方法
for (let i = 0; i < methods.length; i++) {
// 将方法转为字符串形式(完整的描述,包括修饰符、返回类型、参数等)
let methodName = methods[i].toString();
// 获取方法的修饰符,flags 代表访问权限和其他属性(如 native 修饰符)
let flags = methods[i].getModifiers();
// 检查该方法是否为 native 方法(通过与 256 位运算判断,256 代表 native 修饰符)
if (flags & 256) {
// 获取该方法的 ArtMethod 对象,ArtMethod 是方法在 ART 虚拟机中的内部表示
let art_method = methods[i].getArtMethod();
// 通过 ArtMethod 的内存地址 + jni_offset = JNI 函数地址
let native_addr = Memory.readPointer(ptr(art_method + jni_offset));
// 根据 JNI 函数地址中找到所在的模块,并计算该函数在模块中的偏移量
let module;
let offset;
// 打印方法名
console.log("methodName->", methodName);
try {
// 通过函数地址找到所属的模块
module = Process.getModuleByAddress(native_addr);
// 计算函数在模块中的偏移量(函数地址减去模块基地址)
offset = native_addr - module.base;
// 打印模块名称及偏移量,偏移量以十六进制格式显示,并且字母大写
console.log("Func.offset==", module.name, "0x" + offset.toString(16).toUpperCase());
} catch (err) {
}
// 打印该方法的 JNI 函数地址
console.log("Func.getArtMethod->native_addr:", native_addr.toString().toUpperCase());
// console.log("Func.flags->", flags);
}
}
})
}
// 暴露给 Python 调用(注意:exports中函数名需要全部小写,而且不能有下划线,不然会找不到方法)
rpc.exports.getjnimethodaddr = get_jni_method_addr
```

2\. 在 python 脚本中加载 jni_addr.js 并调用 get_jni_method_addr 方法打印指定类中所有 native 方法的内存地址

jni_addr.py
```
import frida
def read_frida_js_source(script):
with open(script, "r", encoding='utf-8') as f:
return f.read()
def on_message(message, data):
print(f"消息: {message['type']}, 数据: {message['payload']}")
def main():
class_name = "com.cyrus.example.MainActivity"
device = frida.get_device_manager().add_remote_device("127.0.0.1:1234")
pid = device.get_frontmost_application().pid
session: frida.core.Session = device.attach(pid)
script = session.create_script(read_frida_js_source("jni_addr.js"))
script.on('message', on_message)
script.load()
script.exports.getjnimethodaddr(class_name)
# 退出
session.detach()
if __name__ == "__main__":
main()
```

运行python脚本,执行结果如下
```
methodName-> public final native java.lang.String com.cyrus.example.MainActivity.getNativeString()
Func.offset== libnative-lib.so 0x24F10
Func.getArtMethod->native_addr: 0X77518B6F10
```

具体原理可以参考这篇文章【[使用 Frida 定位 JNI 方法内存地址](https://cyrus-studio.github.io/blog/posts/%E4%BD%BF%E7%94%A8-frida-%E5%AE%9A%E4%BD%8D-jni-%E6%96%B9%E6%B3%95%E5%86%85%E5%AD%98%E5%9C%B0%E5%9D%80/)



40 changes: 23 additions & 17 deletions public/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,23 @@
<h1>CYRUS STUDIO</h1>
<ul class="posts-list">

<li class="posts-list-item">
<a class="posts-list-item-title" href="https://cyrus-studio.github.io/blog/posts/frida%E8%84%9A%E6%9C%AC%E8%87%AA%E5%8A%A8%E5%8C%96%E5%AF%BB%E5%9D%80jni%E6%96%B9%E6%B3%95/">frida脚本,自动化寻址JNI方法</a>
<span class="posts-list-item-description">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="icon icon-calendar">
<title>calendar</title>
<rect x="3" y="4" width="18" height="18" rx="2" ry="2"></rect><line x1="16" y1="2" x2="16" y2="6"></line><line x1="8" y1="2" x2="8" y2="6"></line><line x1="3" y1="10" x2="21" y2="10"></line>
</svg>
Oct 25, 2024
<span class="posts-list-item-separator">-</span>
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="icon icon-clock">
<title>clock</title>
<circle cx="12" cy="12" r="10"></circle><polyline points="12 6 12 12 16 14"></polyline>
</svg>
3 min read
</span>
</li>

<li class="posts-list-item">
<a class="posts-list-item-title" href="https://cyrus-studio.github.io/blog/posts/%E4%BD%BF%E7%94%A8miniconda%E7%AE%A1%E7%90%86python%E7%8E%AF%E5%A2%83/">使用Miniconda管理Python环境</a>
<span class="posts-list-item-description">
Expand Down Expand Up @@ -207,23 +224,6 @@ <h1>CYRUS STUDIO</h1>
</span>
</li>

<li class="posts-list-item">
<a class="posts-list-item-title" href="https://cyrus-studio.github.io/blog/posts/%E4%BD%BF%E7%94%A8charles%E6%8A%93%E5%8C%85android-app%E6%95%B0%E6%8D%AE/">使用Charles抓包Android App数据</a>
<span class="posts-list-item-description">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="icon icon-calendar">
<title>calendar</title>
<rect x="3" y="4" width="18" height="18" rx="2" ry="2"></rect><line x1="16" y1="2" x2="16" y2="6"></line><line x1="8" y1="2" x2="8" y2="6"></line><line x1="3" y1="10" x2="21" y2="10"></line>
</svg>
Sep 23, 2024
<span class="posts-list-item-separator">-</span>
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="icon icon-clock">
<title>clock</title>
<circle cx="12" cy="12" r="10"></circle><polyline points="12 6 12 12 16 14"></polyline>
</svg>
1 min read
</span>
</li>

</ul>


Expand All @@ -248,6 +248,12 @@ <h1>CYRUS STUDIO</h1>
</a>
</li>

<li class="page-item">
<a class="page-link" href="/blog/page/4/">
4
</a>
</li>


<li class="page-item">
<a class="page-link" href="/blog/page/2/">
Expand Down
9 changes: 8 additions & 1 deletion public/index.xml
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,15 @@
<description>Recent content on CYRUS STUDIO</description>
<generator>Hugo</generator>
<language>zh-cn</language>
<lastBuildDate>Mon, 21 Oct 2024 02:17:40 +0800</lastBuildDate>
<lastBuildDate>Fri, 25 Oct 2024 22:39:53 +0800</lastBuildDate>
<atom:link href="https://cyrus-studio.github.io/blog/index.xml" rel="self" type="application/rss+xml" />
<item>
<title>frida脚本,自动化寻址JNI方法</title>
<link>https://cyrus-studio.github.io/blog/posts/frida%E8%84%9A%E6%9C%AC%E8%87%AA%E5%8A%A8%E5%8C%96%E5%AF%BB%E5%9D%80jni%E6%96%B9%E6%B3%95/</link>
<pubDate>Fri, 25 Oct 2024 22:39:53 +0800</pubDate>
<guid>https://cyrus-studio.github.io/blog/posts/frida%E8%84%9A%E6%9C%AC%E8%87%AA%E5%8A%A8%E5%8C%96%E5%AF%BB%E5%9D%80jni%E6%96%B9%E6%B3%95/</guid>
<description>版权归作者所有,如有转发,请注明文章出处:https://cyrus-studio.github.io/blog/&#xA;1. 通过 ArtMethod 结构体找到 jni 方法在内存中的地址,并把寻址方法通过 rpc.exports 暴露给 Python 脚本调用&#xA;jni_addr.js&#xA;let entry_point_from_jni_offset = -1;&#xD;/**&#xD;* 找到 entry_point_from_jni_ 在 ArtMethod 结构体中的偏移量(根据 Android 版本不同可能会变化)&#xD;*&#xD;* @returns {number} 返回 entry_point_from_jni_ 的偏移量,若未找到返回 -1&#xD;*/&#xD;function get_jni_offset() {&#xD;// 如果偏移量已经计算过(不为 -1),直接返回已保存的偏移量&#xD;if (entry_point_from_jni_offset !== -1) {&#xD;return entry_point_from_jni_offset;&#xD;}&#xD;// 获取 getUidForName JNI 方法的内存地址,该方法位于 &amp;#34;libandroid_runtime.so&amp;#34; 中&#xD;let native_addr = Module.findExportByName(&amp;#34;libandroid_runtime.so&amp;#34;, &amp;#34;_Z32android_os_Process_getUidForNameP7_JNIEnvP8_jobjectP8_jstring&amp;#34;);&#xD;// console.log(&amp;#34;native_addr:&amp;#34;,native_addr);&#xD;// 目标类名 &amp;#34;android.os.Process&amp;#34;&#xD;let className = &amp;#34;android.os.Process&amp;#34;;&#xD;// 使用 Java.</description>
</item>
<item>
<title>使用Miniconda管理Python环境</title>
<link>https://cyrus-studio.github.io/blog/posts/%E4%BD%BF%E7%94%A8miniconda%E7%AE%A1%E7%90%86python%E7%8E%AF%E5%A2%83/</link>
Expand Down
40 changes: 23 additions & 17 deletions public/page/2/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,23 @@
<h1>CYRUS STUDIO</h1>
<ul class="posts-list">

<li class="posts-list-item">
<a class="posts-list-item-title" href="https://cyrus-studio.github.io/blog/posts/%E4%BD%BF%E7%94%A8charles%E6%8A%93%E5%8C%85android-app%E6%95%B0%E6%8D%AE/">使用Charles抓包Android App数据</a>
<span class="posts-list-item-description">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="icon icon-calendar">
<title>calendar</title>
<rect x="3" y="4" width="18" height="18" rx="2" ry="2"></rect><line x1="16" y1="2" x2="16" y2="6"></line><line x1="8" y1="2" x2="8" y2="6"></line><line x1="3" y1="10" x2="21" y2="10"></line>
</svg>
Sep 23, 2024
<span class="posts-list-item-separator">-</span>
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="icon icon-clock">
<title>clock</title>
<circle cx="12" cy="12" r="10"></circle><polyline points="12 6 12 12 16 14"></polyline>
</svg>
1 min read
</span>
</li>

<li class="posts-list-item">
<a class="posts-list-item-title" href="https://cyrus-studio.github.io/blog/posts/%E5%9F%BA%E4%BA%8Epython%E4%B8%8Ek-means%E7%9A%84%E8%87%AA%E5%8A%A8%E5%8C%96%E8%A7%86%E9%A2%91%E5%88%86%E7%B1%BB%E6%96%B9%E6%B3%95/">基于Python与K-Means的自动化视频分类方法</a>
<span class="posts-list-item-description">
Expand Down Expand Up @@ -207,23 +224,6 @@ <h1>CYRUS STUDIO</h1>
</span>
</li>

<li class="posts-list-item">
<a class="posts-list-item-title" href="https://cyrus-studio.github.io/blog/posts/%E7%BC%96%E8%AF%91lineageos%E6%A8%A1%E6%8B%9F%E5%99%A8%E9%95%9C%E5%83%8F%E5%AF%BC%E5%87%BA%E5%88%B0androidstudio/">编译LineageOS模拟器镜像,导出到AndroidStudio</a>
<span class="posts-list-item-description">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="icon icon-calendar">
<title>calendar</title>
<rect x="3" y="4" width="18" height="18" rx="2" ry="2"></rect><line x1="16" y1="2" x2="16" y2="6"></line><line x1="8" y1="2" x2="8" y2="6"></line><line x1="3" y1="10" x2="21" y2="10"></line>
</svg>
Sep 1, 2024
<span class="posts-list-item-separator">-</span>
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="icon icon-clock">
<title>clock</title>
<circle cx="12" cy="12" r="10"></circle><polyline points="12 6 12 12 16 14"></polyline>
</svg>
5 min read
</span>
</li>

</ul>


Expand Down Expand Up @@ -257,6 +257,12 @@ <h1>CYRUS STUDIO</h1>
</a>
</li>

<li class="page-item">
<a class="page-link" href="/blog/page/4/">
4
</a>
</li>


<li class="page-item">
<a class="page-link" href="/blog/page/3/">
Expand Down
32 changes: 32 additions & 0 deletions public/page/3/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,23 @@
<h1>CYRUS STUDIO</h1>
<ul class="posts-list">

<li class="posts-list-item">
<a class="posts-list-item-title" href="https://cyrus-studio.github.io/blog/posts/%E7%BC%96%E8%AF%91lineageos%E6%A8%A1%E6%8B%9F%E5%99%A8%E9%95%9C%E5%83%8F%E5%AF%BC%E5%87%BA%E5%88%B0androidstudio/">编译LineageOS模拟器镜像,导出到AndroidStudio</a>
<span class="posts-list-item-description">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="icon icon-calendar">
<title>calendar</title>
<rect x="3" y="4" width="18" height="18" rx="2" ry="2"></rect><line x1="16" y1="2" x2="16" y2="6"></line><line x1="8" y1="2" x2="8" y2="6"></line><line x1="3" y1="10" x2="21" y2="10"></line>
</svg>
Sep 1, 2024
<span class="posts-list-item-separator">-</span>
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="icon icon-clock">
<title>clock</title>
<circle cx="12" cy="12" r="10"></circle><polyline points="12 6 12 12 16 14"></polyline>
</svg>
5 min read
</span>
</li>

<li class="posts-list-item">
<a class="posts-list-item-title" href="https://cyrus-studio.github.io/blog/posts/windows%E4%B8%8B%E5%88%9B%E5%BB%BAftp%E6%9C%8D%E5%8A%A1%E5%99%A8%E5%AE%9E%E7%8E%B0%E6%96%87%E4%BB%B6%E5%85%B1%E4%BA%AB/">Windows下创建FTP服务器,实现文件共享</a>
<span class="posts-list-item-description">
Expand Down Expand Up @@ -240,6 +257,21 @@ <h1>CYRUS STUDIO</h1>
</a>
</li>

<li class="page-item">
<a class="page-link" href="/blog/page/4/">
4
</a>
</li>


<li class="page-item">
<a class="page-link" href="/blog/page/4/">
<svg viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="icon icon-arrow-right">
<title>arrow-right</title>
<line x1="5" y1="12" x2="19" y2="12"></line><polyline points="12 5 19 12 12 19"></polyline>
</svg>
</a>
</li>

</ul>

Expand Down
Loading

0 comments on commit 4c7a0c0

Please sign in to comment.