当前位置: 首页 > news >正文

Frida JavaScript API 总结

好的,这是一份 Frida JavaScript API 的详细总结,按照功能模块进行分类,并附有常用示例。


Frida JavaScript API 总结

Frida 的 API 主要分为两大领域:操作 Java 运行时 (Android) 和 操作 Native 代码 (C/C++)。你的脚本通常在目标进程的上下文中执行。

核心模块概览

模块名 主要用途 目标环境
Java 与 Java 运行时交互 (Android) Java (ART/Dalvik)
Interceptor 拦截和修改函数调用 Native
Module 操作已加载的库和查找符号 Native
Memory 内存读写和分配 Native
Process 查询进程信息 (模块、线程等) Native
Console 日志输出 通用
send(), recv() 与外部控制端通信 通用


  1. Java API (Android)

用于在 Android 应用的 Java 虚拟机 (JVM) 中进行操作。

Java.perform(fn)

确保你的代码在 JVM 线程中执行。这是几乎所有 Java 层 Hook 的入口点。

Java.perform(function () {// 你的 Hook 代码写在这里console.log("Inside Java runtime!");
});

Java.use(className)

获取一个 JavaScript wrapper 来操作指定的 Java 类。

var StringClass = Java.use("java.lang.String");
var MyAppClass = Java.use("com.example.myapp.MainActivity");

Class.$new() 与 $init

创建新的 Java 对象实例。$init 是构造方法的实现。

var Exception = Java.use("java.lang.Exception");
var e = Exception.$new("My custom exception"); // 创建新实例// Hook 构造方法
StringClass.$init.overload('java.lang.String').implementation = function (s) {console.log("Creating string: " + s);return this.$init(s); // 调用原始构造方法
};

Method.implementation

替换一个方法的实现。

var MyClass = Java.use("com.example.MyClass");
MyClass.targetMethod.implementation = function (a, b) {console.log("targetMethod called: " + a + ", " + b);// 调用原方法var result = this.targetMethod(a, b);// 修改返回值return result + 100;
};

overload(signature)

指定要 Hook 的重载方法。参数类型必须完全匹配。

// 假设方法有多个重载:encrypt(String) 和 encrypt(String, String)
MyClass.encrypt.overload('java.lang.String').implementation = function (data) { ... };
MyClass.encrypt.overload('java.lang.String', 'java.lang.String').implementation = function (data, key) { ... };

Java.choose(className, callbacks)

在堆上枚举已存在的类实例,对每个匹配的实例执行操作。

