如何递归Hook所有被启动的进程?使用Java ProcessBuilder时Hook孙进程失败的问题求助
如何递归Hook所有被启动的进程?使用Java ProcessBuilder时Hook孙进程失败的问题求助
嘿,我之前也碰到过一模一样的问题!用Frida Hook的时候,主进程和直接子进程都能抓到,但子进程用ProcessBuilder启动的孙进程就完全没反应,折腾了好一阵才搞明白问题出在哪,给你分享下我的解决思路和修改后的代码。
首先得搞清楚为啥孙进程抓不到:你原来的脚本只在主进程加了事件监听,而且每个被Hook的进程里没有做任何跟踪自身启动新进程的操作——Frida不会自动递归跟踪所有子进程,除非我们在每个被Hook的进程里也注入代码,让它启动新进程时能被Frida的spawn事件捕获到。
下面是具体的解决步骤和修改后的代码:
核心思路
- 给每个被Hook的进程都注入脚本,Hook它的
ProcessBuilder.start()方法(如果是Java进程),或者底层的native fork/exec调用(如果是native进程),这样当这个进程启动新进程时,Frida能感知到并触发spawn-added事件。 - Python端只需要专心监听
spawn-added事件,每个新进程都重复注入包含Hook逻辑的脚本,形成递归跟踪的闭环。
修改后的完整代码
第一步:更新Frida JS脚本
我们要在JS里加入对ProcessBuilder的Hook,同时兼容非Java进程:
console.log('[+] Attached to process PID: ' + Process.id); // Hook Java ProcessBuilder,跟踪Java进程启动的新进程 Java.perform(() => { try { const ProcessBuilder = Java.use('java.lang.ProcessBuilder'); ProcessBuilder.start.implementation = function() { console.log(`[+] [PID:${Process.id}] 调用了ProcessBuilder.start()`); const result = this.start(); return result; }; } catch (e) { // 非Java进程会抛出异常,直接忽略就行 console.log('[!] 这不是Java进程,跳过ProcessBuilder Hook'); } }); // 可选:Hook Native层的fork函数,跟踪Native进程启动(根据目标架构调整) if (Process.arch === 'arm64' || Process.arch === 'arm') { const fork = Module.findExportByName(null, 'fork'); if (fork) { Interceptor.replace(fork, new NativeCallback(() => { console.log(`[+] [PID:${Process.id}] Native层调用了fork()`); const pid = new NativeFunction(fork, 'int', [])(); return pid; }, 'int', [])); } }
第二步:调整Python脚本逻辑
简化事件监听,专注处理spawn-added,同时确保每个新进程都注入上述脚本:
import sys import frida # 替换成你的目标APP包名或可执行文件路径 TARGET_APP = "com.example.targetapp" # 上面定义的JS脚本 js_hook_script = """ console.log('[+] Attached to process PID: ' + Process.id); Java.perform(() => { try { const ProcessBuilder = Java.use('java.lang.ProcessBuilder'); ProcessBuilder.start.implementation = function() { console.log(`[+] [PID:${Process.id}] 调用了ProcessBuilder.start()`); const result = this.start(); return result; }; } catch (e) { console.log('[!] 这不是Java进程,跳过ProcessBuilder Hook'); } }); if (Process.arch === 'arm64' || Process.arch === 'arm') { const fork = Module.findExportByName(null, 'fork'); if (fork) { Interceptor.replace(fork, new NativeCallback(() => { console.log(`[+] [PID:${Process.id}] Native层调用了fork()`); const pid = new NativeFunction(fork, 'int', [])(); return pid; }, 'int', [])); } } """ def handle_new_spawn(spawn_info): print(f"\n[+] 检测到新进程: [{spawn_info.identifier}] (PID: {spawn_info.pid})") try: # 附加到新进程 session = device.attach(spawn_info.pid) print(f"[+] 已附加到进程 {spawn_info.pid}") # 注入Hook脚本 script = session.create_script(js_hook_script) script.load() print(f"[+] 已为进程 {spawn_info.pid} 注入Hook脚本") # 恢复进程运行 device.resume(spawn_info.pid) print(f"[+] 已恢复进程 {spawn_info.pid} 运行") except Exception as e: print(f"[!] 处理进程 {spawn_info.pid} 失败: {str(e)}") # 初始化Frida设备 device = frida.get_usb_device() # 启用Spawn Gating,确保能在进程刚启动时捕获 device.enable_spawn_gating() # 监听所有新进程启动事件 device.on('spawn-added', handle_new_spawn) # 启动目标主进程 main_pid = device.spawn([TARGET_APP]) print(f"[+] 已启动主APP,PID: {main_pid}") # 附加并注入脚本 main_session = device.attach(main_pid) main_script = main_session.create_script(js_hook_script) main_script.load() device.resume(main_pid) print(f"[+] 已恢复主APP运行,等待新进程事件...") # 保持脚本运行 sys.stdin.read()
一些注意事项
- 确保你的Frida和Frida-server版本匹配,旧版本可能在spawn事件处理上有兼容性问题,建议更到最新版。
- 如果目标是root设备,确保Frida-server有足够的权限;如果是非root设备,目标APP需要是可调试的。
- 要是碰到纯Native进程启动的情况,JS里的Native Hook部分可以根据目标架构(x86、x64等)做相应调整。
内容来源于stack exchange
相关产品推荐
相关产品推荐

