Frida拦截fork后钩子SSL_write时仅生效于子进程,如何同时钩子父子进程的SSL_write?
Frida拦截fork后钩子SSL_write时仅生效于子进程,如何同时钩子父子进程的SSL_write?
兄弟,我懂你遇到的这个坑!之前我也碰过类似的情况——fork之后父子进程是完全独立的执行空间,Frida的hook不会自动在父子进程中都生效,你之前的代码只在子进程里hook了SSL_write,大概率是因为你只在fork完成后的子进程上下文里执行了hook逻辑,而父进程的SSL_write从始至终都没被正确hook上。
给你两个关键点解决这个问题:
- 父进程的SSL_write要提前hook:在脚本一开始初始化的时候,就把父进程的SSL_write hook好,别等fork发生了再处理,这样父进程的SSL_write从脚本运行开始就会被拦截。
- 子进程的SSL_write要单独部署hook:fork完成后,子进程是全新的进程空间,虽然会继承父进程的内存,但Frida的hook绑定是和进程上下文关联的,所以需要在子进程的专属上下文里再执行一次hook逻辑。Frida提供了
Script.runInChild()API,能帮你在指定的子进程中执行代码,刚好适合这个场景。
话不多说,直接给你调整后的代码,你可以直接用:
首先定义一个通用的hook SSL_write的函数,这样父子进程的hook逻辑可以复用,不用写两遍:
function hookSSLWrite() { // 先确保libssl模块已经加载,避免找不到函数 Module.ensureInitialized("libssl.so"); const sslWriteAddr = Module.findExportByName("libssl.so", "SSL_write"); if (sslWriteAddr) { Interceptor.attach(sslWriteAddr, { onEnter: function(args) { console.log(`[PID ${Process.id()}] SSL_write 被调用啦,参数fd: ${args[0]}`); // 这里可以加你自己的业务逻辑,比如打印参数、修改返回值之类的 }, onLeave: function(retval) { console.log(`[PID ${Process.id()}] SSL_write 返回值: ${retval.toInt32()}`); } }); console.log(`[PID ${Process.id()}] 成功hook SSL_write`); } else { console.log(`[PID ${Process.id()}] 没找到SSL_write函数,可能模块没加载?`); } }
然后是主脚本部分:
// 脚本一启动,先把父进程的SSL_write给hook了 hookSSLWrite(); // 拦截fork函数 Interceptor.attach(Module.findExportByName("libc.so", "fork"), { onEnter: function(args) { try { const callerModule = Process.getModuleByAddress(this.returnAddress); console.log(`[*] fork被调用啦,调用者模块: ${callerModule.name},地址: ${this.returnAddress}`); console.log(`[*] 模块路径: ${callerModule.path}`); } catch (err) { console.log(`[!] 解析调用模块出错啦: ${this.returnAddress}, 错误信息: ${err}`); } }, onLeave: function(retval) { const childPid = retval.toInt32(); console.log(`[*] fork执行完成,子进程PID: ${childPid}`); // 分情况处理:父进程上下文和子进程上下文 if (childPid > 0) { // 这里是父进程的上下文,用runInChild在子进程中执行hook Script.runInChild(childPid, { timeout: 0 }, function() { hookSSLWrite(); }); } else if (childPid === 0) { // 这里是子进程的上下文,直接执行hook hookSSLWrite(); } } });
为什么这样能行?
- 脚本启动时就调用
hookSSLWrite(),父进程的SSL_write直接被hook,后续父进程的所有SSL_write调用都会被拦截。 - fork完成后,父进程上下文里用
Script.runInChild()把hook逻辑注入到子进程中,子进程的SSL_write也会被hook上;同时考虑到有些情况下Frida会在子进程中触发onLeave(childPid为0的情况),这里也做了兼容,确保子进程的hook万无一失。
另外提醒你一句:如果你的目标程序是延迟加载libssl.so的(比如用到的时候才加载),那hookSSLWrite里的Module.ensureInitialized("libssl.so")一定要加上,确保能找到SSL_write的地址,不然可能会出现找不到函数的情况。
内容来源于stack exchange
相关产品推荐
相关产品推荐