Java.choose("com.example.MyClass", {onMatch: function (instance) {// 对每个找到的实例执行console.log("Found instance: " + instance);console.log("Value of field: " + instance.field.value);},onComplete: function () {// 枚举完成时执行console.log("Search complete.");}
});

Java.enumerateLoadedClasses()

枚举所有已加载的 Java 类。

Java.enumerateLoadedClasses({onMatch: function (className) {if (className.includes("crypto")) { // 过滤类名console.log(className);}},onComplete: function () {}
});

字段操作

通过 .value 读取或修改字段值。

var MyClass = Java.use("com.example.MyClass");
// 修改静态字段
MyClass.staticField.value = "new_value";// 在实例上修改字段 (需要在 onMatch 回调中)
instance.instanceField.value = 123;

  1. Interceptor API (Native)

用于拦截和替换本机函数(C/C++)的调用。

Interceptor.attach(target, callbacks)

在函数调用时附加回调。

// 通过函数名附加
Interceptor.attach(Module.getExportByName("libc.so", "strcmp"), {onEnter: function (args) {// args[0] 和 args[1] 是 strcmp 的两个参数this.arg0 = args[0]; // 保存供 onLeave 使用this.arg1 = args[1];console.log("strcmp called with: " + args[0].readCString() + ", " + args[1].readCString());},onLeave: function (retval) {// retval 是返回值 (int)console.log("strcmp returned: " + retval);// retval.replace(0); // 强制返回 0 (相等)}
});// 通过地址附加
var funcPtr = ptr(0x1234abcd);
Interceptor.attach(funcPtr, { ... });

Interceptor.replace(target, replacement)

用新的实现完全替换一个函数。

// 创建一个新的本地回调函数
var newStrlen = new NativeCallback(function (ptr) {console.log("Fake strlen called for: " + ptr.readCString());return 5; // 总是返回 5
}, 'int', ['pointer']); // 返回类型, [参数类型列表]// 替换原来的函数
Interceptor.replace(Module.getExportByName("libc.so", "strlen"), newStrlen);

  1. Module API (Native)

用于操作已加载的共享库(SO 文件)。

Module.findBaseAddress(name)

查找模块的加载基地址。

var baseAddr = Module.findBaseAddress("libtarget.so");
console.log("libtarget.so base address: " + baseAddr);

Module.getExportByName(moduleName|null, exportName)

获取导出函数的地址。如果 moduleName 为 null,则在所有模块中查找。

// 从特定模块查找
var openAddr = Module.getExportByName("libc.so", "open");
// 从任何模块查找 (更慢)
var fopenAddr = Module.getExportByName(null, "fopen");

Module.enumerateImports() / Module.enumerateExports()

枚举模块的导入/导出函数。

// 枚举 libssl.so 的所有导出
Module.enumerateExports("libssl.so", {onMatch: function (exp) {console.log(exp.name + " @ " + exp.address);},onComplete: function () {}
});// 枚举所有模块
Process.enumerateModules().forEach(function (module) {console.log(module.name + " @ " + module.base);
});

  1. Memory API (Native)

用于读写和分配进程内存。

Memory.readByteArray(address, length)

从指定地址读取一段字节。

var bytes = Memory.readByteArray(ptr(0x1234), 100);
console.log(hexdump(bytes, { offset: 0, length: 100 }));

Memory.readCString(address)

从指定地址读取一个 C 风格字符串(以 NULL 结尾)。

var str = Memory.readCString(ptr(0x5678));
console.log("Read string: " + str);

Memory.writeUtf8String(address, str)

向指定地址写入一个 UTF-8 字符串。

Memory.writeUtf8String(ptr(0x5678), "New String Content");

Memory.alloc(size)

在目标进程中分配内存。

var buffer = Memory.alloc(100); // 分配 100 字节
Memory.writeUtf8String(buffer, "Data to pass to native function");

Memory.protect(address, size, protection)

修改内存页的保护属性(如 rwx)。

Memory.protect(ptr(0x4000), 4096, 'rwx'); // 使页面可读、写、执行

Memory.scan(address, size, pattern)

扫描内存以查找模式(支持通配符 ??)。

var results = Memory.scan(Module.findBaseAddress("libtarget.so"), 0x10000, "12 34 ?? 78 9a");
results.on('match', function (match) {console.log('Pattern found at:', match.address);
});

  1. Process API

用于查询当前进程的信息。

Process.id

获取当前进程的 PID。

console.log("Current PID: " + Process.id);

Process.enumerateModules()

枚举所有已加载的模块。

Process.enumerateModules().forEach(function (module) {console.log(module.name + " - Base: " + module.base + " - Size: " + module.size);
});

Process.enumerateThreads()

枚举所有线程。

Process.enumerateThreads().forEach(function (thread) {console.log("Thread ID: " + thread.id + ", State: " + thread.state);
});

  1. 工具函数与类型

ptr(address)

将数字或字符串转换为 NativePointer 对象。

var address = ptr("0x1234");
var address2 = ptr(0x5678);

NULL

空指针常量。

if (somePointer.equals(NULL)) {console.log("This is a NULL pointer");
}

new NativeCallback(func, returnType, argTypes)

创建一个新的函数,可供本机代码调用。

var callback = new NativeCallback(function (a, b) {return a + b;
}, 'int', ['int', 'int']);

  1. 通信 API

send(message[, data])

发送消息到外部控制端(如 Python 脚本)。

send({ type: 'info', payload: 'Function hooked successfully!' });
// 发送二进制数据
send({ type: 'data' }, new Uint8Array([0x01, 0x02, 0x03]).buffer);

recv([type], callback)

接收来自外部控制端的消息。

recv('execute', function (message) {console.log("Received command: " + message.payload);// 执行操作...
});

  1. 控制台输出

console.log(message), console.warn(message), console.error(message)

输出日志信息,显示在 Frida 控制台中。

console.log("This is a log message.");
console.warn("This is a warning!");
console.error("This is an error!");

hexdump(source[, options])

以十六进制格式转储内存或字节数组。

var bytes = Memory.readByteArray(somePointer, 64);
console.log(hexdump(bytes));

常用模式总结

  1. Java 层 Hook: Java.perform -> Java.use -> method.implementation
  2. Native 层 Hook: Interceptor.attach(Module.getExportByName(…), {onEnter, onLeave})
  3. 内存扫描: Memory.scan(base, size, “pattern”)
  4. 进程信息: Process.enumerateModules(), Process.enumerateThreads()
  5. 通信: send() / recv() 与外部 Python 脚本交互

这份总结涵盖了 90% 的常用场景。对于更高级的用法,请始终参考官方文档:https://frida.re/docs/javascript-api/

http://www.dtcms.com/a/350809.html

相关文章:

  • 【数据库】dbeaver 查询clickhouse,表内时间与真实时间差8小时
  • 基于Springboot + vue3实现的宿舍管理系统
  • [pilot智驾系统] docs | 用户界面状态(UIState)
  • 第十八节:骨骼动画 - 角色动画控制
  • 时间序列异常检测实战:HMM与LSTM方法解析
  • 在华为云服务器上使用Ansible部署LNMP环境【玩转华为云】
  • Ubuntu22.04 解决eth0未托管问题
  • golang 基础类 八股文400题
  • Redis面试精讲 Day 30:Redis面试真题解析与答题技巧
  • 蓝牙AOA定位方案:重塑精准定位新纪元,赋能行业智能化升级
  • 16-day13强化学习和训练大模型
  • 深入理解 Roo Code 的自动批准功能
  • Node.js(1)—— Node.js介绍与入门
  • 从0开始学习Java+AI知识点总结-25.web实战(AOP)
  • 人工智能-python-深度学习-数据准备
  • 路径总和。
  • 同一性和斗争性
  • 使用 gemini api + 异步执行,批量翻译文档
  • 【Task04】:向量及多模态嵌入(第三章1、2节)
  • 解锁表格数据处理的高效方法-通用表格识别接口
  • sudo 升级
  • Spring Boot 项目打包成可执行程序
  • 3秒传输大文件:cpolar+Localsend实现跨网络秒传
  • 内核编译 day61
  • Ubuntu安装及配置Git(Ubuntu install and config Git Tools)
  • Linux 磁盘文件系统
  • 【银河麒麟桌面系统】PXE实现arm、x86等多架构安装
  • Linux-进程相关函数
  • Vulkan学到什么程度才算学会
  • 关系轮-和弦图的可视化