From 5d73e05e893de98bf939be426eb561ee1169289e Mon Sep 17 00:00:00 2001 From: yhc <1964366186@qq.com> Date: Wed, 12 Aug 2026 11:57:38 +0800 Subject: [PATCH 1/2] fix(workflow): IAT repair iron rule + vuln thin overlay (issue #65) - Map reporter six-phase malware RE flow into re-agent-workflow with IAT repair fail-fast (E-iat-repair-fail -> dynamic API breakpoints) - Equivalent import anchors for .NET; E-exports for DLL/SYS; clean IAT and sandbox no-behavior side paths - Wire radare2/ida/malware hard gates + RULES/obedience rebuttals - Add optional thin vuln report overlay (not a 3rd default full flavor) - Extend verify-routing-coherence assertions; smoke+verify x3 pass --- RULES.md | 2 + RULES_zh.md | 2 + skills/docs-generator/SKILL.md | 11 +- .../references/security-report-templates.md | 16 ++- .../references/vendor-report-rules.md | 55 ++++++++- skills/ida-reverse/SKILL.md | 8 +- .../references/agent-obedience-engineering.md | 2 + skills/malware-analysis/SKILL.md | 38 ++++++- skills/radare2/SKILL.md | 13 ++- .../references/re-agent-workflow.md | 106 ++++++++++++++---- skills/scripts/verify-routing-coherence.ps1 | 16 ++- 11 files changed, 224 insertions(+), 45 deletions(-) diff --git a/RULES.md b/RULES.md index b319a4a..ec0f417 100644 --- a/RULES.md +++ b/RULES.md @@ -217,6 +217,8 @@ After task completion (vulnerability verified / reverse complete / flag captured | "I'll reply to user first, continue after confirmation" | **Don't wait for confirmation on deterministic steps.** Execute while informing user. Only pause at genuine decision points. | | "I understand the rules, please tell me your task" | **This is the WORST failure mode.** Correct behavior: proactively match user intent to routing table, output analysis, start executing. | | "User asked to redo import-table / step X, but I did something else more useful" | **Redo = redo the named step.** When user asks to redo X (e.g. import table check), MUST re-execute X and refresh its Evidence. FORBIDDEN to substitute another step or silently skip X. | +| "IAT repair keeps failing; I'll grind more static unpackers" | **IAT repair iron rule:** try auto/semi-auto repair first; on tool error or unreable binary after repair, STOP static IAT, record E-iat-repair-fail, switch to dynamic API breakpoints. FORBIDDEN infinite static IAT thrash. | +| "No import table (.NET) so the hard gate does not apply" | **Equivalent anchor still MUST:** .NET → dnSpy/IL/metadata summary into E-imports slot; DLL/SYS → E-exports alongside imports. FORBIDDEN to skip the gate. | --- diff --git a/RULES_zh.md b/RULES_zh.md index 1fc2438..502251e 100644 --- a/RULES_zh.md +++ b/RULES_zh.md @@ -316,6 +316,8 @@ AI Agent 在遇到阻力时会自动生成"合理借口"来跳过步骤。以下 | "我先回复用户,等用户确认后再继续" | **不需要等确认。** 如果路由已明确且下一步是确定性的(如安装工具、读取文件),直接执行同时告知用户。不要在每一步都等用户点头。 | | "我理解了规则,请告诉我你的具体任务" | **这是最严重的失败模式。** 读完规则后的正确行为是主动匹配用户意图到路由表,输出分析,开始执行。不是回传问题给用户。 | | "用户让我重做导入表/某一步,但我改做了别的更有用的步骤" | **重做 = 重做被点名的同一步。** 用户要求重做 X(如导入表检查)时 MUST 重新执行 X 并更新对应 Evidence;禁止用其他步骤冒充完成,禁止静默跳过 X。 | +| "IAT 修不好,我再静态试几种壳工具拖时间" | **IAT 修复铁律:** 优先自动/半自动修复;工具报错或修完无法运行 → 立即停静态 IAT,记 E-iat-repair-fail,转动态 API 断点抓取。禁止无限静态死磕。 | +| ".NET / 没导入表,硬门不适用,我跳过" | **等价锚点仍 MUST:** .NET 用 dnSpy/IL/元数据摘要写入 E-imports 语义槽;DLL/SYS 必须并列 E-exports。禁止空过。 | > 如果你发现自己在想以上任何一句话,停下来,回到行为链中正确的步骤,继续执行。 diff --git a/skills/docs-generator/SKILL.md b/skills/docs-generator/SKILL.md index 59ac0cf..ea0e911 100644 --- a/skills/docs-generator/SKILL.md +++ b/skills/docs-generator/SKILL.md @@ -43,13 +43,14 @@ For writing style, tone, and voice guidance, use `Skill(ce:writer)` with **The E 安全类正式报告 **MUST** 读取 `references/vendor-report-rules.md`(只取结构,不抄厂商原文)。仅在任务证据或用户明确要求时选择厂商 flavor;普通逆向和其他任务使用 `flavor = null`。 -| Flavor | 何时用 | 主参考骨架 | -|--------|--------|------------| +| Flavor / Overlay | 何时用 | 主参考骨架 | +|------------------|--------|------------| | `malware` | 明确恶意样本、木马、白加黑、钓鱼投毒 | 火绒式:概述→流程→样本分析→应急处置→IOC | | `apt` | APT/战役/团伙/多阶段感染链/行业定向 | 卡巴斯基 Securelist 式:摘要→感染链→调查叙事→Interesting findings→技术分析→检测缓解→IOC | | `flavor = null` | 普通 APK/ELF/PE/Mach-O 逆向、算法/固件分析、渗透 / CTF / JS 签名 | 原任务模板 + Base 通用元素;不套 malware/APT 专属章节 | +| thin `vuln` | 用户明确要求漏洞/补丁/CVE 技术分析 | 概述→影响/复现→崩溃与补丁分析→防护建议(叠加在 null 上,非第 3 默认全文 flavor) | -原则:**模板在精不在多** —— 仅上述 2 个厂商 flavor,不另建第三套全文模板。 +原则:**模板在精不在多** —— 仅 2 个厂商全文 flavor;`vuln` 仅为可选 thin overlay,不另建第三套默认全文模板。 与 §0 Evidence→Finding→Path **同时生效**;冲突时 Evidence 契约优先。 ### 输出规范 @@ -68,7 +69,7 @@ For writing style, tone, and voice guidance, use `Skill(ce:writer)` with **The E - 复现步骤必须让第三方能独立重现 - 敏感信息(真实 token、密码、内部 URL)用占位符替代 - **MUST** 包含 Evidence → Finding → Path 链(见 `../ops/evidence-finding-path.md` 与模板 §0) -- **MUST** 读取 `references/vendor-report-rules.md`:选定 `malware` / `apt` 或 `flavor = null`;无 flavor 时只输出原任务模板和适用的 Base 元素,不强制 IOC/ATT&CK +- **MUST** 读取 `references/vendor-report-rules.md`:选定 `malware` / `apt` 或 `flavor = null`(漏洞任务可叠加 thin `vuln`);无 flavor 时只输出原任务模板和适用的 Base 元素,不强制 IOC/ATT&CK - **SHOULD** 引用 case `scope.md` / `timeline.md`(`../scripts/case-init.ps1`) ### 图表集成 @@ -177,7 +178,7 @@ For README, API endpoint, and file organization templates, see [references/templ - `field-journal/` — 报告内容同时作为进化日志的数据来源 **安全报告模板**: `references/security-report-templates.md` -**厂商报告规则**: `references/vendor-report-rules.md`(flavor: malware | apt | null) +**厂商报告规则**: `references/vendor-report-rules.md`(flavor: malware | apt | null;optional overlay: vuln) **通用文档模板**: `references/templates.md` diff --git a/skills/docs-generator/references/security-report-templates.md b/skills/docs-generator/references/security-report-templates.md index d72992c..288a3c5 100644 --- a/skills/docs-generator/references/security-report-templates.md +++ b/skills/docs-generator/references/security-report-templates.md @@ -36,13 +36,14 @@ > 全文规则:`references/vendor-report-rules.md`(Issue #65) > **MUST** 在生成安全类正式报告时读取并选型;**只抽结构,禁止抄录厂商原文/IOC 实例**。 -| Flavor | 场景 | 骨架一句话 | -|--------|------|------------| +| Flavor / Overlay | 场景 | 骨架一句话 | +|------------------|------|------------| | `malware` | 明确恶意样本/普通木马/白加黑 | 火绒式:概述→流程→样本分析→应急处置→IOC | | `apt` | APT/战役/多阶段链 | 卡巴式:摘要→感染链→调查→Interesting findings→技术分析→检测缓解→IOC | | `flavor = null` | 普通逆向/渗透/CTF/JS 签名 | 本节任务模板 + 适用的 Base 通用元素 | +| thin `vuln` | 漏洞/补丁/CVE 技术分析(显式) | 概述→影响/复现→崩溃与补丁分析→防护建议 | -**通用元素(G1–G7)摘要**:G1 执行摘要 MUST · G2 Scope MUST · G3 E/F/P MUST · G4 IOC 仅 `malware`/`apt` MUST · G5 建议仅 `malware`/`apt` MUST · G6 附录 SHOULD · G7 ATT&CK 在 `apt` MUST +**通用元素(G1–G7)摘要**:G1 执行摘要 MUST · G2 Scope MUST · G3 E/F/P MUST · G4 IOC 仅 `malware`/`apt` MUST · G5 建议在 `malware`/`apt`/`vuln` MUST · G6 附录 SHOULD · G7 ATT&CK 在 `apt` MUST 选型与章节顺序以 `vendor-report-rules.md` 为准;与 §0.1–0.5 冲突时 **Evidence 契约优先**。 @@ -130,6 +131,15 @@ 3. 仍 **MUST** 含 §0 Evidence 链;`malware` / `apt` flavor 另 **MUST** 含 IOC 表 4. 二进制样本的静态分析 **MUST** 含导入表 Evidence(与 radare2/ida/malware 硬门一致) +## 1c. 漏洞技术分析报告(thin `vuln` overlay) + +当任务为 **OS/组件漏洞、补丁对比、CVE 技术分析**,或用户明确要求「漏洞技术分析报告」时: + +1. 读 `vendor-report-rules.md` §3b,使用 thin `vuln` 章节顺序(**不是** malware/apt 全文 flavor) +2. **MUST** 含:影响范围、授权内复现或明确 n/a、崩溃/根因或补丁差异 Evidence、防护/补丁建议 +3. **MUST** 含 §0 Evidence→Finding→Path +4. **MUST NOT** 在未授权目标上扩展 PoC,或抄录外部利用武器化细节 + ## 2. 渗透测试报告模板 ```markdown diff --git a/skills/docs-generator/references/vendor-report-rules.md b/skills/docs-generator/references/vendor-report-rules.md index ab0ad5b..f18ec60 100644 --- a/skills/docs-generator/references/vendor-report-rules.md +++ b/skills/docs-generator/references/vendor-report-rules.md @@ -11,7 +11,7 @@ | `malware` | 火绒安全病毒/技术分析报告 | 明确的普通木马、白加黑、钓鱼投毒、恶意样本 | | `apt` | 卡巴斯基 Securelist / APT 战役报告(如 MATA) | APT、团伙战役、多阶段感染链、行业定向 | -原则:**模板在精不在多** —— 仅 2 个厂商 flavor + 1 份通用专业元素;普通逆向、渗透、CTF 和 JS 报告保持任务模板,不默认伪装成恶意软件报告。 +原则:**模板在精不在多** —— 仅 2 个厂商全文 flavor(`malware` / `apt`)+ Base 通用元素 + **可选 thin overlay**(如 `vuln` 漏洞技术分析)。普通逆向、渗透、CTF 和 JS 报告保持任务模板,不默认伪装成恶意软件报告;`vuln` **不是** 第 3 个默认全文 flavor。 --- @@ -19,13 +19,15 @@ 在 `docs-generator` 生成**安全类**报告时(逆向 / 恶意软件 / 渗透收尾 / 用户明确要求「专业报告」「厂商风格」)**MUST** 读取本文件。只有任务证据或用户明确要求支持时才选择厂商 flavor;否则使用 `flavor = null`,仅叠加通用专业元素和原任务模板。 -| 信号 | Flavor | -|------|--------| +| 信号 | Flavor / Overlay | +|------|------------------| | APT / 团伙 / 战役 / 多阶段 C2 / 行业定向 / ICS / spear-phish 战役 | `apt` | | 明确恶意样本、木马、窃密、白加黑、仿冒站点 | `malware` | +| 用户明确要求漏洞/补丁/CVE 技术分析,或任务证据为 OS/组件漏洞研究 | `flavor = null` + **thin overlay `vuln`**(见 §3b) | | 普通 APK/ELF/PE/Mach-O 逆向、算法分析、固件分析、渗透测试、CTF、JS 签名 | `flavor = null`;使用原任务模板和通用专业元素最小集 | -用户显式指定「按卡巴/APT」「按火绒/病毒报告」时,覆盖自动选型。 +用户显式指定「按卡巴/APT」「按火绒/病毒报告」「按漏洞技术分析」时,覆盖自动选型。 +**禁止** 把普通 malware/APT/普通逆向默认套进 `vuln` 目录。 --- @@ -160,6 +162,42 @@ --- + +## 3b. Thin overlay:`vuln`(漏洞技术分析 · 可选) + +> Issue #65 补充。结构参考公开「操作系统/组件漏洞技术分析」类报告目录,**只抽章节骨架**,禁止抄录截图/正文中的 PoC 报文、利用细节或未授权攻击步骤。 +> **不是** 第 3 个默认厂商全文 flavor;仅在漏洞研究任务或用户明确要求时叠加。 + +**叙事目标**:读者能快速看到「影响谁 → 如何确认/复现(授权内)→ 根因与补丁差异 → 如何缓解」。 + +### 建议章节顺序 + +```markdown +## 1. 漏洞概述 +### 1.1 影响范围(版本/组件/配置前提) +### 1.2 漏洞复现(授权环境;步骤可第三方重复;无武器化教程口吻) + +## 2. 漏洞分析 +### 2.1 崩溃 / 异常分析(Evidence:崩溃日志、触发条件) +### 2.2 补丁分析(diff/守卫条件/修复点 — 挂 E-*) +### 2.3 PoC 或触发器分析(仅授权范围内已有材料;协议/输入构造层次说明即可) + +## 3. 防护建议 +### 3.1 缓解措施(配置/缓解开关等) +### 3.2 官方补丁与验证 + +## 4. Evidence → Finding → Path(可并入各节或独立表) +``` + +### 硬约束 + +- **MUST** scope/授权:未授权目标禁止复现与 PoC 扩展 +- **MUST** E/F/P:复现、崩溃、补丁结论均挂 evidence_ids +- **MUST NOT** 把 `vuln` 当作 malware/APT 默认壳 +- **MUST NOT** 抄录外部报告/截图中的利用代码或完整攻击武器化步骤 +- IOC 表:仅当存在网络/文件指示器时出现;否则 n/a 或省略 + +--- ## 4. 与现有任务模板的挂接 | 任务模板(`security-report-templates.md`) | 叠加方式 | @@ -183,9 +221,14 @@ elif user_requests_huorong or vir_report or explicit_malware: flavor = malware else: flavor = null # 原任务模板 + Base 中适用的元素 +overlay = null +if user_requests_vuln_tech_report or cve_patch_analysis: + overlay = vuln # thin only; never a third default full flavor emit(base_report) if flavor in (malware, apt): emit(report with flavor outline) +elif overlay == vuln: + emit(report with vuln thin outline) ``` --- @@ -198,6 +241,7 @@ if flavor in (malware, apt): - [ ] `malware` / `apt` 报告有 IOC 表(或 n/a+原因) - [ ] `malware` / `apt` 报告有可执行建议/处置 - [ ] 无 flavor 的任务没有被套入 malware/APT 专属章节 +- [ ] uln 仅在漏洞任务启用;含概述/分析/防护骨架与 E/F/P;无未授权 PoC 武器化 - [ ] 无厂商原文粘贴、无 placeholder/TODO - [ ] 导入表等硬门 Evidence 已进入静态/技术分析(若本任务做过二进制分析) @@ -213,6 +257,7 @@ if flavor in (malware, apt): ## 8. 非目标 -- 不维护 Mandiant/CrowdStrike/奇安信等额外全文模板(结构已由双 flavor 覆盖常见需求)。 +- 不维护 Mandiant/CrowdStrike/奇安信等额外全文模板(结构已由双 flavor + 可选 thin overlay 覆盖常见需求)。 +- 不把 `vuln` 升级为与 malware/apt 并列的默认全文 flavor。 - 不自动爬取厂商站点填报告。 - 不因 flavor 降低 Evidence 契约或授权范围。 diff --git a/skills/ida-reverse/SKILL.md b/skills/ida-reverse/SKILL.md index 8fc262e..cb3537c 100644 --- a/skills/ida-reverse/SKILL.md +++ b/skills/ida-reverse/SKILL.md @@ -244,9 +244,12 @@ idapro_survey_binary(detail_level="minimal") - 入口点(main/WinMain/DllMain) - 有趣的字符串(URL、路径、错误消息) - **导入分类(MUST)**:加密函数 / 网络 API / 文件操作 / 进程注入 / 注册表 — 必须落成 Evidence(建议 id:`E-imports`),可用 `idapro_entity_query(kind="imports")` 或 survey 输出中的 imports 段 +- **DLL/SYS**:导出表与导入表并列(Evidence `E-exports`) +- **.NET**:无传统 IAT 时用模块/元数据/托管引用摘要作为等价锚点写入 E-imports 语义槽 +- **干净导入表**:注明动态加载嫌疑,推动动态 API 断点验证 - 热门函数(高 xref 计数的函数通常是关键逻辑) -**硬门禁**:未将 imports 视图/分类摘要写入 Evidence 前,MUST NOT 进入 Step 4 深挖结论,MUST NOT 声称 survey 完成。导入表为空或查询失败时仍 MUST 记录失败现象。用户要求重做导入表检查时 MUST 重做本步骤,禁止改换其他步骤。 +**硬门禁**:未将 imports 视图/分类摘要(或合法等价锚点)写入 Evidence 前,MUST NOT 进入 Step 4 深挖结论,MUST NOT 声称 survey 完成。导入表为空或查询失败时仍 MUST 记录失败现象。加壳 IAT 修复失败时 MUST 记 `E-iat-repair-fail` 并转动态调试抓 API,禁止静态死磕。用户要求重做导入表/IAT 检查时 MUST 重做被点名步骤,禁止改换其他步骤。 ### Step 4: 深入关键函数 ``` @@ -349,7 +352,8 @@ ida-pro-mcp --config ## 任务完成自检(声称完成前 MUST 通过) - [ ] 我是否执行了工作流中的每一步(而不是只阅读)? -- [ ] survey/imports 是否已写入 Evidence(E-imports)?用户若要求重做导入表,是否重做了同一步? +- [ ] survey/imports 是否已写入 Evidence(E-imports 或等价)?DLL/SYS 是否含 E-exports?IAT 失败是否记 E-iat-repair-fail? +- [ ] 用户若要求重做导入表/IAT,是否重做了同一步? - [ ] 我是否基于 `tool-index` 使用了真实工具路径? - [ ] 我是否产出了可复现证据(命令/脚本/截图/报告)? - [ ] 我是否完成并回写了 RULES 要求的 Checklist 项? diff --git a/skills/llm-security/references/agent-obedience-engineering.md b/skills/llm-security/references/agent-obedience-engineering.md index 622ef7c..a6db971 100644 --- a/skills/llm-security/references/agent-obedience-engineering.md +++ b/skills/llm-security/references/agent-obedience-engineering.md @@ -82,6 +82,8 @@ MAY — 真正可选的 | "用户没明确说要报告,我就不写了" | **报告是默认行为,不是可选。** 安全任务完成后必须生成报告,除非用户明确说"不要报告"。 | | "这个太简单了不需要记录 journal" | **简单任务也有踩坑价值。** 至少记录:目标类型 + 用了什么 + 有无意外,一行也行。 | | "用户让我重做导入表/某一步,但我改做了别的更有用的步骤" | **重做 = 重做被点名的同一步。** 用户要求重做 X(如导入表检查)时 MUST 重新执行 X 并更新对应 Evidence;禁止用其他步骤冒充完成,禁止静默跳过 X。 | +| "IAT 修不好,我再静态试几种壳工具拖时间" | **IAT 修复铁律:** 优先自动/半自动修复;工具报错或修完无法运行 → 立即停静态 IAT,记 E-iat-repair-fail,转动态 API 断点抓取。禁止无限静态死磕。 | +| ".NET / 没导入表,硬门不适用,我跳过" | **等价锚点仍 MUST:** .NET 用 dnSpy/IL/元数据摘要写入 E-imports 语义槽;DLL/SYS 必须并列 E-exports。禁止空过。 | **使用方式**:将本表放在 RULES.md 或其他指令文件末尾附近(高注意力区域)。Agent 在找借口之前先看到反驳。 diff --git a/skills/malware-analysis/SKILL.md b/skills/malware-analysis/SKILL.md index 47fdb4c..fd0a821 100644 --- a/skills/malware-analysis/SKILL.md +++ b/skills/malware-analysis/SKILL.md @@ -45,6 +45,28 @@ sha256sum sample.exe # → VirusTotal / MalwareBazaar / Triage 查询 ``` +```text +Triage MUST 清单(Issue #65): +□ 文件类型:EXE / DLL / SYS / .NET / 其他 +□ 架构 x86/x64/ARM;查壳(DIE 等)与编译语言线索 +□ DLL/SYS:导入表与导出表并列检查(见 Phase 2 硬门) +□ .NET:无传统 IAT → 走 dnSpy/IL/元数据等价锚点(见 Phase 2) +``` + +### Phase 1b: 脱壳与 IAT 处理(有壳时 · Issue #65) + +```text +□ 无壳 / .NET → 跳到 Phase 2 +□ 有壳:尝试脱壳(授权隔离环境)→ 尝试修复 IAT + - x86:ImportREC(或等价);x64:Scylla(或等价)。禁止 64 位死磕 ImportREC +□ 【IAT 修复铁律】优先自动/半自动修复;若工具报错或修复后无法运行: + - 立即终止继续静态 IAT 修复 + - MUST 记录 E-iat-repair-fail(命令、工具、现象) + - ⏩ 转入 Phase 3 动态:API 断点(如 bp CreateFile)/ 硬件断点 / 内存搜索抓取导入 + - 这不算跳过导入表:路径已尝试并记 Evidence +□ 用户要求重做「IAT 修复 / 导入表检查」:MUST 重做被点名步骤,禁止换步骤冒充 +``` + ### Phase 2: 静态分析 ```text @@ -56,9 +78,12 @@ sha256sum sample.exe 重点分析区域: □ 入口点(Entry Point)→ 初始化逻辑 □ 导入表 → API 用途推断(CreateRemoteThread=注入, CryptEncrypt=勒索) - **MUST(硬门)**:执行 rabin2 -i / IDA imports / pecheck 等价命令,将导入表分类摘要写入 Evidence(E-imports)后才能进入 Phase 3 + **MUST(硬门)**:执行 rabin2 -i / IDA imports / pecheck 等价命令,将导入表分类摘要写入 Evidence(E-imports)后才能进入 Phase 3(除非已记 E-iat-repair-fail 并走动态旁路,见 Phase 1b) 分类至少覆盖:网络 / 文件 / 加密 / 进程注入 / 注册表 / 其他可疑 API 解析失败或表为空:仍 MUST 记录失败输出,禁止静默跳过 + **DLL/SYS**:MUST 并列记录导出表 Evidence(E-exports,`rabin2 -E` 或等价) + **.NET**:无传统 IAT 时 MUST 用 dnSpy/IL/元数据/程序集引用与敏感 API 摘要作为等价锚点,写入 E-imports / E-triage-imports 语义槽 + **干净导入表**:仅基础 DLL、几乎无业务 API → MUST 注明动态加载嫌疑(LoadLibrary/GetProcAddress),SHOULD 转入 Phase 3 抓内存 API 用户要求「重做导入表检查」:MUST 重做本项,禁止改换其他步骤冒充完成 □ 资源段 → 嵌入 Payload(.rsrc 节) □ 字符串表 → URL/C2/文件路径/Base64 blob @@ -81,6 +106,12 @@ sha256sum sample.exe □ 网络: HTTP/DNS → C2 通信 □ 内存: VirtualAllocEx → 进程注入 □ 服务: CreateService → 持久化 +□ IAT 修复失败样本:在敏感 API 下断点 / 硬件执行断点 / 内存搜索捕捉真实导入 + +无行为应急分支(MUST): +□ 沙箱无行为、秒退或无限休眠 → 检查反调试/反虚拟机(CPUID、计时、环境特征) +□ 尝试硬件断点绕过、补丁检测点、或换物理机/更高保真环境 +□ 将「无行为 + 条件」写入 Evidence;禁止无条件写成「样本无害」 ``` ### Phase 4: YARA 规则编写 @@ -221,11 +252,14 @@ Triage RE Behav Intel Detect Remed - `references/yara-sigma-rules.md` — YARA + Sigma 编写方法论 - `references/sandbox-orchestration.md` — 沙箱编排与自动化 - `references/anti-analysis-techniques.md` — 94 种反分析技术检测 +- `../reverse-engineering/references/re-agent-workflow.md` — IAT 铁律与六阶段门闩(Issue #65) ## 任务完成自检(声称完成前 MUST 通过) - [ ] 我是否执行了工作流中的每一步(而不是只阅读)? -- [ ] 导入表 MUST 检查是否已执行并写入 Evidence(E-imports)?重做请求是否回到同一步? +- [ ] 导入表 MUST 检查是否已执行并写入 Evidence(E-imports 或 .NET 等价锚点)?DLL/SYS 是否含 E-exports? +- [ ] 若 IAT 修复失败:是否记录 E-iat-repair-fail 并转入动态,而非静态死磕或静默跳过? +- [ ] 重做请求是否回到被点名的同一步?干净导入表/沙箱无行为是否按旁路处理? - [ ] 我是否基于 `tool-index` 使用了真实工具路径? - [ ] 我是否产出了可复现证据(命令/脚本/截图/报告)? - [ ] 我是否完成并回写了 RULES 要求的 Checklist 项? diff --git a/skills/radare2/SKILL.md b/skills/radare2/SKILL.md index 2daec46..39145a7 100644 --- a/skills/radare2/SKILL.md +++ b/skills/radare2/SKILL.md @@ -124,14 +124,17 @@ ERROR: Cannot find ...\share\format\dll\*.sdb 对 PE/ELF/Mach-O 等含导入表的二进制,**MUST** 先完成导入表检查并落成 Evidence,再进入函数级分析或动态步骤: -1. 执行 `rabin2 -i `(或 `recon.ps1` 输出中的 imports 段) +1. 执行 `rabin2 -i `(或 `recon.ps1` 输出中的 imports 段);DLL/SYS 另 MUST `rabin2 -E` 并记 `E-exports` 2. 将完整/分类后的导入表结果写入 Evidence(建议 id:`E-imports` 或 `E-triage-imports`),至少包含: - 复现命令(`repro_command`) - 关键导入分类摘要:网络 / 文件 / 加密 / 进程注入 / 注册表 / 其他可疑 API - 若导入表为空、解析失败或工具报错:仍 MUST 记录失败现象与原始输出为 Evidence,**不得静默跳过** -3. 用户明确要求「重做导入表检查 / 重新检查导入表」时:MUST 重做本硬门步骤本身,**禁止改换为其他步骤冒充完成** + - 导入表「过干净」(仅基础 DLL):MUST 注明动态加载嫌疑,SHOULD 转入动态抓 API +3. .NET 等无传统 IAT:MUST 走等价锚点(dnSpy/IL/元数据摘要)写入同一 Evidence 语义槽,禁止空过 +4. 加壳样本 IAT 修复:x86 用 ImportREC(或等价)、x64 用 Scylla(或等价)。修复失败 MUST 记 `E-iat-repair-fail` 后转动态 API 断点;**禁止**在静态 IAT 上无限死磕(见 `reverse-engineering/references/re-agent-workflow.md` §1.2) +5. 用户明确要求「重做导入表检查 / 重新检查导入表 / 重做 IAT」时:MUST 重做被点名步骤本身,**禁止改换为其他步骤冒充完成** -未记录导入表 Evidence 前:MUST NOT 声称「基础侦察完成」,MUST NOT 进入工作流 2+ 的深挖结论。 +未记录导入表(或合法等价锚点 / IAT 失败旁路)Evidence 前:MUST NOT 声称「基础侦察完成」,MUST NOT 进入工作流 2+ 的深挖结论。 优先直接运行内置脚本: @@ -370,6 +373,7 @@ rax2 -s hello - 不要在未说明风险时直接写模式打开用户文件 - 不要在还没做基础侦察前就下结论 - **禁止跳过导入表检查**(`rabin2 -i` / recon imports):未写入 Evidence 不得进入下一步;用户要求重做导入表时禁止改做其他步骤 +- **禁止 IAT 修复失败后静态死磕**:记 `E-iat-repair-fail` 后转动态;禁止 64 位样本只用 ImportREC - 不要把网页 JS 逆向误导到这个 skill;那是 `reverse-engineering` 的范围 ## 参考资料 @@ -421,7 +425,8 @@ rax2 -s hello ## 任务完成自检(声称完成前 MUST 通过) - [ ] 我是否执行了工作流中的每一步(而不是只阅读)? -- [ ] 导入表检查是否已执行且写入 Evidence(E-imports / E-triage-imports)?若用户要求重做,是否重做了同一步而非换步骤? +- [ ] 导入表检查是否已执行且写入 Evidence(E-imports / E-triage-imports 或 .NET 等价)?DLL/SYS 是否含 E-exports? +- [ ] IAT 修复失败是否记录 E-iat-repair-fail 并转动态?重做请求是否回到同一步? - [ ] 我是否基于 `tool-index` 使用了真实工具路径? - [ ] 我是否产出了可复现证据(命令/脚本/截图/报告)? - [ ] 我是否完成并回写了 RULES 要求的 Checklist 项? diff --git a/skills/reverse-engineering/references/re-agent-workflow.md b/skills/reverse-engineering/references/re-agent-workflow.md index d346aec..a02b19a 100644 --- a/skills/reverse-engineering/references/re-agent-workflow.md +++ b/skills/reverse-engineering/references/re-agent-workflow.md @@ -1,8 +1,8 @@ # RE Agent 工作流门闩(静态↔动态) > 来源启发:binary-re 阶段划分、社区 RE skill(Frida/r2/Ghidra/IDA 循环)、Cerberus 三头环(静/动/插桩) -> 日期:2026-07-17 -> 适用:`reverse-engineering/`、`ida-reverse/`、`radare2/`、与 cre 角色交接 +> Issue #65 增量:IAT 修复铁律、恶意样本六阶段映射、.NET/DLL·SYS 等价路径(2026-08-12) +> 适用:`reverse-engineering/`、`ida-reverse/`、`radare2/`、`malware-analysis/`、与 cre 角色交接 ## 0. 启动 @@ -12,55 +12,119 @@ □ 角色:cre(ops/role-map) ``` -## 1. Triage(5–15 分钟) +## 1. Triage(5–15 分钟 · 强制起点) ```text -□ file / DIE / 熵 / 壳特征 +□ 计算样本 Hash(MD5/SHA256)→ 唯一 ID +□ 识别文件类型:EXE / DLL / SYS / ELF / Mach-O / .NET / 脚本 等 +□ file / DIE / 熵 / 壳特征(PEiD / DIE / Exeinfo 等) +□ 架构:x86 / x64 / ARM;编译语言线索(VC++ / Delphi / .NET / Go / Rust) +□ 加壳类型线索:UPX / ASPack / VMProtect / Themida / 未知混淆 □ strings / rabin2 -z 捡漏 -□ 架构/链接/是否 .NET/Go/Rust/加壳 -□ MUST 导入/导出表:rabin2 -i / -E(或 IDA imports / 等价物) -□ 产出:E-triage(MUST 含 imports 分类摘要:网络/文件/加密/注入/注册表)+ 假设清单(勿过早下结论) +□ MUST 导入/导出锚点(见下方「导入表硬门与等价路径」) +□ 产出:E-triage(MUST 含 imports 或等价锚点分类摘要)+ 假设清单(勿过早下结论) ``` -**阶段门闩(Triage → Static/Dynamic)**:E-triage 中未记录 imports 摘要前,MUST NOT 进入 Dynamic,也 MUST NOT 声称「基础分诊完成」。导入表解析失败时仍 MUST 把失败输出写入 Evidence,不得跳过。用户要求「重做导入表检查」时 MUST 重做 imports 步骤本身,禁止改换其他分析步骤。 +**阶段门闩(Triage → Static/Dynamic)**:E-triage 中未记录 imports **或** 合法等价锚点摘要前,MUST NOT 进入 Dynamic(除非已记录 IAT 修复失败并选择动态旁路,见 §1.2),也 MUST NOT 声称「基础分诊完成」。解析失败时仍 MUST 把失败输出写入 Evidence,不得跳过。用户要求「重做导入表检查」时 MUST 重做 imports/等价步骤本身,禁止改换其他分析步骤。 -## 2. Static +### 1.1 导入表硬门与等价路径 + +| 样本类型 | MUST 锚点(Evidence) | 说明 | +|----------|----------------------|------| +| 原生 PE/ELF/Mach-O(IAT 可读) | `E-imports` / `E-triage-imports`:导入分类摘要 | `rabin2 -i` / IDA imports / 等价 | +| DLL / SYS / 共享库 | **并列** `E-imports` + `E-exports`(`rabin2 -i` + `rabin2 -E`) | 导出表优先级等同导入表(对外入口) | +| .NET 托管(无传统 IAT) | **等价路径**:dnSpy/IL/元数据/程序集引用与敏感 API 摘要 → 仍写入 `E-imports` 或 `E-triage-imports` 语义槽 | **禁止** 因「没有 IAT」而空过硬门;dnSpy 查看 = 原生「查导入表」 | +| 导入表解析失败 / 为空 | 仍记失败输出为 Evidence | 不得静默跳过 | + +**干净导入表警告(MUST 提醒)**:若导入表「过干净」(仅 kernel32/ntdll 等基础 DLL、几乎无业务 API),高度怀疑 `LoadLibrary` + `GetProcAddress` 动态加载 → 在 Evidence 注明嫌疑,并 **SHOULD** 转入 Dynamic 抓取内存 API;不得仅凭静态 IAT 宣称「无网络/无文件能力」。 + +### 1.2 脱壳与 IAT 处理(高风险分岔 · Issue #65) + +```text +分支 A:无壳 / .NET 托管 + → 直接进入 §2 Static(.NET 走等价锚点) + +分支 B:有壳 / 强混淆 + Step 1:尝试脱壳(自动脱壳机 / 手动找 OEP)— 须在授权与隔离环境 + Step 2:尝试修复 IAT + 工具:x86 → ImportREC(或等价);x64 → Scylla(或等价)。禁止 64 位样本死磕 ImportREC。 + 情况 B1:修复成功且可解析 → 记 E-imports(修复后)→ §2 Static + 情况 B2:ImportREC/Scylla 报错、修复后无法运行、或 IAT 全乱码(VMP/加密壳) + → 【IAT 修复铁律】立即终止继续静态 IAT 修复 + → MUST 记录 E-iat-repair-fail(命令、工具、失败现象、决定转动态) + → ⏩ 直接进入 §3 Dynamic:API 断点 / 硬件执行断点 / 内存搜索抓取导入 + → 这不算「跳过导入表」:导入表路径已尝试并记 Evidence +``` + +**IAT 修复铁律(MUST)**:优先尝试自动/半自动修复;一旦修复工具报错或修复后程序无法运行,**立即停止**在静态导入表上死磕,切换动态调试,用 API 断点(如 `bp CreateFile` / 关键网络 API)在运行时捕获导入函数。 + +## 2. Static(基础静态锚点 → 深挖) | 工具 | 何时 | |------|------| -| radare2 / rabin2 | 快速函数/导入/字符串(imports 已在 Triage MUST 完成) | +| radare2 / rabin2 | 快速函数/导入/字符串(imports 已在 Triage MUST 完成或已记失败旁路) | | IDA / Ghidra(MCP 或 headless) | 深挖、交叉引用、类型;survey 阶段复核 imports 分类 | | jadx / dnSpy | Android / .NET | | OLLVM 文档 | 控制流平坦化怀疑 | ```text -□ 确认 E-imports / E-triage 已含导入表 Evidence(缺失则先补,禁止后置) -□ 定位关键函数(加密/校验/网络/授权) -□ 记录地址/符号 → Evidence -□ 一条路不通 → 换工具(IDA?r2?Ghidra) +□ 确认 E-imports / E-triage 已含导入表或等价锚点 Evidence(缺失则先补,禁止后置) +□ 若 DLL/SYS:确认 E-exports 已记录 +□ 敏感 API 分组:网络/WinHTTP、文件/CreateFile、进程/远程线程、注册表/服务 +□ 硬编码域名/IP/URL 字符串;资源节是否藏 Payload +□ 定位关键函数(加密/校验/网络/授权)→ 地址/符号写入 Evidence +□ 一条路不通 → 换工具(IDA↔r2↔Ghidra) ``` **无 MCP 时**:可用导出反编译文本再分析(对照 P4nda0s reverse-skills / IDA-NO-MCP 思路),仍写 Evidence 路径。 -## 3. Dynamic +## 3. Dynamic(交叉验证循环区) + +核心理念:**静态提供线索 → 动态验证 → 验证卡壳 → 回静态重审**(无固定唯一顺序)。 ```text -□ Frida / gdb / emulator:验证静态假设 +□ Frida / x64dbg / gdb / emulator:验证静态假设 +□ 敏感 API 断点、单步跟踪栈/寄存器(白盒) +□ 行为监控:沙箱 / Procmon / RegShot(黑盒) +□ IAT 修复失败样本:硬件执行断点或内存搜索强行捕捉 API □ 反调试/反 Frida → reverse-engineering/anti-analysis □ Android:root 检测 / SSL pinning 绕过脚本按需生成,**须在授权设备** □ 崩溃日志驱动下一轮 hook(自适应循环) ``` -## 4. Synthesis +### 3.1 沙箱 / 动态无行为应急分支(MUST) ```text -□ Finding:算法/校验逻辑/可利用点 +无行为或立刻退出 / 无限休眠 + → 检查反调试 / 反虚拟机例程(CPUID、高精度计时、沙箱特征等) + → 尝试硬件断点绕过、修补检测点、或换物理机/更高保真环境 + → 将「无行为 + 疑似 anti-VM」写入 Evidence,禁止写成「样本无害」而不加条件 +``` + +## 4. Synthesis(IOC / 攻击链 / 报告) + +```text +□ Finding:算法/校验逻辑/可利用点 / 行为结论 □ Path:callflow 或 solve 步骤挂 E-* -□ 报告 docs-generator + 可选图 +□ IOC:网络指纹 + 主机指纹(有则表;无则 n/a+原因) +□ 报告 docs-generator(malware/apt/null/vuln overlay 按任务选型)+ 可选图 +□ 可选:YARA / Snort·Suricata 规则化沉淀 □ field-journal 脱敏 ``` -## 5. 与「堆 RE skill 插件」的差异 +## 5. 六阶段实战映射(Issue #65 思维导图 → 本文件) + +| 实战阶段 | 本文件章节 | 硬门 / 铁律 | +|----------|------------|-------------| +| 1 初步快速研判 | §0–§1 Triage | Hash、架构、文件类型、查壳;imports/等价锚点 | +| 2 脱壳与 IAT | §1.2 | IAT 修复铁律;失败 → E-iat-repair-fail → Dynamic | +| 3 基础静态锚点 | §2 Static | 仅 IAT 正常或等价锚点已记录后深挖 | +| 4 深度交叉验证 | §3 Dynamic | 静↔动循环;无行为应急分支 | +| 5 提取 IoC 与攻击链 | §4 Synthesis | IOC + Kill Chain / Path | +| 6 归档与规则化 | §4 + docs-generator / YARA | 结构化报告;规则可选 | + +## 6. 与「堆 RE skill 插件」的差异 - 本包用 **阶段门闩 + tool-index**,不默认启用 Hex-Rays「unsafe 全自动执行」类插件 -- 动态插桩默认 **offline/lab** network_profile \ No newline at end of file +- 动态插桩默认 **offline/lab** network_profile +- IAT/导入表:**尝试 + 记录** 优先于「无限静态死磕」或「静默跳过」 \ No newline at end of file diff --git a/skills/scripts/verify-routing-coherence.ps1 b/skills/scripts/verify-routing-coherence.ps1 index 49810f1..683f0be 100644 --- a/skills/scripts/verify-routing-coherence.ps1 +++ b/skills/scripts/verify-routing-coherence.ps1 @@ -1,4 +1,4 @@ -#Requires -Version 5.1 +#Requires -Version 5.1 # reverse-skill routing + ops contract gates (skill-router only; no host platform runtime) param([string] $ScratchDir = '') $ErrorActionPreference = 'Stop' @@ -178,7 +178,7 @@ Assert-Fields (Join-Path $skillsRoot 'ops/timeline-workitem.md') @('timeline.md' Assert-Fields (Join-Path $skillsRoot 'ops/role-map.md') @('lead', 'cie', 'cpe', 'cre', 'Handoff') Assert-Fields (Join-Path $skillsRoot 'ops/skill-supply-chain.md') @('AST10', 'MCP', 'bootstrap', 'MUST') Assert-Fields (Join-Path $skillsRoot 'references/community-security-skills.md') @('trailofbits', 'agentskills.io', 'MUST', '2026-07') -Assert-Fields (Join-Path $skillsRoot 'reverse-engineering/references\re-agent-workflow.md') @('Triage', 'Static', 'Dynamic', 'Synthesis') +Assert-Fields (Join-Path $skillsRoot 'reverse-engineering/references\re-agent-workflow.md') @('Triage', 'Static', 'Dynamic', 'Synthesis', 'IAT 修复铁律', 'E-iat-repair-fail', 'E-exports', 'dnSpy') Assert-Fields (Join-Path $skillsRoot 'pentest-tools/references\recon-pipeline.md') @('auth.status', 'network_profile', 'Evidence', 'nuclei') Assert-Fields (Join-Path $skillsRoot 'docs-generator/references\security-report-templates.md') @('Evidence Chain', 'Findings', 'Path') Assert-Fields (Join-Path $skillsRoot 'field-journal/_template.md') @('Scope', 'Evidence', 'Finding') @@ -202,7 +202,17 @@ if ($vendorRulesText -match '(?m)JS/Web 签名逆向报告\s*\|[^\r\n]*malware') } else { Ok 'vendor rules keep JS signature reports flavor-neutral' } -Assert-Fields $vendorRulesPath @('skills/ops/evidence-finding-path.md', '来源证据', 'securelist.com/updated-mata', 'www.huorong.cn') +Assert-Fields $vendorRulesPath @('skills/ops/evidence-finding-path.md', '来源证据', 'securelist.com/updated-mata', 'www.huorong.cn', 'thin overlay', 'vuln') +Assert-Fields (Join-Path $skillsRoot 'malware-analysis/SKILL.md') @('IAT 修复铁律', 'E-iat-repair-fail', 'E-exports') +Assert-Fields (Join-Path $skillsRoot 'docs-generator/references\security-report-templates.md') @('thin `vuln`', '1c. 漏洞技术分析') +if ($vendorRulesText -match '(?m)vuln.*默认全文' -or $vendorRulesText -match '第 3 个默认全文 flavor') { + # presence of explicit "not third default" language is OK; flag only if it claims vuln IS a third default full flavor +} +if ($vendorRulesText -match '仅 2 个厂商全文 flavor' -or $vendorRulesText -match '不是.*第 3 个默认全文 flavor') { + Ok 'vendor rules keep vuln as thin overlay not third default flavor' +} else { + Bad 'vendor rules missing vuln thin-overlay constraint' +} $fieldLog | Set-Content -LiteralPath (Join-Path $ScratchDir 'template-fields.txt') -Encoding UTF8 # --- role map skills exist for primary rows --- From 172e03ada0bc0f89a27b943dec63586972e5809d Mon Sep 17 00:00:00 2001 From: yhc <1964366186@qq.com> Date: Wed, 12 Aug 2026 12:09:38 +0800 Subject: [PATCH 2/2] fix(ci): run nested smoke scripts on same host + UTF-8 BOM Windows CI failed because smoke.ps1 nested bare 'powershell' (often 5.1) to run verify-routing-coherence.ps1. PS5.1 mis-parsed UTF-8 Chinese source without BOM, so nested verify exited 1 while the standalone pwsh verify step passed. - Resolve SmokeHostExe from current process (pwsh on GHA windows-latest) - Rewrite nested invocations to use $SmokeHostExe - Write UTF-8 BOM on smoke.ps1 and verify-routing-coherence.ps1 for PS5.1 safety --- skills/scripts/smoke.ps1 | 26 +++++++++++++++++---- skills/scripts/verify-routing-coherence.ps1 | 2 +- 2 files changed, 22 insertions(+), 6 deletions(-) diff --git a/skills/scripts/smoke.ps1 b/skills/scripts/smoke.ps1 index de25355..60b67ad 100644 --- a/skills/scripts/smoke.ps1 +++ b/skills/scripts/smoke.ps1 @@ -28,7 +28,23 @@ function Bad([string] $m) { [void]$fail.Add($m) } -Write-Host ("=== reverse-skill smoke | LogDir={0} ===" -f $LogDir) +# Prefer the same host that launched smoke (pwsh on GHA windows-latest). +# Bare "powershell" often resolves to Windows PowerShell 5.1, which mis-parses +# UTF-8 scripts without BOM when nested from pwsh. +$SmokeHostExe = $null +try { + $procPath = (Get-Process -Id $PID -ErrorAction Stop).Path + if ($procPath -and (Test-Path -LiteralPath $procPath)) { $SmokeHostExe = $procPath } +} catch { } +if (-not $SmokeHostExe) { + $cmd = Get-Command pwsh -ErrorAction SilentlyContinue + if ($cmd -and $cmd.Source) { + $SmokeHostExe = $cmd.Source + } else { + $SmokeHostExe = Join-Path $env:SystemRoot 'System32\WindowsPowerShell\v1.0\powershell.exe' + } +} +Write-Host ("=== reverse-skill smoke | LogDir={0} | Host={1} ===" -f $LogDir, $SmokeHostExe) # --- 1) routing coherence --- $verify = Join-Path $scriptDir 'verify-routing-coherence.ps1' @@ -37,7 +53,7 @@ if (-not (Test-Path -LiteralPath $verify)) { $verifyExit = 1 } else { $vLog = Join-Path $LogDir '01-verify.txt' - & powershell -NoProfile -ExecutionPolicy Bypass -File $verify 2>&1 | Tee-Object -FilePath $vLog | Out-Null + & $SmokeHostExe -NoProfile -ExecutionPolicy Bypass -File $verify 2>&1 | Tee-Object -FilePath $vLog | Out-Null $verifyExit = $LASTEXITCODE if ($verifyExit -eq 0) { Ok 'verify-routing-coherence exit 0' } else { Bad ("verify-routing-coherence exit {0}" -f $verifyExit) } } @@ -106,7 +122,7 @@ if (-not (Test-Path -LiteralPath $mr)) { } else { foreach ($c in $cases) { $outFile = Join-Path $LogDir ("route-{0}.txt" -f $c.Name) - $raw = & powershell -NoProfile -ExecutionPolicy Bypass -File $mr -Hint $c.Hint 2>&1 | Out-String + $raw = & $SmokeHostExe -NoProfile -ExecutionPolicy Bypass -File $mr -Hint $c.Hint 2>&1 | Out-String $raw | Set-Content -Path $outFile -Encoding UTF8 if ($raw -match [regex]::Escape($c.Expect)) { Ok ("route {0} -> {1}" -f $c.Name, $c.Expect) @@ -128,7 +144,7 @@ if (-not (Test-Path -LiteralPath $appendEvidence)) { Bad 'append-evidence.ps1 missing for immutability check' } else { New-Item -ItemType Directory -Path $evidenceCase -Force | Out-Null - & powershell -NoProfile -ExecutionPolicy Bypass -File $appendEvidence ` + & $SmokeHostExe -NoProfile -ExecutionPolicy Bypass -File $appendEvidence ` -CaseRoot $evidenceCase ` -Id 'E-IMMUTABLE' ` -Title 'first write' ` @@ -142,7 +158,7 @@ if (-not (Test-Path -LiteralPath $appendEvidence)) { $beforeEvidence = (Get-FileHash -LiteralPath $evidencePath -Algorithm SHA256).Hash $beforeIndex = (Get-FileHash -LiteralPath $indexPath -Algorithm SHA256).Hash - & powershell -NoProfile -ExecutionPolicy Bypass -File $appendEvidence ` + & $SmokeHostExe -NoProfile -ExecutionPolicy Bypass -File $appendEvidence ` -CaseRoot $evidenceCase ` -Id 'E-IMMUTABLE' ` -Title 'second write' ` diff --git a/skills/scripts/verify-routing-coherence.ps1 b/skills/scripts/verify-routing-coherence.ps1 index 683f0be..5e11042 100644 --- a/skills/scripts/verify-routing-coherence.ps1 +++ b/skills/scripts/verify-routing-coherence.ps1 @@ -1,4 +1,4 @@ -#Requires -Version 5.1 +#Requires -Version 5.1 # reverse-skill routing + ops contract gates (skill-router only; no host platform runtime) param([string] $ScratchDir = '') $ErrorActionPreference = 'Stop'