JavaScript
连接 Node.js 进程的 V8 虚拟机注入任意 JS 代码
// 获取 libuv 函数指针
const uv_default_loop = new NativeFunction(Module.getExportByName(null, 'uv_default_loop'), 'pointer', []);
const uv_async_init = new NativeFunction(Module.getExportByName(null, 'uv_async_init'), 'int', ['pointer', 'pointer', 'pointer']);
const uv_async_send = new NativeFunction(Module.getExportByName(null, 'uv_async_send'), 'int', ['pointer']);
const uv_close = new NativeFunction(Module.getExportByName(null, 'uv_close'), 'void', ['pointer', 'pointer']);
const uv_unref = new NativeFunction(Module.getExportByName(null, 'uv_unref'), 'void', ['pointer']);
// 获取 V8 引擎函数指针
const v8_Isolate_GetCurrent = new NativeFunction(Module.getExportByName(null, '_ZN2v87Isolate10GetCurrentEv'), 'pointer', []);
const v8_Isolate_GetCurrentContext = new NativeFunction(Module.getExportByName(null, '_ZN2v87Isolate17GetCurrentContextEv'), 'pointer', ['pointer']);
// 获取 V8 句柄作用域函数
const v8_HandleScope_init = new NativeFunction(Module.getExportByName(null, '_ZN2v811HandleScopeC1EPNS_7IsolateE'), 'void', ['pointer', 'pointer']);
const v8_HandleScope_finalize = new NativeFunction(Module.getExportByName(null, '_ZN2v811HandleScopeD1Ev'), 'void', ['pointer']);
// 获取 V8 字符串处理函数
const v8_String_NewFromUtf8 = new NativeFunction(Module.getExportByName(null, '_ZN2v86String11NewFromUtf8EPNS_7IsolateEPKcNS_13NewStringTypeEi'), 'pointer', ['pointer', 'pointer', 'int', 'int']);
// 获取 V8 脚本编译执行函数
const v8_Script_Compile = new NativeFunction(Module.getExportByName(null, '_ZN2v86Script7CompileENS_5LocalINS_7ContextEEENS1_INS_6StringEEEPNS_12ScriptOriginE'), 'pointer', ['pointer', 'pointer', 'pointer']);
const v8_Script_Run = new NativeFunction(Module.getExportByName(null, '_ZN2v86Script3RunENS_5LocalINS_7ContextEEE'), 'pointer', ['pointer', 'pointer']);
// 字符串类型枚举
const NewStringType = {
kNormal: 0, // 普通字符串
kInternalized: 1 // 内部化字符串
};
const pending = []; // 待执行脚本队列
// 异步回调处理函数
const processPending = new NativeCallback(function () {
const isolate = v8_Isolate_GetCurrent(); // 获取当前 V8 隔离实例
const scope = Memory.alloc(24); // 分配句柄作用域内存
v8_HandleScope_init(scope, isolate); // 初始化句柄作用域
const context = v8_Isolate_GetCurrentContext(isolate); // 获取当前上下文
// 执行队列中的所有脚本
while (pending.length > 0) {
const item = pending.shift();
const source = v8_String_NewFromUtf8(isolate, Memory.allocUtf8String(item), NewStringType.kNormal, -1);
const script = v8_Script_Compile(context, source, NULL);
const result = v8_Script_Run(script, context);
}
v8_HandleScope_finalize(scope); // 释放句柄作用域
}, 'void', ['pointer']);
// 关闭回调函数
const onClose = new NativeCallback(function () {
Script.unpin(); // 解除内存固定
}, 'void', ['pointer']);
// 初始化异步句柄
const handle = Memory.alloc(128);
uv_async_init(uv_default_loop(), handle, processPending);
uv_unref(handle);
// 设置弱引用回调
Script.bindWeak(handle, () => {
Script.pin(); // 固定内存防止GC
uv_close(handle, onClose); // 关闭句柄
});
// 脚本执行函数
function run(source) {
pending.push(source); // 加入执行队列
uv_async_send(handle); // 触发异步执行
}
// 示例:注入并执行代码
run('console.log("通过Frida注入执行");');
追踪 Perl 5 进程中的函数调用
const pointerSize = Process.pointerSize; // 获取指针大小
const SV_OFFSET_FLAGS = pointerSize + 4; // SV 结构体 flags 偏移量
const PVGV_OFFSET_NAMEHEK = 4 * pointerSize; // PVGV 结构体名称偏移量
const SVt_PVGV = 9; // 类型标识:GV (Glob Value)
// 挂钩 Perl 的函数入口点
Interceptor.attach(Module.getExportByName(null, 'Perl_pp_entersub'), {
onEnter(args) {
const interpreter = args[0]; // Perl 解释器指针
const stack = interpreter.readPointer(); // 读取调用栈
const sub = stack.readPointer(); // 获取被调函数
const flags = sub.add(SV_OFFSET_FLAGS).readU32(); // 读取类型标志
const type = flags & 0xff; // 提取类型标识
if (type === SVt_PVGV) {
/*
* 注意:此处 console.log() 会影响性能,
* 实际应用中应使用 send() 批量发送事件
*/
console.log(GvNAME(sub) + '()'); // 输出函数名
} else {
// 其他类型暂不处理
}
}
});
// 获取 GV 名称
function GvNAME(sv) {
const body = sv.readPointer(); // 读取 GV 主体
const nameHek = body.add(PVGV_OFFSET_NAMEHEK).readPointer(); // 获取名称指针
return nameHek.add(8).readUtf8String(); // 读取 UTF-8 字符串
}
欢迎点击上方"改进此页面"提交更多示例代码!
关键术语说明:
libuv - Node.js 使用的跨平台异步 I/O 库
V8 Isolate - V8 引擎的独立实例环境
HandleScope - V8 的句柄作用域管理
PVGV - Perl 的全局变量值结构
弱引用(Weak Reference) - 不影响垃圾回收的对象引用
原文链接:JavaScript | Frida • A world-class dynamic instrumentation toolkit
翻译来源:DeepSeek