Files
reverse-skills-max/vendor-new/js-reverse-automation--skill/js-reverse-automation/references/evidence-collection.md

338 lines
12 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 证据收集规则
本文说明 JS 逆向自动化中的证据收集方法:网络捕获、软 Hook、源码定位和运行时 Hook 跟踪,并规定证据强度、记录方式与风险控制。
---
## 1. 网络捕获
### 适用场景
- 确认目标参数位于 URL、请求头、Cookie、JSON 请求体还是表单请求体。
- 页面动作触发多个相似请求,需要缩小到真正参与签名或加密的请求。
- 用户提供了 Optional Fetch Example,需要映射到真实浏览器请求。
### 证据优先级
1. 真实页面动作触发的网络记录。
2. 请求详情:方法、URL、请求头、请求体和响应。
3. 页面内观察代码输出:调用栈、序列化对象和函数参数。
4. 控制台日志与页面状态快照。
### 推荐流程
1. 打开目标页面并完成必要交互,确认请求确实发出。
2. 使用 chrome-devtools-mcp 的网络请求列表筛选候选请求。
3. 读取每个候选请求的详情,确认目标参数位置和请求体结构。
4. 请求较多时,按以下条件缩小范围:
- 是否出现目标参数。
- 请求触发时间是否接近用户动作。
- 响应状态是否符合业务预期。
- 请求体是否同时包含未加密明文和加密结果等相邻字段。
5. 锁定请求后立即记录:
- 请求 URL。
- HTTP 方法。
- Content-Type。
- 参数位置。
- 关键请求头。
- 触发动作。
6. 请求详情不足以定位源码时,再增加最小观察代码或最小 Hook。
### 成功标准
- 至少一个请求被明确标记为目标请求。
- 每个待分析参数的位置已知。
- 已记录足以支持后续源码定位的请求上下文。
### 失败信号
- 只能看到静态资源请求,看不到业务 API。
- 目标动作触发大量相似请求,无法区分签名参与者。
- 能看到请求,但无法确认参数经过哪一层序列化后出现。
### 处理策略
- 多请求竞争时只改变一个输入值,观察哪个请求字段同步变化。
- 序列化不透明时,对以下边界增加最小 Hook:
- window.fetch
- XMLHttpRequest.prototype.open
- XMLHttpRequest.prototype.send
- JSON.stringify
- 页面会刷新时,通过 evaluate_script 注入;需要在刷新前生效时,使用 navigate_page(initScript=...) 预注入。
- Hook 的目的只是记录“发送前最后一个可观察形态”,不能替代网络证据。
---
## 2. 软 Hook 规则
### 适用范围
- 网络证据已锁定目标请求,但仍缺少入口函数证据。
- 需要确认参数在某个函数调用前后是否发生变化。
- 需要确认返回值、this 绑定、异步行为或全局依赖。
### 最小 Hook 原则
- 先 Hook 通用边界,再 Hook 业务函数。
- 先记录后改写,默认不替换原函数。
- 每个 Hook 只增加一个观察点,避免多个 Hook 同时污染证据。
- 页面已加载时,优先使用 evaluate_script 注入。
- 页面将刷新或导航时,使用 navigate_page(initScript=...) 预注入。
### 推荐 Hook 顺序
1. window.fetch
2. XMLHttpRequest.prototype.open
3. XMLHttpRequest.prototype.send
4. JSON.stringify
5. 已明确匹配的业务函数
6. 必要时再补充 eval、Function 或 Promise 相关节点
### 每个 Hook 至少记录
- Hook 点路径。
- 匹配条件。
- 输入参数摘要。
- 返回值摘要。
- 调用栈摘要。
- 是否改变页面行为。
- 注入方式:evaluate_script 或 navigate_page(initScript=...)。
### 入口确认规则
业务函数 Hook 至少要证明以下一项:
- 明文输入与请求中的目标参数存在可验证映射。
- 函数返回值直接进入请求体、请求头或 Cookie。
只看到密码库内部调用、没有业务调用者上下文,不能认定为最终入口。
### 依赖提取规则
明确记录:
- this 绑定来源。
- 依赖的全局对象或闭包对象。
- 是否需要等待异步结果。
- 页面是否必须先完成启动流程。
这些信息最终写入 artifacts/phase3_dependencies.json 和 analysis_result.json。
### 风险控制
- 默认不要冻结大量原型。
- 不要为了方便观察而全局替换所有密码学 API。
- Hook 导致业务分支改变时,先回退到更小范围,再继续分析。
---
## 3. 源码定位
### 核心原则
- 先从请求详情、页面内调用栈和序列化节点回溯,再进行关键词搜索。
- 先找“参数最后一次发生变化的位置”,再找“最深层算法位置”。
- 只接受有证据支持的源码定位结果,不接受纯文本匹配结论。
### 定位优先级
1. 请求详情、页面内 Error().stack 或观察代码捕获的调用栈。
2. 发送前对象构造或序列化位置。
3. 与参数同名或相邻的源码片段。
4. 密码库调用位置。
### 推荐流程
1. 从目标请求开始,确认请求方法、请求体和相关脚本线索。
2. 在请求构造处加入最小观察代码:
- 观察 fetch / XHR send。
- 观察 JSON.stringify。
- 在页面内输出 Error().stack。
3. 页面刷新或导航时:
- 使用 navigate_page(initScript=...) 预注入。
- 重新触发目标动作并记录序列化前对象。
4. 标记参数的三个关键位置:
- 明文入口。
- 处理或加密位置。
- 发送前最终写入位置。
5. 只有其中至少两个位置被证据串联后,才能输出首选入口。
### 候选入口接受标准
- 能解释参数从明文到密文的变化。
- 能定位可调用函数或稳定解析器。
- 能解释 this 绑定、参数签名和必要依赖。
### 常见误判
- 只匹配到参数名,但变量只是中间副本。
- 只匹配到 md5、aes 或 sha,但它并不服务于目标请求。
- 只看到包装函数,没有继续确认真实执行点。
### 输出要求
- source_hint 尽量落到具体 bundle 位置或对象路径。
- evidence 至少包含以下一项:
- 页面内调用栈。
- Hook 捕获的输入参数和返回值。
- 序列化前对象快照。
- 参数值对照实验结果。
---
## 4. 运行时 Hook 跟踪
### 概述
运行时 Hook 使用预注入探针,在网络、密码学和序列化层捕获证据,是入口发现的重要证据源。
### 探针安装
生成:
~~~bash
python3 scripts/emit_runtime_hook_probe.py --output generated/runtime_hook_probe.js --params "target_param1,target_param2"
~~~
注入方式:
- 页面已加载时使用 evaluate_script。
- 页面会刷新或导航时使用 navigate_page(initScript=...)。
幂等性:
- 探针安装前检查 window.__JSRA_TRACE__,重复注入应安全地跳过。
### 探针捕获内容
探针在以下边界安装软 Hook,并将证据写入 window.__JSRA_TRACE__。
#### 4.1 网络请求(requests[])
- Hook 点:window.fetch、XMLHttpRequest.prototype.open、XMLHttpRequest.prototype.send。
- 每条记录包括:
- type:fetch 或 xhr。
- url:请求 URL。
- method:HTTP 方法。
- headers:摘要后的请求头。
- bodySnippet:截断后的请求体。
- timestamp:Date.now()。
- stack:通过 Error().stack 捕获的调用栈,最多 10 帧。
#### 4.2 密码学事件(crypto[])
- Hook 点:crypto.subtle.digest、sign、encrypt、decrypt。
- 每条记录包括:
- type:digest、sign、encrypt 或 decrypt。
- algorithm:算法名称。
- inputLen:输入字节数。
- outputLen:Promise 完成后的输出字节数。
- outputHex:摘要结果前 32 个十六进制字符,仅用于 digest。
- timestamp:Date.now()。
- stack:调用栈,最多 10 帧。
#### 4.3 序列化事件(serializers[])
- Hook 点:FormData.append、FormData.set、URLSearchParams.append、URLSearchParams.set、URLSearchParams.toString、JSON.stringify。
- 每条记录包括:
- type:序列化方法名。
- name:字段名。
- valueSnippet 或 resultSnippet:截断后的值。
- keys:JSON.stringify 对象的键,最多 20 个。
- timestamp:Date.now()。
- stack:JSON.stringify 和 URLSearchParams.toString 的调用栈。
#### 4.4 选择性 JSON.stringify Hook
- 只有待序列化对象包含目标参数或敏感字段时才记录。
- 敏感字段包括 sign、token、enc、password、signature、hash、key、nonce、timestamp、ts、data、encrypt、decrypt。
- 这样可以避免无关序列化调用造成日志洪泛。
### 读取证据
导出全部证据:
~~~js
evaluate_script("window.__JSRA_TRACE__.dump()")
~~~
返回包含 requests、crypto、serializers、errors 的 JSON 字符串。
清空证据缓存:
~~~js
evaluate_script("window.__JSRA_TRACE__.clear()")
~~~
### 使用证据发现入口
1. 从 requests[].stack 中寻找加密或签名函数调用帧,这些帧指向业务调用者,而不仅是密码库。
2. 与序列化事件交叉比对:如果 serializers[] 显示 JSON.stringify 或 URLSearchParams.toString 处理了关注字段,调用栈可以定位请求体组装位置。
3. 将密码学算法和请求体对应:crypto[] 中的 digest 或 encrypt 事件,应与请求体中的密文长度和算法相匹配。
4. 从调用栈提取最外层业务函数,排除 fetch、XMLHttpRequest 和密码库内部函数,作为候选入口。
### 运行时跟踪的证据标准
- 高置信度:至少一条经过业务函数的 requests[] 调用栈,以及一条与目标参数相关的 crypto[] 或 serializers[] 事件。
- 中置信度:至少一条 bodySnippet 中出现目标参数的 requests[] 记录,即使调用栈未明确指向业务函数。
- 仅有密码库内部调用、没有业务调用者上下文,不能达到高置信度。
### 失败处理
| 现象 | 处理方式 |
|---|---|
| 探针注入失败(被反调试阻断) | 记录反调试现象,参阅反调试规则,降级到静态分析 |
| 触发目标动作后没有 requests[] | 确认动作确实执行,并检查探针是否注入到正确执行上下文 |
| crypto[] 为空但请求体包含密文 | 可能使用非 Subtle 密码库,使用 CryptoJS/JSEncrypt Hook 规则 |
| stack 全部匿名或已混淆 | 使用源码定位规则,将调用栈与 bundle 行号关联 |
### 风险提示
- 探针不能替代网络证据,只能补充网络证据。
- 探针使用软包装,不应替换原函数或破坏页面功能。
- Hook 造成计时变化时,先记录未启用 Hook 的基线,再记录启用后的观察结果。
- 探针不会自动跨页面导航持久化,页面刷新后需要通过 initScript 重新注入。
---
## 5. 跨场景证据标准
### 证据层级
1. 网络证据:请求 URL、方法、请求体、请求头和响应,强度最高。
2. 运行时 Hook 证据:调用栈、密码学事件和序列化事件,强度较高。
3. 源码证据:bundle 位置、对象路径和关键词匹配,仅作为辅助。
### 置信度要求
| 置信度 | 最低证据 |
|---|---|
| high | 网络证据 + 运行时/调用栈/模块证据,至少两类 |
| medium | 单一证据源(网络或运行时) |
| low | 仅有关键词搜索或源码模式 |
### 可计入证据的内容
- 运行时探针产生的 requests[],且调用栈经过业务函数。
- 能将算法和输出长度与实际密文对应的 crypto[] 事件。
- 显示参数在请求发送前被序列化的 serializers[] 事件。
- evaluate_script 捕获并指向业务调用者的 Error().stack。
- 能将明文映射到密文的 Hook 输入/输出对。
- 只改变一个输入值后,能证明哪个请求字段随之变化的实验结果。
### 不可单独计入证据的内容
- 没有运行时关联的源码关键词匹配。
- 没有业务调用者上下文的密码库函数匹配。
- 存在于全局对象上、但目标动作期间从未被观察到调用的路径。
- 没有调用栈、Hook 或网络确认的疑似入口。
### 记录要求
每条证据必须包含:
- 来源类型:网络、Hook、调用栈、序列化、密码学或实验。
- 时间戳或序列号。
- 足以复现观察的上下文:URL、方法、Hook 点路径和调用栈。
- 观察发生时是否启用了补丁或 Hook。