# Hook 脚本运行与捕获约定(强制遵守) > 适用范围:本仓库所有 `scripts/hook_*.py` / `probe_*.py` / `scan_*.py` 的创建、修改与运行。 > 原则:**脚本挂上 hooks 后,用后台任务运行;数据实时写日志;目标数据一命中,立刻主动停止任务。绝不用 bash 前台 `sleep` 等超时结束再看结果。** ## 1. 运行方式(必须) - 启动:一律 `bash` 工具的 `run_in_background: true`,例如: ``` cd /Users/yml/codes/Reverse-Engineering-Agent-Universal-v3.0 && \ .venv/bin/python -u scripts/hook_xxx.py > /tmp/hook_xxx.log 2>&1 & ``` 脚本内部必须 `print(..., flush=True)`(或 `-u`),保证日志实时落盘。 - 观察:用 `bash` 前台 `tail -f /tmp/hook_xxx.log`(或 `grep` 关键字)实时查看日志,**不要** `sleep 120` 后一次性读。 - 停止:一旦日志中出现目标数据(`[hit]` / `[wire]` / `[FOUND]` 等命中标记),立即: ``` pkill -f hook_xxx.py # 或 job_kill 对应后台任务 ``` 保存 `evidence/*.json` 后即可分析。不需要等脚本自身的超时窗口走完。 - 配套交互:需要用户在手机上操作(退出登录→重新登录)时,脚本打印提示后立即进入等待,hook 数据实时刷日志;用户操作完成后我们随时 `tail` 查看,命中即杀。 ## 2. 脚本自身结构(必须) - 主循环用 `time.sleep(5)` 轮询,但**每条捕获都立即 `send()`**,`on_message` 里 `print(flush=True)`。 - 超时窗口(如 150s)只是兜底,不是等待方式:数据命中即可提前退出(`pkill`/`job_kill`)。 - 捕获结果写 `evidence/` 下 JSON:`script.on('message')` 全程收集事件,退出前统一落盘;但如果提前被杀,落盘逻辑可能不执行 —— 因此**命中即打印+写入**:`on_message` 里命中类型直接 `OUT` 文件追加写入,保证被杀前数据已持久化。 - 统一模块:`RE = Path("/Users/yml/codes/Reverse-Engineering-Agent-Universal-v3.0")`(frida 环境 + bypass 脚本在此)。 - 设备连接:`frida.get_device_manager().add_remote_device("127.0.0.1:31877")`(设备上 frida-server 14.2.18 监听 0.0.0.0:31877,macOS 侧 `adb forward tcp:31877 tcp:31877`)。 - spawn 流程(稳定版,参考 `hook_genbiz.py`): 1. `device.spawn(["com.duowan.kiwi"])` 2. 加载 `bypass_msaoaid_maps_art_callsite.js` 3. 加载 `mask_frida_maps_only.js` 4. `device.resume(pid)`,`sleep 11` 5. 加载 `patch_guard_block_termination.js` 6. 再 `create_script` 主 hook JS - 注意:**不要直接 attach 运行中的 kiwi 进程**(App 有 msaoaid 反调试,attach 会被杀/闪退);必须 spawn + 三件套 bypass。 - 注意:脚本里的 JS 若在 `resume` 前 `load()`,目标 so 尚未加载,hook 会落空 —— 模块相关枚举/attach 用 `setInterval` 轮询或放在 resume+11s 之后。 ## 3. 常见坑 - `frida-ps -U` 正常但 remote spawn 报 `TransportError`:检查 `adb forward --list`,必须 `tcp:31877 -> tcp:31877`。 - 设备上会同时存在多个 kiwi 进程(主进程 + cloudpatch/logcat 子进程);**hook 必须挂在我们 spawn 的主进程 pid 上**,用户手动操作的若为旧实例,hook 会空转(日志 0 命中)。操作前先 `am force-stop com.duowan.kiwi` 清掉旧实例。 - datadiv 导出名是 `.datadiv_decode...`(带点前缀),匹配用 `name.indexOf('datadiv') >= 0`,不要用 `=== 0`。 - `libhydeviceid.so` 业务符号全部混淆/内部化(只导出 `hy_*` syscall 包装 + JNI_OnLoad),dfpReport 加密体生成函数不在导出表;静态搜不到魔数 `571882cf664bb39401ee` 属正常(运行时拼装)。