Files
reverse-skills-max/vendor-new/rev-skills/docs/audit/2026-09-13-factual-audit.md

1362 lines
158 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.

# 事实性缺陷审查记录
日期:2026-09-13
来源:批 1——外部 AI 审查清单(覆盖约几十个技能,**非 121 全量穷尽**)+ 本库逐条独立核验;批 2——独立监控(每日核对事实/技术/逻辑/命令错误)+ 本库自查补充
用途:为「增量审查机制」(TODO.md)提供 finding 与核验结论
**状态机**:open(已记录待修)→ fixed(已修)→ verified(复核通过)
**核验方法**:本库原文 grep 定位(确认审查引文与文件一致)+ 上游权威源比对(AOSP 源码 / onnx.proto / can-utils 源码 / QEMU 源码 / HF safetensors 规范 / PyPI 元数据)。只有"原文与权威源直接冲突"才记为确认;术语与措辞类问题按"是否会导致错误推理"定级。
**结论汇总**:批 1(高 11 / 中 5)、批 2(高 1 / 中 4)、批 3(高 9 / 中-高 2 / 中 5)、批 3 补充(工具链 1)累计 38 项 finding——**35 项技能缺陷 + 1 项工程性问题(历史文档污染)+ 1 项工具链一致性问题确认,1 项误报**(见批 3 #37);需澄清 2 点(见文末)。已确认缺陷**全部修复**(状态 fixed,待复核——见文末修复记录)。
---
## 高严重度(11 项,会直接导致错误操作)
| # | 技能 | 位置 | 现状(原文) | 问题 | 修正方向 | 核验依据 |
|---|---|---|---|---|---|---|
| 1 | re-android-crypto | SKILL.md:69 | `const alias = ks.getKeyAlias(key);` | **API 不存在**。`java.security.KeyStore` 无 `getKeyAlias(Key)`(只有 `getCertificateAlias(Certificate)`,且只对证书条目有效) | hook `KeyStore.getKey(alias, …)` 时直接记录 alias;或枚举 `aliases()` 建 Key→alias 映射;或经 `SecretKeyFactory…getKeySpec(key, KeyInfo.class)` 取 `KeyInfo.getKeystoreAlias()`(AOSP 定义为 public,SDK 暴露面以官方 API 列表为准) | JDK KeyStore API + AOSP KeyInfo.java |
| 2 | re-android-crypto | SKILL.md:58, 96 | "TEE 与 StrongBox 区分需 `isStrongBoxBacked`(API 28+)" | **类搞错**。`KeyInfo` 无此方法;`isStrongBoxBacked()` 在 `KeyGenParameterSpec`/`KeyProtection.Builder` 上(生成侧) | 已生成 Key 的判定:API 31+ 用 `KeyInfo.getSecurityLevel()`(`SECURITY_LEVEL_STRONGBOX`/`TRUSTED_ENVIRONMENT`/`SOFTWARE`);API 23–30 只能 `isInsideSecureHardware()` 粗判(TEE 与 StrongBox 同为 secure hardware,无法区分) | AOSP KeyInfo.java(无 isStrongBoxBacked,有 getSecurityLevel/isInsideSecureHardware) |
| 3 | re-macos | SKILL.md:79 | "Secure Enclave 密钥:`SecKeyCreateWithData` 带 `kSecAttrTokenIDSecureEnclave`" | **API 用错**。`SecKeyCreateWithData` 是从外部 key data 导入/恢复,不是 SE 密钥生成;SE 密钥不能导入(只能设备内生成) | `SecKeyCreateRandomKey`(属性含 `kSecAttrTokenID: kSecAttrTokenIDSecureEnclave`),或旧 API `SecKeyGeneratePair` | Apple 文档语义(SecKeyCreateWithData = 外部数据导入;SE 绑定走随机生成) |
| 4 | re-ai-model | SKILL.md:70 | "Safetensors:前 8 字节 = 大端 u64 头长度" | **字节序反了**,实为**小端** | `struct.unpack("<Q", data[:8])` | HF safetensors README 原文:"8 bytes: `N`, an unsigned little-endian 64-bit integer" |
| 5 | re-mobile-forensics | SKILL.md:70, 72 | "Manifest.plist(文件映射表:domain/相对路径 → 哈希文件名)" | **文件搞错**。现代备份(iOS 10+)的文件索引是 `Manifest.db`(SQLite `Files` 表:fileID/domain/relativePath/flags/file);`Manifest.plist` 存备份元数据(Version/Date/IsEncrypted/BackupKeyBag/ManifestKey/Lockdown 设备信息等)。旧版 iOS(<10)索引才是 `Manifest.mbdb` | 映射表指向 `Manifest.db`;`Manifest.plist` 改述为元数据与密钥材料载体 | iOS 备份结构(Manifest.plist 元数据 / Manifest.db 索引);本库 gotchas 与 decision-tree 方向一致,SKILL.md 与二者冲突 |
| 6 | re-mobile-forensics | SKILL.md:72 | "文件按内容哈希命名" | **不是内容哈希**。fileID = SHA1(domain + "-" + relativePath),由路径派生,与文件内容无关——不能拿它当完整性校验 | 明确写 path-derived fileID;与 gotchas.md:13 的既有正确表述对齐 | 同上(库内 gotchas:13 已写对,SKILL.md 与之矛盾) |
| 7 | re-mobile-forensics | SKILL.md:74 | "加密备份判定:Manifest.plist 无法明文读取而 Info.plist/Status.plist 正常" | **判定反了**。`Manifest.plist` 在加密备份中**仍可明文读取**(`IsEncrypted`/`BackupKeyBag`/`ManifestKey` 就在其中);被加密的是 `Manifest.db` 与各文件内容 | 改为:读 `Manifest.plist` 的 `IsEncrypted` 键判定;再按备份密码/keybag 解 `Manifest.db` | 同上(加密备份的密钥材料存放位置) |
| 8 | re-riscv | SKILL.md:76 | "reset 向量(QEMU virt 机器 0x80000000…)" | **地址语义混淆**。virt 的 MROM(reset 向量所在)在 `0x1000`;`0x80000000` 是 DRAM 基址,即 reset stub 跳转的默认目标 | 写作:CPU 从 `0x1000` 的 MROM reset stub 起,stub 跳 `start_addr`(默认 DRAM `0x80000000`;pflash 固件场景为 `0x20000000`) | QEMU `hw/riscv/virt.c`:`VIRT_MROM=0x1000`、`VIRT_DRAM=0x80000000`、`riscv_setup_rom_reset_vec(…, start_addr, MROM.base, …)` |
| 9 | re-dotnet | SKILL.md:72 | "EntryPoint RVA(0=DLL)" | **不总是 RVA**。该字段是 union(ECMA-335 II.25.3.3 EntryPointToken):未置 `COMIMAGE_FLAGS_NATIVE_ENTRYPOINT` 时为 metadata token(MethodDef/File),置位时才是 native code RVA;"0 = 无入口"成立 | 写作 EntryPointToken / EntryPointRVA union,按 `COMIMAGE_FLAGS_NATIVE_ENTRYPOINT` 决定解释 | ECMA-335 II.25.3.3 CLI header 字段定义 |
| 10 | re-automotive | SKILL.md:89, 149 | `candump can0 -f 0x7E0:0x7FF`(注释作 ID 过滤) | **命令错**。`-f <fname>` 是把日志写入文件(这条命令会生成名为 `0x7E0:0x7FF` 的日志文件)。过滤语法在接口名后的逗号位:`candump can0,7E0:7FF`(`can_id:can_mask`,匹配条件 `received & mask == can_id & mask`) | 两条命令拆开:过滤 `candump can0,7E0:7FF`;写文件 `candump -f <file> can0` | can-utils 源码 `candump.c` usage(`-f <fname> (log CAN-frames into file <fname>)`)+ Debian manpage 过滤语法节 |
| 11 | re-forensics | SKILL.md:15 | "转储来源:…没有则按 [[re-memdump]] 转一份(`gcore -o out <pid>`…);已有 .raw/.mem/.core 直接进入下一步" | **与子技能自相矛盾且工作流错误**。gateway 把 gcore 产物当取证默认来源;但 [[re-mem-forensics]]:52 与 [[re-memdump]]:73 明确 gcore 是单进程 ELF core(无内核结构/页表),Volatility 整机插件不可解析 | 分流:gcore → gdb/eu-stack 进程级复盘;整机镜像(LiME/AVML/崩溃转储等)→ Volatility | 库内三处原文对照(re-forensics / re-mem-forensics / re-memdump) |
## 中严重度(5 项,会导致错误推理)
| # | 技能 | 位置 | 现状(原文) | 问题 | 修正方向 | 核验依据 |
|---|---|---|---|---|---|---|
| 12 | re-ai-model | SKILL.md:69 | "起始字节形如 `08 08 12 <len> ...`" | **不能当识别 signature**:第二字节是 ir_version 的**值**,随 ONNX 版本递增(当前已发布 13 = `0x0D`,main 分支枚举已到 14),不是固定 8;`producer_name` 为 SHOULD present,不保证出现 | 保留"protobuf 无固定魔数",把 `08 08 12…` 降为"部分旧样本的形态举例",并说明首字段是 ir_version(tag `0x08` + 变长值) | onnx.proto `Version` 枚举(IR 1…13 已发布,14 待发布) |
| 13 | re-dotnet | SKILL.md:73 | "版本串("v4.0.30319",.NET Framework/.NET Core/.NET 10 产物恒定)" | **常见默认值≠不变量**。`MetadataRootBuilder` 默认确为 v4.0.30319,但参数可指定其他串;ECMA-335 允许 vendor-specific 版本串 | 改为"典型默认值(Roslyn/MetadataRootBuilder 产物常见)",不作恒定断言 | ECMA-335(版本串为自由格式)+ MetadataRootBuilder 默认值语义 |
| 14 | re-macos | SKILL.md:78 | "钥匙串条目类型…与 ACL(`kSecAttrAccessible` 可访问性类)" | **术语不准**。`kSecAttrAccessible` 管"设备处于什么状态时条目可读"(可访问性);访问控制是 `kSecAttrAccessControl`/`SecAccessControl`(生物识别/密码门槛),macOS 传统 ACL 另有 `SecAccess`/`kSecAttrAccess` | SKILL.md 与 gotchas.md:30 的既有正确区分对齐(ACL 与可访问性分开表述) | Apple 钥匙串属性语义;库内 gotchas:30 已正确区分 |
| 15 | re-mem-forensics | SKILL.md:21 vs :23 | 标题"(Python 3.8-3.11)",正文"官方要求 Python 3.8+…3.14 可安装" | **标题与正文矛盾**:官方只要求 `Python >=3.8.0`,无 3.11 上限 | 标题去掉上限("Python 3.8+") | PyPI volatility3 元数据(Requires Python >=3.8.0) |
| 16 | re-ransomware | SKILL.md:65 | "熵(>7.0 已加密)" | **高熵≠加密**:压缩数据、媒体文件、随机填充、压缩 section 同样高熵;此处把证据写成了判定 | 改为"高熵(>7.0)→ 加密/压缩/高随机性候选,需结合文件头与上下文佐证" | 方法论(本库 re-anti-analysis:199、re-binary-core R24 已写"高熵≠加密") |
**#16 范围补充**:库内多数位置措辞正确("可疑加壳/加密""密文/压缩候选""提示加壳/加密"),硬化表述目前定位到 2 处——re-ransomware:65 与 re-proto-rev:136(">7.5 几乎肯定加密")。修复时一并收敛。
---
## 批 2(2026-09-13,独立监控 + 本库自查)
| # | 严重度 | 技能 | 位置 | 现状(原文) | 问题 | 修正方向 | 核验依据 |
|---|---|---|---|---|---|---|---|
| 17 | 高 | re-frida 等 9 文件 | re-frida/SKILL.md:76,90,113,136;re-frida/references/frida-scripts.md:33-34;re-android-native/SKILL.md:115;re-android-native/references/probes.md:26;re-crypto-id/SKILL.md:111;re-ios-jb/SKILL.md:86;re-flutter/SKILL.md:114;re-address-space/SKILL.md:26,72,80 | `Module.findExportByName(...)` / `Module.getExportByName(...)` / `Module.enumerateExports(...)` / `Module.findBaseAddress(...)` 等静态调用 | **Frida 17.0.0 移除了全部静态查找/枚举 API**(静态仅存 `Module.load` / `findGlobalExportByName` / `getGlobalExportByName`)——安装指引给的是 `pip install frida-tools`,用户拿到 17+ 后示例报 `is not a function`;属横向污染(多技能共享旧模板) | 迁移为模块实例调用:`Process.getModuleByName("libfoo.so").findExportByName("func")`、`.base`、`.enumerateExports()`;全局符号(原 null 模块参数)用 `Module.findGlobalExportByName(...)`;re-frida 补迁移条目,其余技能就地改写 | Frida 17.0.0 发布公告(静态 API 移除清单与替代写法)+ 官方 JavaScript API 文档(Module 静态/实例方法现行清单) |
| 18 | 中 | re-frida-script-author | SKILL.md:73 | "`Interceptor.attach` 的 onEnter/onLeave 里 `this.context` 读寄存器、`this.returnValue` 改返回值" | **`this.returnValue` 不存在**:`this` 上只有 returnAddress/context/errno/lastError/threadId/depth;改返回值必须用 onLeave 参数 `retval.replace(...)`——脚本生成方法论技能写错会系统性复制进新脚本 | 改为 onLeave `retval.replace(...)`;注明 retval 跨调用复用、需留存时先复制 | 官方文档 Interceptor 节(onLeave(retval)、replace()、`this` 属性清单无 returnValue) |
| 19 | 中 | re-ics | SKILL.md:87 | `ModbusPDU03ReadHoldingRegistersRequest(start_addr=0, quantity=10)` | **字段名错**:scapy 定义为 camelCase `startAddr`(`XShortField("startAddr", 0x0000)`),可直接复现 | 改 `startAddr=` | scapy 源码 `scapy/contrib/modbus.py` 字段定义 |
| 20 | 中 | re-angr | SKILL.md:25,122;references/gotchas.md:5 | "angr 9.2.x 支持 Python 3.8–3.11" | **9.2.x 不是固定区间**:下限随补丁版本抬高(9.2.91 要求 ≥3.8 → 9.2.203 要求 ≥3.10);"9.3.0 起 3.12+" 半句正确 | 改为"9.2.x 下限随补丁版本抬高,装前以目标版本 PyPI `requires-python` 为准" | PyPI 元数据:9.2.91(≥3.8,2024-02)、9.2.203(≥3.10,2026-02)、9.3.4(≥3.12) |
| 21 | 中 | re-ios-jb | SKILL.md:88 | `Memory.readCString(a[0])` | **`Memory` 下无 readCString**(Memory 静态仅 scan/alloc/copy/dup/protect/patchCode/queryProtection/allocUtf8String 等);读 C 字符串是 NativePointer 实例方法(本库自查发现,与 #17 同类) | 改 `a[0].readCString()` | 官方文档 Memory 节方法清单 + NativePointer 节 |
**说明**:re-frida-script-author 的 gotchas.md 与 SKILL.md 坑节此前已正确记载 Frida 17 迁移写法——说明问题不在知识缺失,而在"迁移只写进了说明、没落到示例";本次修复即把示例与说明对齐。
## 批 3(2026-09-13,独立监控第二轮)
覆盖 8 个技能,16 项——**15 项确认并修复,1 项误报**(#37)。
| # | 严重度 | 技能 | 位置 | 现状(原文) | 问题 | 修正方向 | 核验依据 |
|---|---|---|---|---|---|---|---|
| 22 | 高 | re-automotive | SKILL.md:96 | `candump -c can0 # 每 ID 帧计数` | **`-c` 是颜色模式**(increment color mode level),不计数——照抄得到彩色输出而非统计 | 改 `candump can0 \| awk '{print $2}' \| sort \| uniq -c`;坑节同步 | can-utils 源码 `candump.c` usage |
| 23 | 中 | re-automotive | SKILL.md:87 | "落盘日志(自动轮转…)" | **无轮转**:源码只一次 `fopen(logname,"w")`,无大小/时间触发;默认文件名带时间戳 | 改述为"默认文件名带时间戳;无轮转,需要轮转交给 logrotate/外部脚本" | can-utils 源码 `candump.c` 日志处理段 |
| 24 | 高 | re-disk-forensics | SKILL.md:89 | `tsk_recover -e … # 批量恢复全部已删除文件` | **语义反了**:默认行为才是只导未分配(已删除)文件;`-e` 是已分配+未分配**全部文件**(`-a` 只导已分配) | 默认命令去掉 `-e`;`-e` 单列一行注明"全部文件" | sleuthkit `tsk_recover(1)` man page |
| 25 | 中-高 | re-disk-forensics | SKILL.md:115 | `dd … skip=<A_end> count=<B_start-A_end>` | **off-by-one**:mmls 的 End 是含端点的末扇区(源码 `part->start + part->len - 1`,即 Length=End-Start+1);真正的 gap 从 A_end+1 起 | 改 `skip=$((A_end+1)) count=$((B_start-A_end-1))`;提示直接用 mmls 的 Unallocated 项 Start/Length | sleuthkit 源码 `tools/vstools/mmls.cpp`(printf 与算术) |
| 26 | 高 | re-format-pe | SKILL.md:102 | `for cid, count, off in rh['values']:` | **必然报错**:pefile 的 `values` 是扁平整数数组 `[compid, count, …]`(源码 `headervalues += [.., ..]`),无三元组、无 `off`,且已按 key 解密 | 改 `vals=rh['values']; zip(vals[0::2], vals[1::2])` | 本地装 pefile 读 `parse_rich_header` 源码 |
| 27 | 高 | re-format-pe | SKILL.md:86 | `ptr_size = 8 if pe.FILE_HEADER.Machine == 0x8664 else 4` | **判据错**:位宽由 Optional Header Magic 决定(0x10b=PE32 / 0x20b=PE32+);ARM64(0xAA64) 也是 PE32+,会被按 4 字节读 | 改按 `pe.OPTIONAL_HEADER.Magic == 0x20b` 判定 | PE/COFF 规范(Machine 与 Magic 语义分离) |
| 28 | 高 | re-format-elf | SKILL.md:91 | "`DT_BIND_NOW`/FLAGS 出现 = 全 RELRO、GOT 只读" | **把两个独立条件写成等价**:BIND_NOW 只表示启动时完成绑定;只读重定位区由 `PT_GNU_RELRO` 建立 | 全 RELRO = `PT_GNU_RELRO` + BIND_NOW;仅 RELRO = Partial;仅 BIND_NOW 推不出 RELRO | GNU ld 文档(`-z now` 与 `-z relro` 分列定义) |
| 29 | 中 | re-format-elf | SKILL.md:73 | `objdump -d -j .init_array` "逐条反汇编回调地址" | **-d 不处理数据节**:.init_array 是函数指针数组,-d 只反汇编被标记为指令的节,实际无输出 | 改 `objdump -s` 取指针,再按指针地址反汇编目标函数 | objdump 语义(节标志决定 -d 范围) |
| 30 | 高 | re-format-elf/references/layout.md | :32,:34,:132 | e_phnum/e_shnum 扩展编号写成同一套("同上 PN_XNUM 溢出处理") | **混了三套独立规则**:e_phnum==PN_XNUM → `shdr[0].sh_info`;e_shnum==0 → `shdr[0].sh_size`;e_shstrndx==SHN_XINDEX → `shdr[0].sh_link` | 三条分别写清,并建议配 parser fixture 验证 | ELF 规范(扩展编号三规则) |
| 31 | 中 | re-format-elf/references/layout.md | :29 | e_flags "MIPS 的字节序/ABI 位" | **无字节序位**:MIPS e_flags 是 ABI/ISA/PIC/NaN 等;字节序始终由 `e_ident[EI_DATA]` 决定 | 改述为 ABI/ISA/PIC/NaN,并注明字节序看 EI_DATA | ELF/LLVM 的 EF_MIPS_* 定义 |
| 32 | 高 | re-format-macho | SKILL.md:70,:130;references/layout.md:89 | `__LINKEDIT` "无映射内容""运行时不可访问" | **错**:它是正常段(有 vmaddr/vmsize),通常映射为只读区域(vmmap 可见);只是 shared cache 场景链接元数据驻留方式不同 | 改述为"只读映射段;shared cache 影响驻留方式",并提示按 LC_SYMTAB 用 nm/dyldinfo 定位而非照抄文件偏移 | Mach-O 段语义 + dyld shared cache 行为 |
| 33 | 中 | re-macos | SKILL.md:56 | "看 `com.apple.quarantine`(…来源 URL)" | quarantine 记录隔离标志/时间戳/责任方,**不含来源 URL**;来源信息在 Spotlight 属性 | 来源改用 `mdls -name kMDItemWhereFroms` | Apple quarantine 与 kMDItemWhereFroms 语义 |
| 34 | 中 | re-address-space | SKILL.md:55 | "PIE = 0(所有地址是相对偏移)"当不变量 | **格式无此要求**:ET_DYN 的最低 p_vaddr 不必为 0;load_bias 应按最低 PT_LOAD p_vaddr 与运行时映射求差 | 改为"取最低 PT_LOAD 的 p_vaddr,别假设 PIE 必为 0" | ELF GABI(base / load bias 定义) |
| 35 | 高 | re-hypervisor | SKILL.md:68 | VMCS 编码"索引在 bits 9:0" | **漏 bit0 语义**:bit0=访问类型(full/high),索引在 bits 9:1(9 位);类型 bits 11:10、宽度 bits 14:13 | 写全四段位域并给解码式 `index=(enc>>1)&0x1ff` 等 | Intel SDM VMCS 字段编码(示例 0x400C/0x681E 复核通过) |
| 36 | 高 | re-hypervisor | SKILL.md:87 | `echo 1 \| sudo tee /sys/module/kvm_intel/parameters/nested` | **当前内核写不进去**:`module_param(nested, bool, 0444)` 只读,sysfs 写入失败 | 改 `modprobe -r kvm_intel && modprobe kvm_intel nested=1`,`/etc/modprobe.d` 持久化,读参数验证 | 内核 commit 801d3424(`module_param(nested, bool, S_IRUGO)`,S_IRUGO=0444 只读)+ RHEL/Fedora/SUSE 文档均以 modprobe 重新加载开启 |
| 37 | 误报 | re-uefi | —— | 监控称仓库有 `uefifind fw.bin all list <GUID>` 并把 GUID 文本当 pattern | **仓库不存在该写法**:`uefifind` 全文仅 2 处且都正确(位置参数语法 + 紧邻一行已指向 UEFIExtract 的 GUID 模式) | 不修;记录为误报 | 全仓 grep + `uefifind(1)` man page 复核 |
### 工程性问题:历史文档污染(本轮记录,已缓解)
- **现象**:`docs/superpowers/{plans,specs}/` 是历史存档、不随技能修订同步——grep 确认 2 处保留已修正的旧错误(`plans/2026-08-18-six-skills.md:239` 的 `SecKeyCreateWithData`;`plans/2026-08-18-six-skills-v2.md:449` 的"内容哈希 + manifest.plist 映射")
- **风险**:不在人读,而在 Agent/RAG 全仓检索时把已修错误重新召回
- **缓解(已实施)**:① 新增 `docs/superpowers/README.md` 声明本目录为历史存档、当前事实以 `.claude/skills/` 为准;② 两处旧错误就地标注"已于 2026-09-13 修正 + 现文位置"(保留原文,不重写历史);③ `CLAUDE.md` 开发工作流节加注:历史存档不得当现行指引检索
- **待定**:是否给全部 27 个历史文档统一加头部横幅(当前只处理了含已知错误的 2 个文件)
### 批 3 补充:工具链一致性问题(#38,用户报告,已修)
| # | 严重度 | 位置 | 现象 | 问题 | 修正方向 | 核验依据 |
|---|---|---|---|---|---|---|
| 38 | 高(工具链) | `validate.mjs` vs `bin/convert.mjs` | 规范(`docs/skill-template.md`)写「frontmatter 标准 YAML」,但 `validate.mjs` 是逐行解析、**不支持块标量**;`bin/convert.mjs` 另有一套支持块标量的实现 | **同一仓库两个解析器对同一批文件结果不同**:104/121 个技能的 `description` 用 `>` 折叠块,validate 侧解析成字面量 `">"`(非空 → 恒过),**「description 非空」校验对 86% 的技能是空转**;且名称/描述一致性无从校验 | 抽出单一实现 `lib/frontmatter.mjs`(支持简单 scalar / 块标量 `>` `|` / 内联 flow list 与 JSON;其余 YAML 特性显式不支持并写明扩展流程),`validate.mjs` 与 `bin/convert.mjs` 改为共用;补回归测试 | 对全部 121 个技能同时跑两个解析器:修复前 104 个 `description` 不一致;块标量为空/歧义 0 个 |
| 38-fix | —— | 新增 `lib/frontmatter.mjs`、`tests/frontmatter.test.mjs`;改 `validate.mjs`、`bin/convert.mjs` | —— | —— | 6 条新测试:折叠/字面块标量、空块标量报错、块标量不吞并同级键、`splitFrontmatter` 行为、**全技能跨解析器一致性回归**(直接编码被破坏的那条不变量) | `npm test` 31 项通过(原 25 + 新 6);修复后 `description` 不一致 0 个、空描述 0 个 |
### 批 3 补充 2:触发词双语校验(#39,用户要求,已实施)
- **背景**:#38 修复前 validate 看不到块标量里的真实 description,`AGENTS.md` 的「description 含中英触发词」约定从未被 CI 兜住
- **实施**:`validate.mjs` 的 `checkSkillDir` 增加断言——description 须同时含 CJK(U+3400–4DBF / 4E00–9FFF / 3040–30FF / AC00–D7AF)与拉丁字母;规格同步 `docs/skill-template.md`、`AGENTS.md`、`CLAUDE.md`
- **存量核查**:实施前全量检查 121 个技能——双语俱全 121、缺 CJK 0、缺拉丁 0,规则不误伤存量
- **测试**:新增 1 条(双语通过 / 仅中文报错 / 仅英文报错);4 个测试夹具与 2 处内联 description 同步补英文(夹具只应暴露其目标缺陷,不叠加无关错误)
- **结果**:`npm test` 32 项通过(原 31 + 新 1)
### 批 3 补充 3:能力层未闭环(#40,用户报告,部分闭环)
- **核查(三处断点)**:
1. **声明覆盖**:仅 23/121 技能声明 capabilities(网关 11/12、原子 12/108、入口 0/1)
2. **消费**:0——全仓 `grep capabilit` 在 `re-analyze/` 下只命中注册表自身;triage/rerouting 仍按领域名与关键词路由
3. **完整性**:只有"标签须在注册表内"一条检查;注册表 52 个标签中 **15 个无人声明**(悬空)
- **本次闭环**(元数据 → 索引 → 可查询 → CI 防漂移):
- 悬空清零:为 15 个悬空标签补声明(14 个技能,均为技能名与标签语义一一对应者,如 `tracing`→re-tracing、`tee-analysis`→re-tee、`binary-diffing`→re-variant)——现 **标签 52/52 有声明**
- 新增查询表 `re-analyze/references/capability-index.md`(`lib/capability-index.mjs` 渲染、`bin/capindex.mjs` 生成):「能力 → 技能」反查 + 未声明清单 + 覆盖率计数(标签口径 + 技能口径),路由/检索首次有消费入口
- CI 两条新检查:注册表标签悬空 → 报错;索引过期 → 报错(提示 `node bin/capindex.mjs`)
- 测试 +5(注册表解析 / 标签反查 / 悬空检出与消失 / 索引三态(缺失·过期·同步)/ 渲染内容)
- **仍未闭环(需定策略)**:
- **技能覆盖 37/121**——按注册表既定的「渐进策略」,剩余 84 个技能未标注;本次只补悬空项,未做全量标注(避免与既定策略冲突)
- **路由仍按领域名**——triage/rerouting 未改为「输入特征 → 需要能力 → 技能」,索引已就绪,属设计级改造
- **结果**:`npm test` 37 项通过;`OK: 121 skills validated`
### 批 3 补充 4:全局数据契约偏文件域(#41,用户报告,已修)
- **现象**:`re-analyze/references/analysis-contract.md` 的 §一 上下文清单与 §三 数据契约只有一套文件域字段(`sha256 / arch / format / entropy / sections / imports_exports / strings_refs / base_addr / symbols_known`),除 `sha256` 外均为 PE/ELF 视角——SDR、CAN、AI 模型、TEE、取证等域无字段可用
- **影响面**:81 个文件引用 `[[analysis-contract]]`;点名具体字段的仅 2 处(re-triage 输出契约、re-address-space 的 base_addr);其余为非文件域技能的泛引(只引 §四 复核格式,域中立)——故改动以契约结构为主
- **修复**:改为两层结构——**核心字段**(所有域必带:target_id / sha256 / evidence / findings / unverified,与 §四 复核格式对齐)+ **域扩展字段**(10 个域组:文件/二进制、网络/协议、总线/车载、射频/SDR、AI 模型文件级、AI 模型行为级、移动/托管、TEE、取证/情报、沙箱/行为);§一 上下文清单改按域展开;新增 §3.3 传递规则(核心必带、域字段选填不要求跨域填充、只增不改)
- **核验**:用户点名的 5 个域(SDR / CAN / AI model / TEE / 取证)均有字段组;契约内 `[[链接]]` 全部解析通过;非文件域技能无硬套文件域字段的表述(逐条 grep 确认)
- **结果**:`npm test` 37 项通过;`OK: 121 skills validated`
### 批 3 补充 5:能力层剩余缺口闭环(#42,用户要求,已闭环)
- **技能覆盖**:84 个未声明技能全部标注——**原子技能 108/108**(入口 `re-analyze` 与元网关 `re-feedback` 按策略省略,索引显示 119/121)
- **标签缺口**:全量标注暴露注册表缺口——12 类能力此前无标签可表达(架构相关、语言运行时产物、磁盘取证、eBPF、Electron、虚拟化、越狱、跨平台框架、利用开发、二进制补丁、插件开发、沙箱搭建),补齐(52→64)
- **路由按能力匹配**:`triage.md` 目标表(19→30 行)与 `rerouting.md` A 表(23→33 行)全部加「需要能力」列,技能列改为索引反查结果;A 表同时补齐此前缺行的域(语言产物、RISC-V/MIPS、hypervisor、eBPF、磁盘/整机取证、越狱、白盒、内核驱动、HarmonyOS、TLS、变体对比)
- **CI 防漂移**(累计 4 条):原子技能必须声明能力|路由能力列标签须在注册表内|路由标称能力须被本行技能声明|索引须与声明同步(+ 此前的注册表标签不得悬空)
- **反向验证**:故意改错 A 表一行能力 → validate 精确报出 `rerouting.md:15 路由标称能力 'tls-analysis',但本行技能(re-packer-id / re-anti-analysis)均未声明该能力`;还原后 OK
- **结果**:`npm test` 39 项通过(+2:原子技能必须声明、路由一致性);`OK: 121 skills validated`
- **遗留(可选)**:网关内部选择树未加能力列——网关内调度仍按输入形态判定树,属网关层设计,未纳入本轮
### 批 3 补充 6:网关选择树能力标注(#43,用户要求,已完成)
- **范围**:11 个有选择树的网关(re-binary-core 与 re-anti-analysis 无独立选择树,走「完整工作流」段)+ 各网关完整工作流段
- **产出**:**336 处链接标注能力**(选择树段 100% 覆盖,11 个网关全部 0 遗漏);网关内调度可直接读「输入形态 → 技能(能力:`tag`)」
- **约定**:`[[re-xxx]](能力:`tag1`、`tag2`)`——**显式「能力:」前缀**。标注过程中发现原格式 `(`tag`)` 与「链接 + 反引号代码」不可区分:re-memdump 的 `[[re-x64dbg]](`minidump` 命令)` 被误判成能力标注(`minidump` 非注册标签),故加前缀消歧;无前缀括号一律视为普通说明
- **CI**:选择树段内技能链接必须带标注;标注的能力须在注册表内且被被标注技能真的声明;非技能链接(references 文档如 [[platform-tips]])豁免
- **反向验证**:删掉 re-mobile 一处标注 → `FAIL: re-mobile: 选择树内 [[re-apk]] 缺少能力标注(形如 [[re-apk]](能力:\`能力\`))`;还原后 OK
- **过程中修正的检查器缺陷 2 处**:① 括号嵌套时把内层 `[[子技能]](能力:…)` 的标签算到外层(改为只取链接括号**开头**的连续标签段);② references 链接被误要求能力标注(改为只校验技能链接)
- **结果**:`npm test` 40 项通过(+1:选择树标注一致性);`OK: 121 skills validated`
### 批 3 补充 7:新增 re-sample-acquire(#44,用户要求,已落地)
- **缺口**(用户发现):"只有现象描述、没有样本"时缺一个采集环节——现有零件都以前提"样本已在手"开头([[re-memdump]] 需已知 PID、[[re-netcap]] 需能抓包、[[re-fileless]] / [[re-loader]] 需已有样本、[[re-triage]] 需已有文件);入口输入类型表也无"现象描述/无样本"这一档
- **形态**:新增原子技能 `re-sample-acquire`(能力标签 `sample-acquisition`;原子 108→109,总数 121→122)= SKILL.md(141 行)+ 4 份平台分支 `references/platform-{windows,linux,macos,sel4}.md`(共 248 行)
- **核心方法论**(用户提供 + 社区实践核验):
- CORE RULE:**不猜进程名、不依赖"用了哪个注入 API"**——找「异常执行内存 + 到达该内存的执行上下文」;先问 provenance(这块可执行内存是谁创建的、经什么路径进来)
- 两特征 + 一补充:内存被改成可执行(W→X / RWX);无背书区域在执行;线程起点/RIP/调用栈归属
- **漏检点**(本轮重点补的):只查 `MEM_PRIVATE` 会漏 module stomping(`MEM_IMAGE` + COW,需查 Working Set `.Shared` 位);只看线程起点会漏 trampoline / `SetThreadContext` / `jmp rcx` / Win11 `_beginthreadex` 等绕过(要 PC + 调用栈一起看);只按 MZ/PE 头找载荷会漏**擦头 implant**(保存整区再分类);JIT/Wine/浏览器/安全软件本身就产生同类 artifact →**评分制而非二元判定**
- trigger 与 ground truth 分工:事件源只回答"**何时** dump",内存扫描回答"**dump 什么**"(直系统调用/共享段/覆盖已有 RX 区都能绕过用户态 hook)
- **四平台观测模型不同(用户要求不得机械翻译)**:
- **Windows**:VAD/region + 线程 + 模块链;Sysmon 8/10/25、ETW-TI、内核回调三件套
- **Linux**:VMA(`/proc/<pid>/maps`,perms/pathname 语义;**6.11+ `PROCMAP_QUERY` ioctl**);tracepoint/kprobe 与 **BPF LSM**(内核 BPF LSM 文档即以 `file_mprotect` 为示例,`SEC("lsm/file_mprotect")`);`process_vm_readv`/ptrace 读取(受 ptrace access check)
- **macOS**:Mach task + VM region(`vm_region_recurse_64`/`mach_vm_region*`、`mach_vm_read*`);**Endpoint Security**(`NOTIFY_MMAP`/`NOTIFY_MPROTECT`/`NOTIFY_REMOTE_THREAD_CREATE`/`NOTIFY_GET_TASK`,`AUTH_*` 可拦截);**权限现实**——SIP 下 `task_for_pid` 对受保护进程 EPERM、Hardened Runtime 默认吊销内存读取、`get-task-allow` 可恢复("不是 root 就能读")
- **seL4**:capability 制,**不存在"root 全读"模型**;路线是构造期由 monitor 记录 provenance(TCB/frame/VSpace caps → execution provenance graph),TCB debug API 与 fault endpoint 作事件源;提问从"代码藏在哪个进程"改为"**哪个 capability flow 授予了 executable authority**"
- **挂载**:入口输入类型表 + triage 路由行 + rerouting A 表 2 行 + re-malware 网关(子技能清单与选择树);re-memdump 跨域反向指向("未定转什么"时先走采集)
- **核验**:各平台事实逐条对上游(内核 `proc.rst` / `bpf_lsm.rst`、Apple ES 与 SIP/Hardened Runtime 文档、seL4 debug API、PE-sieve 选项与 wiki);`npm test` 40 项通过;`OK: 122 skills validated`;计数五处 + README 导航同步
- **备注**:本技能是新的审查面(监控下一轮会按同样标准核验其 API/命令/判据);采集动作本身留痕,技能内已写明授权边界与停止条件
### 批 3 补充 8:内核覆盖扩到跨平台(#45,用户要求,已落地)
- **缺口**(用户发现):内核态载荷覆盖**只有 Windows**——`re-kernel` 标题/触发词写死 Windows,且「何时不用」原文把 Linux 推给零散技能;全库关键词扫描 `LKM` / `System Extension` / `kmod` / `insmod` **0 命中**,`kext` 仅 2 处顺带提及
- **形态**:`re-kernel` 重构为跨平台 = SKILL.md(92 行主干)+ 4 份平台分支(windows-kernel 76 / linux-kernel 74 / macos-kernel 55 / android-kernel 42);原 Windows 内容**原样迁入** windows-kernel.md;两个纯 Windows 的旧 references 更名(`gotchas.md`→`windows-gotchas.md`、`decision-tree.md`→`windows-decision-tree.md`,`git mv` 保留历史)以免与新范围混淆
- **结构核心**(按用户要求):**失败模式决策表**——六类症状(struct offset 全错 / 符号解析怪异 / 文件与运行行为不一致 / 模块"消失" / driver IPC 调不通 / 异常 ELF section)→ 优先怀疑项(按顺序)→ 处理方向。要点是"观察与预期冲突时先怀疑什么",而不是工具清单
- **macOS 按要求拆两代**:KEXT(`Info.plist` 先行 → selector map 优先 → **AuxKC 版本坑** → codeless kext → arm64e PAC)与 System Extension / DriverKit(**用户态进程模型**、激活与 entitlement 排错顺序:activated? → service? → entitlement/Team ID/sandbox → 才轮到 selector)
- **Linux 收录失败模式**:`.ko` 是 ET_REL(relocation 即信息);四类"看着像坏"的合法形态(签名尾 / BTF 与 split BTF+`.BTF.base` / RANDSTRUCT / livepatch `.klp.rela`);**5.7 起 `kallsyms_lookup_name()` 不再导出给模块**;rootkit **cross-view**(`lsmod` 干净 ≠ 没有 + hook 落点不止 syscall table)
- **Android**:GKI vs vendor module、protected symbol(KMI 白名单:构建期检查 `check_buildtime_symbol_protection.py` + 运行期拒绝加载)、**KMI 分支不可互换**(`android12-5.10` ≠ `android13-5.10`)、模块位置与 `modules.load` 计划
- **采集侧同步**([[re-sample-acquire]]):Linux 分支加"内核态载荷采集"(cross-view、内核 text 与磁盘副本 diff、hook 落点、采集时机、授权边界);macOS 分支加"KEXT/DEXT 采集"(DEXT 按用户态进程处理、kext 先对齐 AuxKC 运行版本、内核内存读取的 SIP 现实)
- **核验(8 项上游)**:kprobes 文档("通常由 kernel module 注册")、5.7 unexport 提交、`CONFIG_DEBUG_INFO_BTF_MODULES` 与 distilled `.BTF.base`(仅外置模块生成)、`TAINT_RANDSTRUCT` 与配置名、livepatch 节格式与 `SHN_LIVEPATCH`、AuxKC 与 LocalPolicy 字段、Android protected symbol/KMI 分支、dext 安装路径与 userclient entitlement。**两处口径修正**:① 5.7 的变化是"停止导出"而非 kallsyms 格式变更;② RANDSTRUCT 的**配置名**是 `CONFIG_GCC_PLUGIN_RANDSTRUCT`(`T` 是 taint 字符)
- **结果**:`npm test` 40 项通过;`OK: 122 skills validated`
- **顺带发现(系统性问题,未修)**:references **同名文件普遍**——`gotchas.md` 33 个、`decision-tree.md` 13 个,导致 `[[gotchas]]` 一类链接在多技能间**歧义**(validate 只检查"存在"不检查"唯一")。候选规则:references basename 全局唯一,或链接限定技能前缀——待定
### 批 3 补充 9:seL4 分析分支(#46,用户提供,已落地)
- **背景**:用户指出 seL4 的经验更特殊——核心**不是"内核模块怎么逆",而是"如何不把 capability 系统的行为误判成普通 OS 行为"**;此前 seL4 只落在采集侧([[re-sample-acquire]] 的 monitor 视角),分析侧无覆盖
- **形态**:`re-kernel` 新增第五个平台分支 `references/sel4-kernel.md`(**201 行,五个分支中最大**,印证"特殊情况密度可能高于 Linux LKM");SKILL.md 平台差异表加 seL4 行、失败模式决策表加 3 行(CPtr 本地地址 / MCS 卡住 / IRQ 只来一次);[[re-sample-acquire]] 的 platform-sel4.md 加"方法侧入口"互链
- **内容**(16 节 + 压缩决策树):先识别运行模型(root task / 裸 libsel4 app / capDL / CAmkES / MCS / VM)→ **CPtr 是 CSpace 本地地址不是全局 ID**(跨 component 必须按 **kernel object** 对齐)→ capDL-loaded 不照搬 root-task slot 语义 → CAmkES glue 折叠 → badge(身份 vs bit 聚合事件)→ CSpace guard/depth 与 FailedLookup 四分类 → **错误码即诊断**(DeleteFirst=目标非空 / RevokeFirst=有派生 / FailedLookup=index·depth·类型)→ Untyped 非 malloc(2^n 对齐、Revoke 父 untyped 才可重用)→ **device untyped 只能变 Frame** → IRQ 走用户态(未 ack 不再送)→ **DMA 旁路不在 isolation proof 内** → fault 是 IPC(反复同一 fault = handler 没修)→ MCS(SC/budget/passive server/reply object/捐赠链被打断)→ capDL snapshot cross-view → capability 图必须带 rights
- **核验(上游)**:seL4 manual(CSpace 与 CNode guard/depth 语义、错误码定义、**"device untyped 只能 retype 成 frame 或子 untyped"** 及附加限制);MCS 发布说明与提交(SC = budget/period、passive server 依赖 client 捐赠、reply object 取代 `SaveCaller` 并跟踪捐赠、timeout fault、**链中 reply object 被撤销则 SC 回不到发起者**);debug API(`seL4_DebugSnapshot` 输出 capDL、`seL4_DebugCapIdentify` 返回 cap 类型号);capDL loader 与 root task 初始环境(slot 2/3 语义、初始 CNode guard 恰好解析 32 位)
- **核验中的三处精化**:① `seL4_DebugSnapshot` 据 devel 列表是**二进制命令/响应协议**(等命令字 0xa0–0xff、回传二进制),不是人类可读文本转储;② device untyped 的限制**不止**"只能变 Frame"——device frame 还不能作 IPC buffer、不能建 ASID pool、ARM 上不能做可执行 frame,且 device 属性会被子 untyped 继承;③ Linux 侧同批核验中确认 5.7 的变化是 `kallsyms_lookup_name()` 停止导出(非格式变更)
- **结果**:`npm test` 40 项通过;`OK: 122 skills validated`
### 批 3 补充 10:references 同名歧义治理(#47,用户决策,已落地)
- **决策**:`[[gotchas]]` 这类跨技能裸链有歧义(`gotchas.md` 33 个、`decision-tree.md` 13 个)——用户在"basename 全局唯一"与"链接限技能前缀"之间选了**后者**
- **规则**:技能链接 `[[re-xxx]]`;**裸 references 链接 `[[文件名]]` 必须落在本技能 `references/` 内**;跨技能引用必须写 `[[re-xxx/文件名]]`(validate.mjs 强制,**references 文件内同样校验**——此前只查 SKILL.md 正文)
- **迁移**:**471 处**跨技能裸引用加前缀(`platform-tips` 347、`analysis-contract` 104、`anti-dynamic-workflow` 10、`frida-scripts` 8、`rerouting` 1、`sel4-kernel` 1);**287 处**本技能内引用保持裸链;2 处重命名遗留(re-kernel 的 gotchas/decision-tree)改为指向同技能新名
- **校验器改动**:链接检查重写为三态判别(技能 / 跨技能 references / 本技能 references),并把校验范围从 SKILL.md 正文**扩展到 `references/*.md`**(跨技能引用多在这边)
- **占位符约定**:文档里写示例用尖括号形式 `[[re-<技能名>]]` / `[[<文件名>]]`——不会被解析成真链接(改动过程中 capabilities.md 的格式说明自己触发过一次断链报错,即此问题)
- **反向验证**:在 `re-kernel/references/windows-gotchas.md` 里写裸 `[[platform-tips]]` → `FAIL: re-kernel/references/windows-gotchas.md: broken [[platform-tips]] link(裸 references 链接须在本技能 references/ 内;跨技能请写 [[re-xxx/platform-tips]])`;还原后 OK
- **结果**:`npm test` **41 项**通过(改 1 条链接规则用例 + 新增 1 条跨技能限定用例);`OK: 122 skills validated`
### 批 3 补充 11:技能计数同步不完整(#48,用户发现,已修)
- **现象**:新增 `re-sample-acquire` 后,计数只在"记得的 5 处"同步(README/README_EN/AGENTS/package.json/marketplace.json + README 网关行),**漏了 5 处**:`CLAUDE.md` 3 处(技能总数、`OK: 121 skills validated` 示例、架构图"原子技能 108 个")、README/README_EN 前言"12 大类网关 → **108** 原子技能"
- **根因**:① 同步清单本身是记忆产物,没有"计数出现点"的全量来源;② 自查 grep 用了"旧数+单位"的复合模式,对全角括号与措辞差异过敏 → **首轮扫描报"零命中"的假阴性**(真正的发现来自换用"数词散扫 + 逐文件人工核")
- **修法**:5 处改为 122/109;历史记录(`TODO.md`、`docs/audit/`、`lib/frontmatter.mjs` 注释里的"104/121"等)保留原值——它们是当时事实
- **固化**:`CLAUDE.md` 的「新增/修改技能的标准流程」第 4 步从"同步 5 处"改为**逐处清单**(README 4 处 / README_EN 4 处 / AGENTS 2 处 / package.json / marketplace.json / CLAUDE.md 3 处),并写明自查方式与"不要用复合模式"的教训
- **核对**:实际结构 **122 = 1 entry + 12 gateway + 109 atomic**,与文档现值一致
- **结果**:`npm test` 41 项通过;`OK: 122 skills validated`
### 批 3 补充 13:macOS 低层分支加深(#49,用户提供,已落地)
- **背景**:用户补充 macOS 低层逆向的失败模式——macOS 的坑在于**三套完全不同的模型混在一起**(KEXT+IOKit 内核态 / DriverKit·DEXT 用户态 / System Extension 框架),且四个事实最容易让整条分析链跑偏:① codeless KEXT 可能根本没代码 ② 磁盘 KEXT 与当前运行的可能不是同一版本(AuxKC)③ arm64e 指针不能当普通 64 位指针(PAC)④ `IOServiceOpen` 失败可能停在 entitlement/activation 层,根本没走到 UserClient
- **形态**:`macos-kernel.md` 从 55 行扩到 **286 行**(现为该技能最大分支);主干平台表 macOS 行改为「三套模型」,失败模式决策表加 3 行(符号化偏移 / kext 加载不了的完整条件 / UserClient 与 dispatch)
- **新增要点**(相对旧版):`Info.plist` 的 IOKitPersonalities 匹配键全集与"Info.plist 先行"顺序;**IOKit class graph 优先于 call graph**(OSMetaClass/vtable;unresolved virtual calls 常因缺 kernel/superclass type universe);dispatch 字段的 **`check` 前缀**与 `kIOReturnBadArgument` 可能是**框架层拒绝**(含 completion 需要有效通知 Mach port);dext 的停手信号与按用户态调试;System Extension ≠ DriverKit 同义词;Host app 与 dext 两边都要逆;六态生命周期(bundle→registered→approved→activated→matched→started);**Rosetta 不翻译 kext**(`KMErrorDomain Code=71`);Kernel Collection;**panic 符号化的 `__TEXT_EXEC.vmaddr` 偏移**与 UUID/KDK build 匹配;UAKL / Reduced Security / AuxKC / SIP 与签名校验的关系;**KIP** 机制;rootkit 的年代差异(10.x Intel → 11+ Apple Silicon);KEXT 双机调试 vs DEXT 本机调试
- **核验(6 项上游)**:Apple 文档的 dispatch 字段名(确认带 `check` 前缀,与 arguments 字段区分)、`kIOReturnBadArgument` 的端口成因(StackOverflow 实例为 `checkCompletionExists=true` + 错误端口)、panic 符号化 `__TEXT_EXEC`(Apple 开发者论坛 DTS 工程师答复,含 `otool`/`atos` 完整命令)、AuxKC/UAKL/1TR/签名校验(Apple 平台安全指南)、KIP 机制(内核初始化后启用、内存控制器拒写受保护区、MMU 双向限制、使能硬件启动后锁定)、Rosetta 不翻译 kernel extension(官方 Rosetta 文档 + `Incompatible architecture` 报错)
- **结果**:`npm test` 41 项通过;`OK: 122 skills validated`
- **体量备注**:`re-kernel` 现 **1094 行 / 8 文件**(主干 105 + 七份 references),已达"平台分支各自可成技能"的规模——是否拆分由用户判断,本轮未动
### 批 3 补充 14:Windows 驱动分支加深(#50,用户提供,已落地)
- **背景**:用户补充 Windows 驱动分析的失败模式(33 点 + 决策树),核心是"**先识别 driver model,再恢复 callback / 设备栈 / I/O 路径**",并点名七个最易产生事实性错误的点(把所有 `.sys` 当 WDM / `GsDriverEntry` 当入口 / `MajorFunction` 空当"无 I/O" / 不知道 KMDF·NDIS·minifilter 的 callback registration / 不知道 IRP completion 是异步控制流 / 不知道 IOCTL 的 Method 决定 buffer 语义 / 2026 年仍用旧签名假设)
- **形态**:`windows-kernel.md` 从 76 行扩到 **501 行**(技能内最大文件);同时**接回两个旧 Windows reference 的链路**(`windows-gotchas` / `windows-decision-tree` 在重写后一度成为孤儿——它们含独占内容:版本差异组与证据分级,故补链而非删除)
- **新增要点**:驱动模型分类(WDM/KMDF/UMDF/minifilter/NDIS/StorPort/PortCls/AVStream);`GsDriverEntry`;WDM 的 `DRIVER_OBJECT` 赋值图;KMDF 的 Evt* 与 `WDF_*_CONFIG` dataflow(`!drvobj` 指 Wdf01000.sys 属正常);miniport 架构与 NDIS callback 图(网卡驱动无 READ/WRITE 正常);device stack 与 **INF 的栈位置**(UpperFilters/LowerFilters/AddFilter);minifilter 的 altitude 与 pre/post 流水线;`CTL_CODE`/`METHOD_*` 语义与 **NEITHER 用户指针**;**completion edge 与 `STATUS_PENDING`**;`PAGE` section 的 IRQL 语义与偶发 0xD1;**Driver Verifier 的故障注入**与 0xC9 的追链法;PE relocation;PDB public≠private 与 signature+age;`!analyze -v` 只是入口;**UMDF/Wudfhost**(`!wdfkd.wdfumdevstacks`、`%ProgramData%\Microsoft\WDF`);**2026 驱动签名策略**;**HVCI 兼容要求**与 Test Mode 仍需签名;x64 patching 禁忌;callback-registration graph;IRP flow graph;minifilter unload 四态
- **核验(3 项上游,均带时间点)**:① Microsoft Windows Driver Policy——**2026-04 安全更新后旧 cross-signed 驱动默认不再受信**,默认只认 WHCP 签名(另有 curated allow list);**先行评估模式**(约 100 小时运行 + 2–3 次启动相关条件才转强制;期间发现不合规驱动则继续评估并重置计数);企业可用 Application Control for Business 覆盖(须由 Secure Boot PK/KEK 权威签名);适用 Win11 24H2/25H2/26H1 + Server 2025。② HVCI 官方 checklist(NX 默认、`NonPagedPoolNx`、不用 W+X 段、不直接改可执行系统内存、**内核不用动态代码**、数据不当代码、0x1000 对齐)+ **Test Mode 在 HVCI 下仍要求签名**(失败码 0xC0000428 / CodeIntegrity 219)+ Microsoft 计划 **2026-10-13** 起在符合条件设备默认启用 Memory Integrity。③ UMDF(`!wdfkd.wdfumdevstacks` 的 `!process`→`.process /P`→命令工作流;dump 路径 `%ProgramData%\Microsoft\WDF`,UMDF 2.15/Win10 1507 起;WER 三类事件 WUDFHostProblem/UnhandledException/VerifierFailure;`wdfumtriage`/`wdfldr`/`wdfumirps`/`wdflogdump`)
- **结果**:`npm test` 41 项通过;`OK: 122 skills validated`;re-kernel 全部 references 均可达(孤儿检查通过)
- **体量**:`re-kernel` 现 **1522 行 / 8 文件**(windows-kernel 501 / macos 286 / linux 277 / sel4 201 / android 42 + 主干 108 + 两份 Windows 附录)——拆分与否待用户决定
## 需澄清(非误报,但审查表述需修正)
1. **candump `-f` 确实存在**:上游 can-utils 当前版本有 `-f <fname>`(写日志文件),Debian bookworm 打包的 manpage(can-utils 2020.11.0)尚未收录该选项——核验时以源码为准。#10 的结论(原命令会写文件而非过滤)成立。
2. **re-mobile-forensics 是局部不一致而非全错**:gotchas.md:13 与 decision-tree 已含正确表述(SHA1(domain+relativePath)),缺陷集中在 SKILL.md 正文与 references 互相矛盾——修复时以 gotchas 为准并消除分歧。
## 未覆盖范围(局限)
- 批 1 为外部 AI 抽查(约几十个技能)结果、本库核验其列出的 16 项;批 2 为独立监控首轮 4 项 + 本库自查 1 项——**均非 121 技能全量逐条审计**
- #17 同类风险面:本轮已 grep 排查 `Memory.read*/write*` 型访问器与 legacy 回调式枚举(`Process.enumerateModules({...})`),未见残留——但属关键字排查,未做全量语义校验
- 未核验的外部结论一律未入库;后续批次沿用本文档状态机续记
## 核验来源清单
| 来源 | 用途 |
|---|---|
| AOSP `KeyInfo.java`(frameworks/base/keystore) | #1 #2 方法列表 |
| JDK `java.security.KeyStore` API | #1 |
| Apple Security 框架文档语义 | #3 #14 |
| HF `safetensors` README(Format 节) | #4 |
| iOS 备份结构(Manifest.plist / Manifest.db) | #5 #6 #7 |
| QEMU `hw/riscv/virt.c` | #8 |
| ECMA-335 II.25.3.3(CLI header) | #9 #13 |
| can-utils `candump.c` + Debian manpage | #10 |
| 库内原文三处对照 | #11 |
| onnx.proto `Version` 枚举 | #12 |
| PyPI volatility3 元数据 | #15 |
| 库内既有正确表述(re-anti-analysis / re-binary-core) | #16 |
## 修复记录(2026-09-13)
批 1(#1–#16)、批 2(#17–#21)、批 3(#22–#36)共 36 项**已全部修复**,状态 **fixed(待复核)**;#37 为误报未改;工程性问题(历史文档污染)已按上述三层缓解处理。
- 涉及文件 28 个(技能 SKILL.md 21 + references 7),其中 Frida 17 横向迁移覆盖 9 个文件(批 1+2);批 3 另改 10 个技能文件(含 2 个 references)+ 历史存档 2 处 + `docs/superpowers/README.md` + `CLAUDE.md`
- 校验:`npm test` 通过(`OK: 121 skills validated` + 25 项单测);grep 复核确认已移除 API 无残留(保留的"旧写法"文字均为迁移说明性注释)
- 复核入口(后续波次):按状态机 fixed → verified 逐项复核;重点复核两处语义选择——① Frida 迁移中 `find*`(返 null)与 `get*`(抛异常)在各示例语境下是否选得恰当;② re-forensics 转储分流的表述是否与实际 [[re-mem-forensics]] / [[re-memdump]] 边界完全一致
## 后续机制建议(来自同一审查,待评估)
审查提出把验证体系分四层:Syntax → API/CLI validity → Format/spec assertion → behavior fixture,即对 API 名做静态符号表比对、对 CLI 示例跑 `--help`、对格式常量做 spec 断言、对关键结论建最小 fixture(如生成最小 safetensors 验证前 8 字节、起 `-S -s` QEMU 验证 $pc、用脱敏备份验证 fileID 派生)。
可选落点:与 TODO「增量审查机制」合并设计——finding 记录(本文档格式)+ 高风险技能的 fixture 子集,先覆盖 ABI/offset/格式字段/API 名四类断言。
---
## 补充 15:特殊系统深化波次(2026-09-13,QNX / Fuchsia-Zircon / UEFI-PI / VxWorks / Zephyr / RTEMS / FreeBSD / illumos)
来源为外部整理的特殊系统调研(8 个系统的"核心模型 + 最危险误判"),按**每一条具体机制先核验上游、再入库**处理。本波次**不是缺陷修复**(原文无事实性错误),而是**事实补全与边界条件补足**,性质同"补充 1–14"。
### 落地位置(8 → 3 个技能,不新增技能)
| 系统 | 落点 | 形态 |
|---|---|---|
| QNX Neutrino | `re-rtos/references/qnx.md` | 新增分支(该技能原为单文件) |
| VxWorks | `re-rtos/references/vxworks.md` | 新增分支 |
| Zephyr | `re-rtos/references/zephyr.md` | 新增分支 |
| RTEMS | `re-rtos/references/rtems.md` | 新增分支 |
| UEFI / PI / EDK2 | `re-uefi/references/pi-stages.md` | 新增分支(该技能原为单文件) |
| Fuchsia / Zircon | `re-kernel/references/zircon-kernel.md` | 新增分支(与 sel4-kernel 并列为 capability 系统) |
| FreeBSD | `re-kernel/references/freebsd-kernel.md` | 新增分支 |
| illumos / Solaris | `re-kernel/references/illumos-kernel.md` | 新增分支 |
挂载点:`re-rtos` / `re-uefi` / `re-kernel` 的 SKILL.md(运行模型差异表 / 阶段判定表 / 失败模式决策表 / 分支指针);`re-analyze/references/rerouting.md` A 表新增 9 条"异常信号 → 换路"行。
### 核验中发现并写入的**边界条件修正**(通行说法不完整之处)
| # | 常见说法 | 核验后的准确表述 | 依据 |
|---|---|---|---|
| 1 | FreeBSD linker set 是 `struct linker_set {ls_length, ls_items[]}`,以 NULL 结尾 | 那是 **a.out 时代**的结构;**现代 ELF** 由 `__start_set_<名>` / `__stop_set_<名>` 定界,**列表不再以 NULL 结尾**——按结尾 NULL 扫描会越界;且 2001 年起宏已隐藏实现 | freebsd-src 提交 f10fa038("gensetdefs past its use-by date")+ `sys/linker_set.h` 语义 |
| 2 | illumos `attach()` 的命令值包含 `DDI_PM_RESUME` | 现行文档命令值为 **`DDI_ATTACH` / `DDI_RESUME`**;`DDI_PM_RESUME` 属**已废弃的 PM 接口**(配套 `DDI_PM_SUSPEND`),**是年代线索而非标准写法** | `attach(9E)`(illumos/Oracle 现行页)+ `pm(9P)` 声明原 PM 接口过时 |
| 3 | QNX 服务端"继承客户端优先级" | 提升**可发生在发送时刻**(不等 server 收到);**回复后不自动恢复**(直到被新消息/pulse 改变或显式设置);另有 **server boost**(无 RECEIVE-blocked 线程时);`ChannelCreate()` 的 **`_NTO_CHF_FIXED_PRIORITY`** 可关闭继承 | QNX《Priority inheritance and messages》《Server boost》+ `MsgSend()`/`ChannelCreate()` 参考页 |
| 4 | `zx_channel_write` 失败时 handle 归还原主 | **失败也会消费**(handle 被丢弃而非归还)——改动后语义为"始终消费";另:`channel_write_etc` 的 `ZX_HANDLE_OP_MOVE`/`DUPLICATE`、rights 只能收窄、in-transit handle 随 channel 销毁而关闭 | Zircon `docs/handles.md`、`channel_write`(含 ZX-2204 语义变更)、`channel_write_etc` |
| 5 | `dlopen` 的 `RTLD_LAZY` 会推迟符号解析 | **RTEMS 上两者行为相同**:`dlopen` 返回前**全部重定位已完成**;且**未解析符号不导致失败**(需 `dlinfo(RTLD_DI_UNRESOLVED)` 查)、**重名符号判错**、不支持符号版本 | RTEMS `cpukit/libdl`(`rtl.h`)与 RTEMS C User's Manual 的 runtime link editor 章节 |
| 6 | DXE 侧"不应修改 HOB"是约定 | HOB 构造调用在 DXE 阶段**会断言失败**(PEI HOB 对 DXE 只读);DXE 跨阶段状态只能走复位调用 | PI Spec Vol.1 §9(PEI to DXE Handoff)+ EDK2 `HobLib.h` 注释 |
| 7 | Zephyr 的 early init"不调用内核服务"是弱约定 | `PRE_KERNEL_1/2` **运行于中断栈的内核初始化上下文**,服务本就不可用——符合设计;反之出现线程/互斥/睡眠应先怀疑阶段判错 | Zephyr `include/zephyr/init.h` 的 level 语义 + 设备/`SYS_INIT` init 基础设施拆分 |
| 8 | VxWorks 模块"链接不完整"即损坏 | DKM(`.out`)**动态链接到内核符号表**,独立观察必然大量 unresolved;`undefined symbol` 的真实成因是 **VIP 未包含该组件**;同版本 ≠ 同 ABI 环境(随 VSB/VIP 变化) | VxWorks 7 SDK Application Developer Guide + VSB/VIP 构建说明 |
其余事实(QNX `dispatch_create`/`resmgr_attach`/`iofunc_*` 序列、io-pkt 的 `devnp-*.so` 与 `devnp-shim.so`、单线程栈上下文与 `nw_pthread_create`;DFv2 的 driver manager/host/index/runtime 与同驻本地通道;PI 阶段与 `DXE_RUNTIME_DRIVER` 生命周期、`EVT_SIGNAL_VIRTUAL_ADDRESS_CHANGE`/`ConvertPointer`;Zephyr iterable sections 与 LLEXT/`llext_add_domain`;RTEMS `confdefs.h`/`CONFIGURE_INIT` 唯一性与 `rtems_driver_address_table` 的 major=表索引;FreeBSD `SYSINIT` 排序键与 `SI_SUB_KLD` 合并时机;illumos `nulldev`/`nodev` 语义差异)均按上游文档或官方头文件核验后写入,逐条依据见各分支文末"工具与验证"。
### 本轮校验
- `node validate.mjs`:`OK: 122 skills validated`(含新分支的链接规则与路由能力校验)
- `npm test`:41 项全过;`node bin/capindex.mjs` 重生成后无差异(本波次未增删能力标签)
- 未做:行为 fixture(LLEXT 装载、io-pkt 加载、OVMF 阶段切换等需真实目标或构建环境)——沿用"后续机制建议"的四层体系,先落在可选层
---
## 补充 16:特殊系统第二批(2026-09-13,分层 hypervisor / 分区 RTOS / 组件 OS,18 类)
来源为同源的外部整编("再往外一层"两批:10 类 + 8 类)。处理方式同补充 15:**逐条机制先核验上游再入库**,属事实补全与边界条件补足,非缺陷修复。
### 落地位置(18 → 4 个技能,不新增技能)
| 类别 | 系统 | 落点 |
|---|---|---|
| 分区/嵌入式 hypervisor | Xen、QNX Hypervisor、Jailhouse、ACRN、Bao | `re-hypervisor/references/{xen,qnx-hypervisor,jailhouse,acrn,bao}.md` |
| RTOS 家族 | NuttX、eCos、ThreadX Modules、FreeRTOS 上下文、INTEGRITY/ARINC 653/VxWorks 653/PikeOS | `re-rtos/references/{nuttx,ecos,threadx-modules,freertos-context,partitioned-rtos}.md` |
| 通用 OS 内核 | OpenBSD、NetBSD、Genode、MINIX 3、Plan 9·9front | `re-kernel/references/{openbsd-kernel,netbsd-kernel,genode,minix3,plan9}.md` |
| 汽车软件 | AUTOSAR Classic | `re-automotive/references/autosar-classic.md` |
挂载:4 个 SKILL.md(平台差异/运行模型表 + 失败模式决策表 + 分支节 + description),`rerouting.md` A 表新增 15 行。
### 核验中确认的**关键边界条件**(写入时以这些为准)
| # | 主题 | 准确表述 | 依据 |
|---|---|---|---|
| 1 | OpenBSD KARL | **变的是内核内部布局,不是加载基址**(与 KASLR 区分);启动代码可被 unmap 或"trash";**手工把内核拷到 `/` 会使重链接脱开**(分析环境≠生产环境) | KARL 原始设计公开讨论 + locore 固定/其余 `.o` 随机重排的实现描述 |
| 2 | OpenBSD pledge | 违规是**不可捕获的 SIGABRT**(非可捕获错误);promise **只能削减不能恢复**,提升尝试返回 `EPERM`(继承 execpromises 场景下被忽略并返回成功);**"不调用 pledge" ≠ `pledge("everything")`**;`error` promise 改为返回 `ENOSYS`;线索为 `ps` 状态 `p` 与 `lastcomm` 的 `P` 标志 | `pledge(2)` 手册页与其 ERRORS/承诺表 |
| 3 | NetBSD 模块路径 | `KERNEL_DIR` 是 **2025-04-28 起**(UPDATING 20250427)的**可选**构建选项,**仅 i386/amd64**;旧 `/stand/<arch>/<版本>/modules` 与新 `<内核目录>/modules` 并存;另有 kern/59394(内核仍以文件形式放在 `/netbsd` 时 `kern.module.path` 报错) | NetBSD UPDATING、`wiki.netbsd.org/kernel_dir/`、kern/59394 |
| 4 | Xen grant 撤销 | **映射期间 Xen 不支持撤销**:结束外来访问只阻止后续映射,须等 `GTF_reading`/`GTF_writing` 清零;grant reference = 本域 grant table 条目下标(条目含 flags/domid/frame-MFN) | Xen `docs/misc/grant-tables.txt` + 接口文档 |
| 5 | Xen event port | 端口整数**绑定到每 guest `shared_info` 的位掩码**(32 位 guest 1024 位、64 位 guest 4096 位);**迁移/重连时稳定的是 remote port**,本地端口重新分配,且解绑后**可被重用** | 相关提交(save remote evtchn port, not local port)+ event channel 文档 |
| 6 | QNX Hypervisor shmem | 工厂页**写 `size` 才触发创建**(首次使用时创建 → **各 guest 启动顺序无关**);共享区可表现为 MMIO 或 PCI(默认 PCI);**直通设备同一时刻只允许一个 resident 访问** | QNX 8 文档:shmem vdev、factory/control pages、configuring guests |
| 7 | Jailhouse loadable | `JAILHOUSE_MEM_LOADABLE`(0x20)区域的映射**在 cell 启动时被撤销**;重装走 **Cell Set Loadable**(错误码 `-EPERM`/`-ENOENT`/`-EINVAL`,root cell 不可设为 loadable) | jailhouse `cell-config.h` + `control.c`(`cell_start`/`cell_set_loadable`) |
| 8 | Jailhouse ivshmem | **设备不维护 pending 语义**:MSI-X 的 Pending Bit Array **恒返回 0**,INTx 的 Interrupt Status 位**从不置位**;事件状态应**从共享内存协议推导**;one-shot 模式下中断投递会清 Interrupt Control 的 bit 0;Doorbell 只写、读未定义 | `ivshmem-v2-specification.md` |
| 9 | ACRN ivshmem | **dm-land 与 hv-land 可同时存在但永不互通**;前缀 `dm:/`(早期 `sos:/`)与 `hv:/`;**通知只在 hv-land 支持**(dm-land 无 doorbell);dm-land 下 guest 重编程 BAR2 会使共享内存不可用 | ACRN ivshmem HLD 与 enable_ivshmem 指南 |
| 10 | Bao 共享 identity | identity 是配置里的 **`shmem_id`**(IPC 的 `base` 只是本 VM 映射地址,**不应据地址相等/不等推断**);IPC `size ≤ 对应 shmem 大小`;**cache coloring 默认未启用**、随平台可用颜色数截断、代价是**丧失大页**并抬高 TLB 压力 | Bao README/config 结构与 cache coloring 评估材料 |
| 11 | NuttX 双堆 | 两个具体配置项(`CONFIG_MM_MULTIHEAP` + `CONFIG_MM_KERNEL_HEAP`),**`MM_KERNEL_HEAP` 在 flat 构建下默认关闭**;PROTECTED 的用户 API 由 `syscall/syscall.csv` 经 `tools/mksyscalls` 自动生成;驱动 upper half 在 `drivers/`,lower half 在 `arch/` 或 `boards/` | NuttX `mm/Kconfig`、Protected Build 指南、Device Drivers 文档 |
| 12 | FreeRTOS 细节 | `pxHigherPriorityTaskWoken` **自 V7.3.0 起可选(可传 NULL)**,但取舍不同;`portYIELD_FROM_ISR` 通常是 **pend(Cortex-M 走 PendSV),真正切换在中断退出后**;MPU 区域**大小与对齐必须是同一个 2 的幂**;降权到用户模式**不可回退** | FreeRTOS 官方 API 参考(队列/MPU)与端口文档 |
| 13 | ThreadX Modules | preamble **必在模块第一个地址**;properties 位区分特权/用户模式与 MPU/共享内存,并编码编译器 ID;**ARM 上非特权模块经 SVC 陷入**;支持 **XIP**(指令在 Flash、数据在 RAM);**模块线程栈顶有线程入口信息结构需计入栈用量** | eclipse-threadx/rtos-docs 的 threadx-modules 第 1/2 章 |
| 14 | eCos 三层 | ISR 返回 `CYG_ISR_CALL_DSR` 时调度 DSR;**DSR 会被调度器锁推迟**;**ISR 不允许使用 DSR 级锁**;**DSR 可 signal 条件变量但不能 wait** | eCos 参考手册:同步与驱动接口章节 |
| 15 | ARINC 653 / PikeOS | COLD_START 与 WARM_START 的差别是**是否需要从非易失存储器拷代码到 RAM**;初始化模式(COLD/WARM)下**只有主进程可调度**;**refresh(周期)只对采样模式的接收有意义**;PikeOS 的 **APEX 服务经链接在固定地址的 API table 进入**,POSIX 内核把用户线程映射到**每核一个** system thread,分区支持 256 优先级 | ARINC 653 分区模式状态机材料、SYSGO POSIX/ARINC 653 产品文档 |
| 16 | INTEGRITY | 内核空间**不做动态内存分配**,且**内核内存不用于消息/信号量等由进程请求创建的对象**;启动表定义资源归属、连接静态分配且不可绕过;多核共享资源争用可使 **WCET 增加 8–13 倍** | Green Hills INTEGRITY / INTEGRITY-178 tuMP 产品与安全材料 |
| 17 | AUTOSAR `E_OS_ACCESS` | 确切条件:**对象未在配置时授予访问权**,或**对象属于另一个不处于可访问状态的 OS-Application**;**trusted 与非 trusted 一视同仁**(默认拒绝);例外是检查类服务(`CheckObjectAccess` 等) | AUTOSAR OS SWS(SWS_Os_00056 / OS448 / OS509)与 RTE SWS |
| 18 | MINIX 3 | 消息载荷**定长 56 字节**,超出部分走 grants;**`EPERM` = grant 无效**(含"页表走查失败也报 EPERM,以免 grantee 探测 granter 地址空间"),**`EFAULT` = 未映射**;live update 的授权方向是**内核(仅)授予新进程对旧进程地址空间的只读访问**,且**可回滚**、**旧/新实例可能同时存在**;活跃 direct grants 会使更新复杂化 | `minix/include/minix/ipc.h` 与 `safecopies.h`、MINIX 3 消息传递 wiki、live update 指南与相关论文 |
| 19 | Genode | **quota 捐赠沿 session 路径被逐级扣减**("系统还剩内存"与"该 child OOM"不矛盾);**ROM session 在生命周期内可更新**(配置可动态改变);服务名只在局部 parent 层级成立、label 可被重写 | Genode 架构文档(Interfaces and Mechanisms)、Foundations 手册 |
| 20 | Plan 9 | **union 只有单层叠加**(查找返回第一个匹配,上层不存在的名字不会落到下层深树);`bind` 的 `new` **在 bind 时求值**;`/srv` 是服务注册表;9P 的 **fid 是 session 内 client 侧句柄**(walk 绑给 newfid,库层拒绝重用已存在 fid) | `bind(1)`、`9p(2)`/`9p(3)`、`srv(3)` 手册页与 lib9p 文档 |
### 本轮校验
- `node validate.mjs`:`OK: 122 skills validated`;`npm test`:41 项全过
- 分支挂载完整性检查:`re-rtos` 9 / `re-hypervisor` 5 / `re-automotive` 1 个 references 文件均有 SKILL.md 入链(`re-kernel` 的 `windows-gotchas` / `windows-decision-tree` 由同目录 `windows-kernel.md` 互链,非孤儿)
- 未做:行为 fixture(KARL 重链接、Xen 迁移端口、MINIX live update 等需真实环境)
---
## 补充 17:跨系统误判总表 + 第三批特殊系统(2026-09-13)
来源为同源的外部整编"合并后完整版本":前半部分是**跨系统的总原则**(十类高频误判、共同规律、异常处理树),后半部分是**更多冷门系统**。两类内容分别处理。
### 一、跨系统总原则 → 新的入口级控制文件
新建 **`re-analyze/references/cross-system-models.md`**(跨系统运行模型与误判总表),内容:
- **十类高频误判表**(现象 → 不要直接推断 → 必须先排除)
- **共同规律 A–E**:本地句柄≠全局标识、ready≠有资格运行、无内核入口≠无 I/O、无 CFG 边/syscall≠没发生、磁盘≠运行
- **跨系统异常处理树**(函数无 caller / 地址不一致 / 驱动无内核入口 / 线程不执行 / IPC 无 syscall / 内存访问故障 / binary 存在但不运行 / runtime≠disk)
- **使用方式**:核对手段统一为 cross-view + configuration + runtime verification
挂载:`re-analyze/SKILL.md` 第三步加入「**跨系统误判表(判定前强制前置)**」——**任何要写 hook / dead code / loader bug / 恶意 的时刻,先逐项排除该运行模型允许的正常机制,未排除完不写结论**。
### 二、新增系统(22 类)的落地位置
| 类别 | 系统 | 落点 |
|---|---|---|
| 通用 OS 内核 | HelenOS、Redox、Haiku、z/OS、IBM i、OpenVMS、Unikraft·MirageOS | `re-kernel/references/{helenos,redox,haiku,zos,ibmi,openvms,unikraft-mirageos}.md` |
| RTOS | µC/OS、SYS/BIOS、SAFERTOS、CMSIS-RTX5、T-Kernel、TOPPERS、OSE·OSEck、Nucleus、Deos | `re-rtos/references/{ucos-sysbios,safertos-rtx5,tkernel-toppers,ose-oseck}.md`;Deos 并入 `partitioned-rtos.md`;Nucleus 入 SKILL.md 运行模型表(内容量不足以成篇) |
| Hypervisor | Hyper-V·VMBus、XtratuM、LynxSecure、Quest-V | `re-hypervisor/references/{hyperv-vmbus,xtratum,lynxsecure-questv}.md` |
| 汽车 | AUTOSAR Adaptive | `re-automotive/references/autosar-adaptive.md` |
`rerouting.md` A 表新增 13 行。
### 三、核验后的关键事实(写入依据)
| 主题 | 核验后的表述 |
|---|---|
| HelenOS fibril | fibril 由**用户态库协作调度**,**内核完全不知道其存在**;devman 在用户态按 match id 评分匹配并启动驱动,`driver_ops` 由**通用连接处理器**在来连接时调用 |
| Redox 句柄 | 内核把文件操作转成 **SQE/CQE** 消息;**scheme 侧 handle 描述符与客户端 fd 不是同一个**(内核在 `(进程, fd)` 与 `(进程, handle)` 间映射);provider 初始化后常进入 **null namespace**(安全设计) |
| Haiku 两层模块 | **driver module(`driver_v1`,绑定节点、认领 I/O 资源)与 device module(`device_v1`,暴露 `/dev` 接口)**;`B_FIND_CHILD_ON_DEMAND` 决定按需搜索;`suspend`/`resume` **从不被调用** |
| Hyper-V GPADL | GPADL 是**描述并映射客户机缓冲区的句柄**;宿主对经 GPADL 共享的内存总量有上限(WS2019+ 约 1280 MB,更早约 384 MB) |
| Hyper-V SR-IOV | **VF 数据面不经过 VMBus 与 hypervisor**,而 **VF 控制面仍走 VMBus** 回到 PF 驱动;拆除时 NetVSC 从 VF 解绑并迁回软件合成路径 |
| SAFERTOS ESM | ACP(限制可调 API)与 OACP(限制可访问对象)**各自独立**;**间接对象 ID + 交叉引用表**取代指针式句柄;per-task 区域**大小须为 32 字节倍数、基址 32 字节对齐**,**每次上下文切换重新编程** |
| CMSIS-RTX5 | Safety Class 的**动机**:RTOS 对象经"以数字 ID 为参数、在 handler 模式执行"的系统调用访问,**单靠 MPU 可被"用别的对象 ID 调 API"绕过**;**中断处理程序绕过 MPU 保护**;**ISR FIFO 溢出时系统状态已不一致**,对策是增大对象尺寸 |
| µC/OS | `OSIntEnter`/`OSIntExit` **必须成对**且前者不得由任务级代码调用;**只有最后一个嵌套 ISR 退出时**才判断切换;Cortex-M 上切换仅触发 **PendSV**;直接递增计数只在"递增时中断已关闭"的架构安全 |
| SYS/BIOS | **`Swi_disable()` 会连带禁用 Task 调度器**;Swi 调度器禁用期间**绝不能调用阻塞 API**(会不可恢复地损坏 Task 调度器状态);**Hwi 与 Swi 共用系统中断栈**(默认 4096 字节) |
| T-Kernel | 三种上下文(任务/准任务/任务独立)**合法性由规范规定**;设备驱动的六个处理函数**以准任务部分运行、必须可重入、且不保证互斥**;`tk_wai_dev` **只等待调用时刻正在处理的请求**,超时后处理仍在继续 |
| TOPPERS | 四家族(ASP3/HRP3/FMP3/**HRMP3**)规范分开规定;HRMP3 就绪队列**按保护域 + 按处理器**;内核内**不做动态内存管理** |
| AUTOSAR Adaptive | **Modelled Process ≠ OS 进程**,不可 1:1 比较;状态是"键"、清单是"表"、进程集合是"查表结果";EM 启动后**不再自行发起**状态切换 |
| Deos | 同一系统内**三类调度模型并存**(ARINC 653 APEX / RMS / POSIX),多核用 **BMP + 缓存分区** |
| XtratuM | **Plan 0 保留给初始化、Plan 1 保留作维护**;计划切换在**当前计划剩余槽执行完之后**;**IPVI 每分区最多 8 个**;固定优先级**数值 0 最高** |
| LynxSecure | 官方表述为**静态配置 + 固定资源分配 + 无中央管理内核 + 无共享内存 + 无集中调度**;("初始化划分的 setup code 被移除"一说**未获公开资料证实,未写入**) |
| Quest-V | **每个 sandbox 一个 monitor**(而非一个中央 hypervisor);monitor 只在引导、故障恢复、建通道、初始化影子页表时介入;**设备中断直接投递给 sandbox kernel**;**无全局时钟**,跨 sandbox 时间戳不可直接比较 |
| Unikraft | **native(API 兼容,syscall 变廉价函数调用)与 binary-compatible(捕获 Linux ELF 的 syscall)两条路线**;**非 PIE 决定地址布局且限单应用** |
| MirageOS | 同一份源码换目标,**差别只在一个被替换的平台主模块 + 目标包集合** |
| OpenVMS | 完成顺序为 **写 IOSB → 置事件标志 → 触发 AST**;**AST 不中止进行中的系统调用**;进程等待时 AST 投递后**原等待会被重新执行** |
| z/OS | **SRB 不能调用 SVC(除 ABEND)或 WAIT**;**home 地址空间在整个执行期不变,`PSAAOLD` 总指向 home**;跨地址空间使用 TCB 指针是经典 **S0C4-11** 成因 |
| IBM i | 内存与辅存**构成单一 64 位地址空间**;对象**按名字而非硬件地址**访问 |
| OSE / OSEck | LINX **统一核内/处理器间/板间通信**,支持共享内存/DMA/RapidIO/以太网/PCI,**零拷贝共享内存**;(其 **XIP 能力本次未获证实,已在文件中标注"不要断言"**) |
| Nucleus | **MMU(Cortex-A)/MPU(Cortex-M)子系统隔离 + 线性内存映射 + 动态 reload/restart/update 而不停机** |
### 四、本轮校验
- `node validate.mjs`:`OK: 122 skills validated`;`npm test`:41 项全过
- 分支入链检查:`re-kernel` 22 / `re-rtos` 13 / `re-hypervisor` 8 / `re-automotive` 2 个分支文件均有 SKILL.md 入链(`windows-gotchas`/`windows-decision-tree` 由同目录互链)
- **两处未证实内容已明确标注而非照写**:OSE 的 XIP、LynxSecure 的"setup code 被移除"
- 未做:行为 fixture(fibril 调度、SR-IOV 切换、AST 投递等需真实环境)
---
## 补充 18:14 个分支的深度展开 + Nucleus 新增 + 入口速查表(2026-09-13)
来源为同源外部整编的第三份材料:对 14 个系统的**机制级展开**(心智模型 → 特殊情况 → 下一步查什么)与一张汇总速查表。处理方式:**逐条核验后并入对应分支**,不新增技能(Nucleus 内容量已足以成篇,新增 1 个分支文件)。
### 一、落地位置
| 动作 | 对象 |
|---|---|
| **新增分支** | `re-rtos/references/nucleus.md`(线性映射 + entitlement / 固定块内存池 / 动态模块生命周期) |
| **深度展开** | `autosar-adaptive`(清单三件套 / 服务发现 / PHM / UCM / Persistency)、`xen`(通知抑制 / 睡前再检查 / FIFO 事件 ABI / 迁移身份)、`hyperv-vmbus`(GPADL 删除阻塞 / packet 生命周期 / 外部数据待决)、`partitioned-rtos`(Deos 两级调度 / slack / SafeMC / 排错顺序)、`ucos-sysbios`(调度器锁嵌套 / 信号量与互斥量 / 定时器任务上下文 / PendAbort)、`safertos-rtx5`(权限模型 / ESM 拒绝语义)、`xtratum`(两种切换时机 / 采样刷新 / 掩蔽扩展中断)、`acrn`(MSI-X trap 路径三态 / 设备归属迁移)、`lynxsecure-questv`(LynxSecure 官方表述)、`unikraft-mirageos`(启动表 / shim 三层符号 / Lwt / 目标指纹) |
| **入口级扩充** | `re-analyze/references/cross-system-models.md` 新增**异常速查表(约 40 行,按现象直查)** 与**版本/代际提示**节 |
`rerouting.md` A 表新增 7 行。
### 二、本轮核验后的关键事实
| 主题 | 核验后的表述 |
|---|---|
| **AUTOSAR PHM** | 以**进程粒度**监督(不是任务级);三类监督 Alive(周期内检查点数量)/ Deadline(起止检查点耗时区间)/ Logical(检查点顺序符合监督图,与时间无关);本地状态含 **EXPIRED(终态)**;**监督模式 = `<machine state, function group state>`**;恢复动作含"请求看门狗驱动复位";**PHM 自身不启停进程**;**PHM 还监督 EM 守护进程存活,其失败升级为看门狗/机器复位** |
| **AUTOSAR Persistency** | `keepExisting` / `overwrite` / `delete` 三策略 + 清单约束(前两者要求存在初始值,`delete` 要求不存在);**版本比较:清单版本更低时回滚**(存在有效备份时) |
| **AUTOSAR 服务发现** | `FindService` 允许返回空;可用性变化时重新回调且**实现负责串行化同一 handler**;handle 可指向**远端** service instance |
| **Xen 通知抑制** | 推送宏**只有越过对端设置的 `req_event` 阈值时才通知**;消费侧"无工作 → 设阈值 → 全屏障 → 再查"是**防丢唤醒**的协议核心(并附已知的索引回绕副作用与 NAPI 场景副作用) |
| **Xen FIFO 事件 ABI** | 优先级 **0 最高 / 15 最低(默认 7)**,每 VCPU 16 个队列;事件字含 **PENDING / MASKED / LINKED / BUSY**;**unmask 在 PENDING 时必须投递通知**;**存在 2-level 与 FIFO 两套 ABI,记账布局不同**;**初始化控制块不会重投当前 pending 事件(会丢),应在绑定事件之前完成** |
| **Hyper-V GPADL** | **删除在 GPADL 仍被 server 映射时会阻塞直到解除**;从 buffer 创建时该 buffer 被 probe 并锁定直到 GPADL 销毁 |
| **Hyper-V packet 生命周期** | 完成调用**可立即也可稍后**发起,直到它被调用才清理映射/释放缓冲/(按需)发送完成 packet——**回调返回不是释放边界** |
| **Hyper-V 外部数据** | 需要分页时返回 **STATUS_PENDING**,**必须从回调返回**,之后**可能在不同 IRQL 再次回调**;返回的 MDL **已锁定、不带任何虚拟地址、在完成调用时失效**且由内核库释放 |
| **Nucleus** | **线性内存映射 + 受保护区域 + entitlement**(Cortex-A 用 MMU、Cortex-M 用 MPU);**`NU_PARTITION_POOL` 是固定大小块分配器**(与"空间隔离域"同名的术语坑);**分配是 O(1)、不可能碎片化,唯一失败模式是池耗尽**;`NU_SUSPEND` 下池空则任务挂起;非任务线程只能用 `NU_NO_SUSPEND` |
| **µC/OS 定时器** | 回调**在内部定时器任务上下文中执行**(不是中断、不是创建者任务)、**使用定时器任务的栈**、且**绝不能阻塞/等待**(回调串行执行,阻塞会卡住整个定时器子系统) |
| **µC/OS PendAbort** | 中止等待是**让任务就绪**而非正常投递;**只能由任务调用**;被唤醒任务带"等待被中止"的错误码返回 |
| **Deos SafeMC** | **两级调度**:Level 1 是**跨核对齐的执行窗口**,Level 2 为每个核/window 指派 scheduler(ARINC 653 / Deos RMA / POSIX);**Slack 通过滑动时间窗实现**(窗口可压缩/扩张/滑动);**cache partitioning 为软件实现、做到应用/分区级、免去分区切换的 cache flush**,与内存池互补 |
| **XtratuM** | 普通 plan 切换**要等当前计划槽跑完**,而**健康监控切维护计划可立即发生**(终止当前槽);同 MAF 内多次请求可**最后一次生效**;采样端口刷新周期决定新鲜度、旧数据可标无效;**扩展中断在分区启动时默认掩蔽** |
| **ACRN MSI-X** | **三类 VM 的 trap 路径不同**(Service VM → hypervisor handler;post-launched → Device Model handler 再涉及 hypervisor;pre-launched → hypervisor handler);设备所有权在 Service VM 与 post-launched VM 之间**双向迁移** |
| **Unikraft 启动表** | 三类表(早期 / 构造 / 初始化)+ **七级顺序(构造→早期→平台→库→rootfs→系统→晚期)**、**每级 10 个优先级**、条目在按名字排序的专用链接段中 |
| **MirageOS Lwt** | 协作式轻量线程 + 事件循环;**不让出会饿死整个事件循环**(不需要互斥量或内核死锁);后台异常交给 async 异常处理器,行为取决于其配置 |
### 三、未证实 / 未直接命中的内容(已按此处理)
| 内容 | 处理 |
|---|---|
| LynxSecure"用于初始配置的特权 setup code 随后被丢弃" | **未证实**——改为写入官方明确表述的部分(不可变 boot 分区、内核功能仅限分区/数据流/状态调解、I/O 全导出到 guest、无管理控制台登录、无动态系统修改),并标注该机制未被证实 |
| TI SYS/BIOS 的"中断禁用期间多次发生、恢复后只服务一次" | **未命中上游**——未写入 |
| Deos 的外部时钟同步 | **未直接命中上游**——以"候选解释之一,需在具体型号文档确认"的措辞写入 |
| Hyper-V `GPADL_READ_ONLY` 非安全措施 | **未命中**——未写入(只写了已证实的删除阻塞与 buffer 锁定语义) |
### 四、版本/代际提示(已写入入口文件)
- 某平台规范公开版本已推进(如 R25-11)而多数细节来自上一完整公开版(R24-11)——**核心模型适用,条目前先做版本指纹**
- 某 hypervisor 最完整公开手册属于特定代际(如 XM-4)——**不要无条件套到其他代际**
- 同一系统的**安全认证产品线与基础产品线不是同一份二进制/内核**,可选机制不同
### 五、本轮校验
- `node validate.mjs`:`OK: 122 skills validated`;`npm test`:41 项全过
- `re-rtos` 分支数 13 → 14,`re-analyze/references/cross-system-models.md` 新增速查表与版本提示节
---
## 补充 19:HIC 入库与"信任边界"通用规则(2026-09-13)
### 一、落地
- **新增分支**:`re-kernel/references/hic.md` —— capability + 物理沙箱 + 多版本驱动系统(`re-kernel` 分支数 22 → 23)
- **入口级规则**:`re-analyze/references/cross-system-models.md` 新增「**共同规律 E:信任边界不能从指令形态推导**」(四条推论表:直接 call / 直接 MMIO / 同特权级 / 整数句柄各自可能是什么),并写明配套要求(内存取证区分 VA/PA/frame/capability/owner domain/mapped domain;共享内存指针带域语义)
- **挂载**:`re-kernel` SKILL.md(平台差异表行 + 4 条决策表行 + 分支指针 + description 触发词)、`rerouting.md` A 表 1 行
### 二、触发条件设计(用户明确要求"不能误触")
`hic.md` 内专设「触发条件(命中 / 不要命中)」一节:
- **命中**要求**组合证据**:同特权级 + MMU 隔离的模型、模块自描述元数据、入口页 IPC 形态、两种 capability 记账模型并存、旧新实例并行的滚动更新
- **不命中**逐条列出该走哪里的对照表:仅"驱动在用户态"→ 用户态驱动各分支;仅"capability/handle 本地标识"→ seL4/Zircon/Genode 等;仅"共享内存+通知"→ Xen/VMBus;仅"有滚动更新"→ MINIX/NetBSD;**仅"看到直接 MMIO"→ 不足以说明任何事**
- 判据写明:**本分支的标志是那一组组合,而不是其中任何单独一条**
### 三、命名决策(记录在案)
初版按本库红线 2(禁止具体到某个项目/产品,暗示也不行)做了**机制类脱敏**——起因是检索发现公开 OSDev 线程的作者 handle 与本仓库 git 身份一致,点名会同时构成"项目名 + 作者身份"的双重指向。**用户明确要求点名**(该项目为公开项目),遂按用户决定改为具体系统条目。
**先例**:此类"是否点名"的判断**以用户对自身项目公开性的判断为准**;默认仍按红线 2 脱敏,用户明确要求时点名。
### 四、核验
- HIC 的公开信息(OSDev 线程:物理沙箱、1:1 连续物理映射、同特权级直接调用快路径、capability 管控与未授权记录、Privileged-1 官方模块审计/签名模型、大页与页表层数、KPTI-like 跨边界隔离)与用户提供的设计描述一致,**分支内容以用户提供的设计文档为准**(本库对第一方设计文档无需外部转述)
- 跨系统对照表的 11 条来源(Fuchsia DFv2 / crash recovery / bind metadata、seL4-CAmkES、Xen 前后端与 grant table、Genode、QNX、Barrelfish、MINIX live update 与协议静止)中,**除 Barrelfish 外均已在本库其他分支有独立记录**;Barrelfish 仅作为对照经验写入,未单独立分支
- 链接修复:初版 `[[xen]]` / `[[hyperv-vmbus]]` 跨技能裸引用被校验拦下(应为 `[[re-hypervisor/xen]]` 形式),已修正
### 五、本轮校验
- `node validate.mjs`:`OK: 122 skills validated`;`npm test`:41 项全过
- `re-kernel` 分支 23,全部有 SKILL.md 入链
---
## 补充 20:8 个分支的"操作层"补深 + LynxSecure/Quest-V 拆分(2026-09-13)
来源为同源外部整编的**深度审计**:指出部分分支"概念正确且稀有,但宽度只有一根很深的井",并逐一列出该补的操作层内容。本轮按其给出的优先级处理。
### 一、评估维度(记入审查方法)
该审计提出一个**二维评估**,值得作为后续审查的固定视角:
```
深度(某一机制的资料质量) × 平台覆盖度(拿一个真实样本进来能走多远)
```
据此的定位:**OpenVMS / z/OS = A+ 深度、C 覆盖度**(深的是某个异常机制,不是整个平台);**eCos = 深度集中在一个切面**;**Haiku / Redox = 某一层很深、换一层突然变浅**;**Nucleus 已超出预期**(不再列最高优先级)。
### 二、落地
| 动作 | 对象 |
|---|---|
| **拆分** | `lynxsecure-questv.md` → `lynxsecure.md` + `questv.md`(两者各拆一份) |
| **操作层补深** | `ibmi`、`zos`、`openvms`、`redox`、`haiku`、`ecos`、`ose-oseck` |
| **挂载同步** | `re-kernel` / `re-rtos` / `re-hypervisor` SKILL.md 的分支指针与决策表、`rerouting.md` 新增 6 行、`partitioned-rtos.md` 的同族链接改指两个新分支 |
### 三、补进去的操作层要点
| 分支 | 新增的操作层内容 |
|---|---|
| **IBM i** | **层次边界**(MI / TIMI / SLIC / PASE,PASE 绕过 TIMI);**程序模型**(OPM/EPM/ILE;`*MOD` 不可执行且绑定后常被丢弃、`*PGM` 是 bind-by-copy、`*SRVPGM` 是 bind-by-reference 且激活时解析签名);**activation group**(PSSA/PASA/堆 + 覆盖作用域 + 存储模型相容约束);**两套指针**(系统指针 16 字节 tagged 指向对象 / 空间指针指向偏移)与**两种存储模型**(single-level vs teraspace 的 job 边界、mmap 支持、跨 job 共享方式);**space addressing violation 的异常数据**(对象系统指针 + 空间偏移 + 空间类别)与 **tagged 指针的 fork/共享内存限制**;**产物识别**(DMPOBJ / DBGVIEW 编译清单 / 压缩态 / 时间戳必然差异) |
| **z/OS** | **可执行材料**(load module / program object / PDS vs PDSE);**AMODE/RMODE**(程序对象与运行中程序各有属性);**XPLINK 与非 XPLINK 的栈行为相反**(栈方向、GPR4 带 0x800 偏置、BACKCHAIN vs 展开信息、参数传递方式、转换仅限 31 位);SVC/PC 表;dump 类型与 IPCS(**XPLINK 下控制块更少 → 依赖 LEDATA 视图**);EBCDIC 与记录模型 |
| **OpenVMS** | **第二条控制流:条件处理**(处理器的继续/重投递/展开三种去向、**第二次异常跳过已搜索帧**、经异常向量建立的处理器每次都被调用);**建立处理器的两种方式与语言差异**(栈帧字段 vs 过程描述符/展开信息块;**I64 运行时没有该入口**;C 必须用运行时专有接口,否则与 setjmp/longjmp 同用是未定义行为);**镜像启动时建立的三个默认处理器**(traceback / catchall / last-chance);**镜像激活与共享镜像**(逻辑名重定向机制、默认目录、**特权/仅执行镜像只认可信逻辑名且被引用镜像必须安装**);节(全局/私有/消息)与调用标准;RMS 文件规格解析规则(已知镜像查找忽略版本号) |
| **Redox** | **启动链**(引导器 → 极小 ELF 加载器 bootstrap → initfs 两级启动;内核参数携带硬件描述来源:ACPI vs 设备树);**syscall ABI 刻意不稳定**,稳定层在用户态运行时;**relibc 与辅助向量**(静态/动态可从 auxv 判断、线程用 fd 承载、可重启语义与 errno 映射);scheme 的**两种匹配方式**(路径前缀 vs 记住打开时的 scheme)与调度分类;**驱动两遍构建**(initfs 体积优化 + panic-abort vs 主系统标准 release) |
| **Haiku** | **系统侧对象模型**(team/thread/area/port/semaphore + 信号量的扩展标志:可中断、释放全部、仅在等待时递减);**KDL**(栈回溯/线程/内存/切换 CPU/系统日志)与**调试 API 细节**(消息头含线程与 team ID、team 调试标志含 image 事件与 syscall 前追踪、**64 位下参数缓冲区被扩大**);**BeOS 兼容是单向的**且调试接口与文件系统 API 属于不兼容部分;用户态服务边界 |
| **eCos** | **CDL 配置系统**(通道/调试/构建目标等选项决定编入项;用 ROM 监视器时通道选项通常失效);**HAL 与向量表**(位置由内存布局决定、默认异常向量、**ROM 监视器加载的应用异常默认进监视器**);**虚拟向量**(静态地址表、服务清单、保留字节与间接层代价);**启动顺序**(复位入口 → 平台设置 → HAL 启动 → 构造函数 → 主启动);**构造函数被向量表覆盖的真实坑**;调试桩与 GDB 去向 |
| **OSE / OSEck** | **信号号不唯一**(多个端口可共享同一信号号 → 需次级 id 与解析函数);**先注册后发送否则丢**、一次事件可能关联多个信号要取空;**域/块/段/池的所有权**(只能在**自己的池**里分配、跨域发送会被拷贝);**进程类型与静态/动态类别**;监督(链路级 + 平台级、DSP 监督信号、看门狗)与错误处理器;**错误检测的能力边界**(结尾标记能检出越界写,检不出不改标记的指针访问/泄漏/未初始化读取);**系统信息接口**(信号空间、保存的寄存器与栈);OSE 与 OSEck 的差异与异构边界 |
| **LynxSecure** | **明确区分【官方表述】与【该恢复什么】**:官方表述(不可变 boot 分区、内核功能仅限资源分区/数据流控制/状态变更调解、I/O 全导出到 guest、无管理登录、无动态系统修改、hypervisor 自身也不能访问 guest 资源)用于判断"缺什么算正常";操作层按方法论给(配置优先于代码、启动阶段是唯一能看到配置生效的窗口、**用三项职责反查内核边界**、跨分区找受控通道而非共享页、用官方约束验证 DMA 隔离、**"8 MB 里哪一段是核心"的定位法**) |
| **Quest-V** | **monitor 的四个介入时机**、EPT 用于内存隔离而非 CPU 虚拟化、中断直接投递与早期解复用、**显式消息 + 共享内存通道(缓存行大小)+ IPI**、**故障路径**(EPT violation → VM-exit;必要时强制触发陷入;抢占超时把检测逻辑放进 monitor)、**本地/远程在线恢复**(换实现靠改 EPT 激活)、以及**"哪一段是 monitor"的四条判据** |
### 四、未获证实 / 未写入
- **LynxSecure 的配置 artifact、启动阶段细节、partition 描述结构**:公开资料缺失(检索无结果)。**未编造**;改用"该恢复什么"的方法论表述,并在文件开头明确标注【官方表述】/【该恢复什么】两类内容的分野
- **OSE 的 XIP**:仍未证实,文件中保留"不要断言"的措辞
- **OSE 的 attach 语义细节、signal pool 监督的内部设计**:本次检索只确认了 hunt/attach 属于信号 API 与池的所有权规则,更细的内部机制未获证实,未写入
### 五、本轮校验
- `node validate.mjs`:`OK: 122 skills validated`;`npm test`:41 项全过
- `re-hypervisor` 分支 8 → 9(拆分后),`re-rtos` 14、`re-kernel` 23;全部有 SKILL.md 入链
- 措辞检查:新写内容经"最 X"筛查并改写(`questv` / `ose-oseck` 各一处)
---
## 补充 21:系统识别指纹表(2026-09-13)
### 一、缺口与落地
**缺口**:库里有"运行模型 + 误判表 + 异常速查表",但**没有"怎么认出这是哪个系统"**这一层——rerouting A 表要求你已经知道目标是什么。
**落地**:新增入口级控制文件 **`re-analyze/references/system-fingerprints.md`**(199 行),**覆盖本库全部 55 个系统**(脚本自检:按显示名逐个核,55/55 命中)。
### 二、结构:五层流程
```
① 载体与格式(PE / ELF 是否 ET_REL / Mach-O / 无容器镜像 / 配置 / 转储 / 流量)
② 超家族收敛(几条问题归到某一族)
③ 家族内指认(9 张表:UNIX 与 Windows 系内核驱动 / capability 与用户态驱动型 /
RTOS / 分区与安全 RTOS / Hypervisor / 固件引导 / 主机大型机 / 车载 / unikernel)
④ 易混淆对(15 组专项判据)
⑤ 负判据("看到 X 就不是 Y")
```
**判据强度分级**:**[强]**(唯一判据,可单独定案)与 **[弱]**(需组合)——文件里明确写了"弱判据单独使用会把无关系统卷进来",并给出例子("有 Kconfig"无法区分 Zephyr 与 NuttX)。
### 三、本轮新核验的事实地基
| 事实 | 核验结果 |
|---|---|
| **ELF note 段标识** | NetBSD:`.note.netbsd.ident`,note 名 `"NetBSD"`,`NT_NETBSD_IDENT` = 1;OpenBSD:`.note.openbsd.ident`,note 名 `"OpenBSD"`,`NT_OPENBSD_IDENT` = 1;FreeBSD:`.note.ABI-tag`,note 名 `"FreeBSD"`,`NT_FREEBSD_ABI_TAG` = 1(GNU ABI 标签里另有 FREEBSD=3、NETBSD=4、SOLARIS=2、LINUX=0、HURD=1) |
| **`EI_OSABI` 现行取值** | NONE=0、HPUX=1、**NETBSD=2**、LINUX=3、HURD=4、86OPEN=5、**SOLARIS=6**、AIX=7、IRIX=8、**FREEBSD=9**、TRU64=10、MODESTO=11、**OPENBSD=12**、**OPENVMS=13**、NSK=14、ARM=97、STANDALONE=255。(**注意**:2000 年曾有 FREEBSD=4/NETBSD=5/OPENBSD=6 的提案,与现行值不同;本表按现行值写) |
| **OpenBSD note 的强制程度** | 讨论中一度写作"通常包含"后改为移除该措辞;无 note 的二进制会执行失败,但最终未写成"必须"——本表据此只把它当**强判据之一**而非唯一依据 |
### 四、处理原则(重要)
- **判据全部取自本库已核验的分支**(各分支文末"工具与验证"节),本文件**不引入新断言**;文中已写明这一来源约定
- **两处检索未命中**(hypervisor 配置产物特征、RTOS 识别串)**未改用外部猜测**,而是改用库内已核验内容(如 ACRN 的 `IVSHMEM_ENABLED`、Jailhouse 的 `.cell` 与控制台串、Bao 的 `struct config`、RTOS 的对象头魔数与 API 前缀)
- **判据薄的两个系统**(LynxSecure / Quest-V)在表中明确标注"不要靠字符串定案",改为结构性与行为判据
- 新增了**维护约定**:新增系统分支时须同步往本表加一行(载体/强判据/结构线索三列必填)
### 五、挂载
| 位置 | 内容 |
|---|---|
| `re-analyze/SKILL.md` 第二步 | "先认目标"段(含"判不出不要硬判") |
| `triage.md` 前置 | 认系统先于查表;家族已定系统未定时按家族级分支推进 |
| `cross-system-models.md` | 互为前后置:先定身份、再查该身份允许哪些"正常异常" |
| `CLAUDE.md` 控制文件表 | 新增两行(fingerprints / cross-system-models) |
| 5 个技能 | re-kernel / re-rtos / re-hypervisor / re-uefi / re-automotive 的「何时使用」各加一条前置回链 |
### 六、本轮校验
- `node validate.mjs`:`OK: 122 skills validated`;`npm test`:41 项全过
- 覆盖度自检:按 55 个系统显示名逐个核对,**55/55 命中**(脚本核对方式记于本节,后续加系统时可复用)
---
## 补充 22:对 d4a5348 的抽样审查——2 处事实 + 4 处元规则(2026-09-13)
来源为同源外部审查(针对当前 HEAD 抽样)。审查自身给出的定位值得记下:**"不是内容事实性质量崩了,更像是扩张得很快以后,少量表述过强 + 元规则开始比具体知识更容易制造误判。"** 本轮 6 条全部处理。
### 一、事实性修正(2 条)
| # | 位置 | 原文 | 问题 | 修正 | 核验 |
|---|---|---|---|---|---|
| 1 | `analysis-contract.md` constants 步 | "有语义的 magic number(如 **ELF 头 0x202**)" | ELF 魔数是 `\x7fELF`,`0x202` 与 ELF 无关 | 改为 `ELF 魔数 \x7fELF(小端读作 0x7f454c46)` | 定义级事实 |
| 2 | `system-fingerprints.md` §二 | "`.note.ABI-tag`(FreeBSD)" | **把 note type 与 section name 混了** | 改为 `.note.tag`(note 名 `"FreeBSD"`、`NT_FREEBSD_ABI_TAG`=1),并注明**早年版本曾用 `.note.ABI-tag`**,识别时应两者都看 | FreeBSD `lib/csu/common/crtbrand.S`:`.section .note.tag,"aG",%note,.freebsd.noteG,comdat`;note 名 `NOTE_FREEBSD_VENDOR`;描述符为 `__FreeBSD_version`。**上一次搜索之所以出错**:官方头文件的注释写的是 "Values for FreeBSD **.note.ABI-tag** notes",而实际生成的 section 是 `.note.tag`——**注释与实现不一致** |
### 二、元规则修正(4 条)
| # | 位置 | 问题 | 修正 |
|---|---|---|---|
| 3 | `system-fingerprints.md` 判据标注 | **[强] 混了两个独立概念**——"对某系统高度特异"与"这个东西通常一定能观察到" | 拆成**二维**:**特异度**(`独有`/`高`/`弱`)× **可观测性**(`稳定`/`视构建`/`仅运行期`),标注形如 `独有·稳定`;并写明典型误用:把 `独有·视构建` 当"一定能看到",于是对 strip 过的产物得出"不是该系统"的错误结论(举 Haiku `driver_v1`/`device_v1` 为例)。全文 62 处标注完成 |
| 4 | `system-fingerprints.md` §二 | "ELF + ET_REL → **[强]** Linux 内核模块"**过强**——ET_REL 只说明"可重定位 ELF",后半句"或同类可重定位模块"已自认这一点 | 降为 **[弱·稳定]**:ET_REL 仅指示"可重定位 ELF";**需再命中 `.modinfo` / `__this_module` / `vermagic` 才升到 Linux 可加载内核模块** |
| 5 | `system-fingerprints.md` 缺**证据归属**维度 | 固件里可能同时有 Linux rootfs、MCU blob、guest 镜像、编译期 sysroot——**找到 `procnto`/ARXML/`seL4_*`/FreeRTOS 特征串中的任何一个,都不能回答"主体是哪个系统"**。指纹表越丰富,这类假命中越多 | 新增**第 ⓪ 层 `evidence_scope`**(`container` / `executable` / `embedded payload` / `guest` / `dependency` / `toolchain artifact` / `documentation`),规则:**先判证据属于谁,再判它是哪个系统**;跨 scope 命中只记"存在性",不作主体身份依据。同步改流程图(五层 → ⓪+四层)与入口 SKILL.md 的"先认目标"段 |
| 6 | `analysis-contract.md` 两条规则过硬 | ① "每目标**不超过 8 次**工具调用"当全局硬上限——大型固件/内核/协议/混淆程序会被强行截断;② "五步严格顺序、不可跳步、**禁止先反编译再倒推**"与真实 RE 的迭代性质冲突(类型恢复常常要先粗反编译拿 field-use / call-shape / switch / allocation size 才有线索) | ① 改**软预算**:8 次为一档,**到档必须重新评估**(继续 / 换路 / 收束三选一,结论记录在案),评估通过进入下一档;② 改**收敛循环**:`初次反编译 → 四类信息交替恢复 → 重新反编译 → 定点`,并把"decompilation"从终步改为**收敛判据**(四条同时满足才算定点:类型全解析 / 常量有名 / 虚调用目标已识别 / 签名带参数名)。**保留的约束**是"禁止只反编译不复核就交付" |
### 三、审查确认无问题的两处(本轮无需改动)
- **Haiku `driver_v1`/`device_v1` 后缀**:得到官方文档支持(本库此条早已如此写)
- **ThreadX `TX_THREAD_ID` = `0x54485244`('THRD')**:与当前 upstream 一致(本库此前已纠正过旧资料的 TIMR/EVEN 写法)
### 四、本轮校验
- `node validate.mjs`:`OK: 122 skills validated`;`npm test`:41 项全过
- 二维标注落地自检:`独有·` / `高·` / `弱·` 共 62 处
---
## 补充 23:对 22a76dc 的抽样审查——网络隔离 / 工具生命周期 / ABI(2026-09-13)
来源为同源外部审查(第二批,抽查 re-netcap / re-proto-rev / re-android-native / re-angr / re-ai-model / re-malware / re-mem-forensics + validate.mjs 与测试)。10 条全部处理,其中 1 条**核验后与审查意见相反**。
### 一、P0:两处操作级 bug
| # | 位置 | 问题 | 修正 |
|---|---|---|---|
| 1 | `re-netcap` 步骤 5 与坑表 | **沙箱断网验证不成立**——把"断网 / fake DNS / INetSim"并列,并用 `ping 8.8.8.8` 不通作为"无真实外联"的验证。**ICMP 被阻断 ≠ TCP/UDP 被阻断**;**fake DNS 挡不住硬编码 IP 的 C2**;纯断网又抓不到 C2 | 改为**默认拒绝出站(default-deny egress)+ 白名单到分析基础设施**,并给出 iptables 落地示例;验证改为**三条独立验证**(TCP / UDP / 硬编码 IP 直连),明确写"`ping 不通`不构成任何一条"。坑表同步改写 |
| 1b | `re-sandbox` 步骤 1 与 `re-malware` | "VM 快照 > 容器 > firejail"的排序容易被当作"容器是一般恶意样本的后备隔离层",但**容器与 firejail 都共享宿主内核** | 在层级说明处明确:**中低两档只适用于已知低风险样本**;样本存在内核攻击面(提权/内核漏洞/驱动载荷)时这两档不构成隔离边界;**默认承载未知高威胁样本的是 VM 快照** |
| 2 | `re-netcap` 步骤 5 | **mitmproxy 透明代理规则只重定向了 80**——上下文在处理 HTTPS/TLS,但 PREROUTING/OUTPUT 两条都是 `--dport 80`,目标访问 443 时**根本不会进入 mitmproxy** | 改为 `-m multiport --dports 80,443`,并注明"只写 80 是最常见的失误";补充非标准 TLS 端口(8443 等)需按实际观测补齐 |
### 二、P1:工具操作层(Volatility 3 三连)
| # | 问题 | 核验与修正 |
|---|---|---|
| 5 | **符号获取机制混了 Windows 与 Linux/macOS** | 核验:**Windows** 按 PDB GUID/age 在 `symbols/windows/` 找 ISF,**找不到时自动从 Microsoft 符号服务器下载 PDB 并转换**;**Linux/macOS 靠 kernel banner 精确匹配**(banner 编码在 ISF 内、文件名不重要),获取途径是社区预构建包或自行构建(`dwarf2json` 需调试内核 / `btf2json` 用 `vmlinuz` BTF + `System.map`)。原文"首次运行从 volatilityfoundation.org 下载、Linux 也是对应内核版本"**两侧都错**,已按上述改写并补"先跑 `banners` 拿 banner"的工作流 |
| 6 | **插件命名漂移** | 核验:`windows.hashdump` / `lsadump` / `cachedump` **确已迁到 `windows.registry.*`**,旧名为弃用别名(v2.27 标记 **2026-09-25** 移除——距今 12 天),已改命令与坑表。**但审查关于 malfind 的部分与核验相反**:malfind 的**源码目录**在 `windows/malware/` 下,**命令行调用名仍是 `windows.malfind`**(`malware` 不进入调用名)——**照"迁到 windows.malware.malfind"改会引入新错误**,故未改;并把这条区别写进了坑表("源码目录变了 ≠ 调用名变了") |
| 7 | **凭据来源统一写成"LSASS 内存"不准确** | 核验:三个插件都是 **registry-hive 派生**——hashdump ← SAM + SYSTEM(boot key)、lsadump/cachedump ← SECURITY(cachedump 用 **NL$KM** 解 MS-CACHEv2)。已改为分开记录:**registry-hive-derived** vs **LSASS process-memory** 两条路径,并写明取证报告里 provenance 写错后果较重 |
### 三、P1:ABI 两处
| # | 位置 | 问题 | 修正 |
|---|---|---|---|
| 3 | `re-android-native` | **JNI 字符串语义写反**(`GetStringUTFChars` 写成"C 串→UTF-8")+ **`JNINativeMethod` 三个字段被硬编码成各 8 字节** | 语义改为 **jstring → Modified UTF-8** / **Modified UTF-8 → Java String**,并补"**是 Modified UTF-8 不是标准 UTF-8**"(空字符 `0xC0 0x80`、增补字符代理对上不同);字段宽度改为"**各为一个指针**:64 位 8 字节、**32 位(armeabi-v7a/x86)4 字节**,数组步长 12 字节"。两处出现处均已改 |
| 4 | `re-angr` | **recv/read hook 的 ABI 错误**——写成"或 hook 返回符号指针",而 POSIX `recv`/`read` 的**返回值是 ssize_t 字节数** | 改为:**按调用约定取 buf 参数**(x86-64 SysV:RSI=buf、RDX=len)→ 写符号字节到该地址 → **返回符号长度**;并写明照原文实现会让 `if (recv(...) > 0)` 一类控制流全部建歪 |
### 四、P2:两处内容错误
| # | 位置 | 问题 | 修正 |
|---|---|---|---|
| 8 | `re-ai-model` | **"流式提取"名不副实**——`to_array()` 对 external data 张量会**完整 materialize**,且 `base_dir` 默认空字符串(权重不在 CWD 时直接失败) | 标题改为"**逐 tensor 惰性落地**",代码里加 `base_dir="."` 与 `del arr`,并注明**不是流式**、峰值取决于最大张量;坑表同步 |
| 9 | `re-proto-rev` | **Ethernet FCS 诊断错**——"帧短 14 字节"归因到 FCS,但 **FCS 是 4 字节、14 字节是典型以太网头部长度** | 重写为"**先量实际少了几字节**":缺 4 字节查 FCS 剥离,缺 14 字节查以太网头/注入层;并删去"Scapy 不保留尾部"这类笼统断言(帧抽象随版本与配置而异) |
### 五、结构性结论(写入 TODO)
审查指出:**41 项测试与 `validate.mjs` 主要校验 schema 与路由图,不执行 Markdown 里的 shell/Python 示例,也不验证第三方 API/CLI 是否仍存在**——所以"122 skills validated / 41 tests pass"的准确含义是**结构与路由图健康**,而非"技能内容可执行"。本轮 Volatility 的过期命令即典型漏网类型。
**趋势判断(记录)**:**领域知识已比工具操作层稳定**,新的主要缺陷来源转为「**命令/API 生命周期**」与「**示例代码没真正 smoke-test**」——与此前以事实性错误为主不同。
已在 `TODO.md` 新增「工具 CLI/API 生命周期审查」条目,含最小方案(第三方命令/API 清单 + 版本漂移检查 + 示例可执行性 + 与增量审查机制合并设计)。
### 六、本轮校验
- `node validate.mjs`:`OK: 122 skills validated`;`npm test`:41 项全过
- 涉及文件 7 个:`re-netcap` / `re-sandbox` / `re-mem-forensics` / `re-android-native` / `re-angr` / `re-ai-model` / `re-proto-rev`
---
## 补充 24:工具 CLI/API 生命周期机制落地(2026-09-13)
上一节把"命令/API 生命周期"定为新的主要缺陷来源,本节实现其最小骨架。
### 一、交付物
| 文件 | 作用 |
|---|---|
| `docs/audit/tool-register.json` | **登记表**(140 项):`name` / `kind` / `where`(引用它的技能) / `last_verified` / `source` + 一份 `ignore` 名单 |
| `lib/tool-register.mjs` | 抽取(`extractCommands`)、扫描(`collectFromSkills`)、比对与时效(`checkRegister`)、探测(`smokeProbe`) |
| `bin/toollife.mjs` | CLI:`check` / `candidates` / `stale` / `smoke`(与 `bin/capindex.mjs` 同构:lib 放逻辑、bin 做壳) |
| `tests/toollife.test.mjs` | 10 项:抽取器各类边界 + 死条目/候选/时效/非法日期 + **仓库自身一致性** |
`package.json` 增加 `npm run toollife`;`npm test` 通过 `tests/*.test.mjs` 自动纳入一致性检查。
### 二、设计取舍(记录判断依据)
- **抽取只认显式标注为 shell 的代码块**(```sh / ```bash / ```console / ```shell)。先按"所有代码块"试过一版:去重候选 **717** 个,其中大量是 python 体与结构体字段名(`print` / `import` / `onLoad` / `simgr.*`);限定标注后降到 **159**,治理成本量级下降
- **不做"每个命令都必须登记"的硬门**——那会把 `ls`/`cat`/`grep` 一类基础工具也拖进来。登记表只管**有生命周期风险的第三方工具**,基础工具在 `BASE_UTILS` 里直接过滤
- **`last_verified: null` 是一等状态**:表示"已登记、尚未核验当前 CLI/API 形态"。当前 140 项里只有 1 项已核验(`vol`,本会话核过插件路径与符号机制),其余 **139 项是明确的待核验积压**——这不是缺陷,而是把真实状态显性化;`check` 三档统计(已核验 / 超期 / 待核验积压)
- **超期与积压分开**:`stale` 只统计**已核验且超过 180 天**的项(避免把"从未核验"混进"该复核了");`pending` 单独列,供下一轮审查波分批消化
- **`smoke` 不进 CI**:探测本机是否装某工具,在 CI 机器上必然大量缺失,只作本地报告
- **死条目即失败**:登记为"在用"但技能里已找不到该命令 → `check` 报错。这是**唯一**做成硬门的检查——它无歧义、不会因正常编辑误报
### 三、防漂移闭环
```
新增技能引用新第三方工具
→ check 把该命令列为"未登记候选"
→ 仓库自身一致性测试失败(npm test 红)
→ 登记(或放入 ignore 并写明理由)
→ 绿
```
同理,**删掉某工具的全部引用而不清理登记表**也会红(死条目)。
### 四、未做(保留在 TODO)
- **示例可执行性**:把技能里的 shell/Python 示例抽成最小可跑片段。需要权衡 fixture 与网络/工具依赖,单独评估
- **逐项回填 `last_verified`**:按 `stale` 输出分批核验。当前积压 139 项
### 五、本轮校验
- `npm test`:`OK: 122 skills validated` + **51 项测试全过**(原 41 + 新增 10)
- `npm run toollife`:`登记 140 项|已核验 1|超期 0|待核验积压 139`,无错误、无未登记候选
---
## 补充 25:示例可执行性 + 增量审查机制 + 登记表风险分层(2026-09-13)
上一节遗留的三项,本节一并落地。
### 一、示例可执行性(`lib/skill-examples.mjs` + `bin/examplecheck.mjs`)
**定位**:`validate.mjs` 校验结构、不执行示例;本检查补"**示例至少语法正确**"这一层——抓不到"命令过期",但能抓到"照抄会立刻报错"。**只做语法检查**:不联网、不装依赖、不运行程序。
首轮测量与规范化(每一步都是必要的,否则误报淹没真错):
| 阶段 | python 块 | shell 块 | 说明 |
|---|---|---|---|
| 原始 `compile` / `bash -n` | 51 错 | 26 错 | 绝大多数是**假阳**:块缩进在列表项下、`(gdb)` 提示符行、`<pid>` 被 shell 当重定向 |
| 去缩进 + 提示符规范化 | **3 错** | 22 错 | python 的 3 处是真错 |
| 占位符中和 + 会话记录识别 + heredoc 拆分 | **0** | **0** | 剩余 22 处全部是 `<占位符>` |
**抓到的真问题**(已修):
- **3 处 python 语法错**:`simgr.explore(find=0x4011xx, ...)` —— `0x4011xx` 不是合法 Python(`invalid hexadecimal literal`),照抄即报错。改为合法地址 + `# 示意地址:按目标实际入口/分支替换`
- **2 处语言标错**:`re-fp-runtime` / `re-nim` 把 **Haskell / Nim 源码与构建命令塞在同一个 ```sh 块**里——已拆成 `haskell` / `nim` 代码块 + `sh` 命令块
**两个刻意的设计决定**:
- **调试器会话块不按 shell 检查**:含 `(gdb)`/`(jdb)` 提示符,或"交互式工具启动行 + `> ` 命令"的块是**会话记录**,行内容是喂给调试器的,不是 shell 语句——丢弃提示符行后再检查,避免把 jdb 转录当 shell 脚本报错
- **sh 块里嵌的 python heredoc 单独按 python 检查**(`python3 - <<'PY'` 在技能里很常见)——否则这些代码完全在检查视野之外
**CI 取舍**:需要 python3 / bash,缺失时**跳过而非失败**;接入 `npm test`(有解释器时生效),成本约 8 秒(391 块,每块一次解释器调用)。
### 二、增量审查机制(`lib/review-state.mjs` + `bin/auditstate.mjs`)
```
docs/audit/review-state.json 122 技能 × { hash, last_reviewed, note }
node bin/auditstate.mjs status → changed / unreviewed / ok 三态
node bin/auditstate.mjs update <技能...> → 回填当前 hash + 日期
```
审查波的工作流变为:**`status` 列出"内容在复核之后又变了"的技能 = 工作集 → 只审这些 → `update` 回填**。成本从 O(技能总数) 降到 O(变更数)。
- **hash 口径**:技能目录下全部 `.md`/`.sh` 按相对路径排序后逐个喂入(路径 + 内容),任一文件变化即触发
- **`last_reviewed: null` 是一等状态**:存量技能尚未按本机制复核——当前 122 项中 120 项已复核(本会话审查波覆盖)、2 项(re-ai-triage / re-feedback)从未复核
- **初始播种规则**:本会话被改动过的技能视为已复核(内容正是审查的产物)
- **已删除技能**自动从状态清理并在 `status` 告警;有测试断言状态文件覆盖全部技能
**与增量审查机制原方案的一处偏离**:原计划"扩展 validate.mjs",实际**改为独立脚本 + 一条测试断言**——审查状态需要写盘与日期,与 validate.mjs 的纯读校验性质不同,混在一起会破坏其单一职责。
### 三、登记表风险分层(`deriveRisk`)
原 `stale` 只按"距上次核验的时长"排序,但 134 项积压里**不同条目的漂移风险差异极大**。新增按**断言类型**分层(不落盘,随内容实时派生):
```
写死了层级路径(如 windows.registry.hashdump)或版本号 → 高风险(+2 各)
写出命令行开关 → 中(+1)
只点名工具名 → 低
出现面(多少个技能引用) → 仅作严重度排序,不计入风险等级
```
> 第一版把"出现次数"也算进分数,结果 `readelf` 得 130 分——那是**频率**不是**具体度**,已改正为按断言类型。
当前:**待核验 134|高风险 40|低风险 94**,`npm run toollife` 按影响面给出建议顺序(`lldb` / `tshark` / `rizin` / `adb` / `binwalk` …)。
**首批回填 6 项**(均为本会话审查波中确实核验过 CLI/API 形态的):`vol`、`frida`、`candump`、`mmls`、`tsk_recover`、`readelf`。
### 四、本轮校验
- `npm test`:`OK: 122 skills validated` + **67 项测试全过**(上轮 51 + 新增 16)
- `npm run examples`:`代码块 913 个|已检查 391 个`,通过
- `npm run audit:status`:`已复核未变 120|待复核 0|从未复核 2`
- `npm run toollife`:`登记 140 项|已核验 6|超期 0|待核验 134(高风险 40)`
---
## 补充 26:把"约定"变成检查——四类收尾(2026-09-14)
前面几轮反复出现同一个模式:**多副本信息 + 无单一事实源**(frontmatter 解析两套、能力声明无消费端、计数散落六处、references 同名、审查历史泄漏)。这一轮把当时还是"人工约定"的四类也收成检查。
### 一、probe.sh 工具清单(登记表 → 生成)
`probe.sh` 硬编码 **19** 个工具,而登记表已有 **137**——`RE_TOOLS` 是 agent 判断"环境里装了什么、优先用什么"的依据,硬编码清单会让**已装的工具不被使用**。
做法与能力索引同构:**登记表是源,probe.sh 里的清单是生成物**(`lib/probe-tools.mjs` + `bin/probelist.mjs`,`--check` 校验新鲜度并入 `npm test`)。
顺带修掉两处真问题:
- **`MEM_GB` 恒为空**:`free` 的输出被本地化(`内存:` 而非 `Mem:`),`awk '/^Mem:/'` 匹配不到——固定 `LC_ALL=C`。**与 readelf 同一类坑**(本轮 fixture 也踩到)
- **`dd` / `hexdump` 混进登记表**:属基础工具,已归入 `BASE_UTILS` 并从登记表移除(否则会被死条目检查打回)
### 二、计数同步(人工清单 → 检查)
`CLAUDE.md` 里的"按清单逐处核对"一直是人工的(历史上漏过 5 处)。`tests/counts.test.mjs` 把 13 处计数点变成断言,另加两条:README 引用的技能必须存在、**每个技能都必须在 README 出现一次**。
后者当场抓到一个真缺口:README 用简写 `re-format-pe/elf/macho`,导致 **`re-format-elf` / `re-format-macho` 从未以全名出现**(简写既不可 grep 也不利于检索)——已改为全名。
### 三、指纹表覆盖(文档约定 → 检查)
`system-fingerprints.md` 写着"新增系统分支须同步加行",但无检查。`tests/fingerprints.test.mjs` 用 MAPPED / EXEMPT 两张表断言:**新增分支若两处都没登记即失败**,并要求豁免项写明理由、映射表不得残留已删文件。
### 四、复核 = 回归断言(`tests/audit-regressions.test.mjs`)
"fixed → verified"原计划是人工复核一遍。改为**把已修事实写成永久断言**——22 条,覆盖 #1–#21 与补充 22/23。一次完成复核与防回归:日后有人重写技能时,错的说法写回去会直接红。
**复核中发现的新问题**:三条断言失败,查下去全是技能里**刻意保留的迁移对照说明**("旧写法 `Module.findExportByName(null, n)` 已移除"、"KeyStore 无 getKeyAlias"、"`this` 上没有 returnValue")——即文档写对了,是断言太粗。据此给 `absent` 加了**否定语境识别**(`已移除/已废弃/弃用/无此/没有/不再/不是/勿用/不携带/不支持/不存在/旧写法/过时`)。这条规则本身值得记:**断言与文档的区别在于,"提到错误"不等于"主张错误"**。
### 五、行为 fixture(四层验证体系的最上层,首次落地)
`tests/format-fixtures.test.mjs`:对**字节布局类断言**用纯代码构造最小样本验证,不依赖网络与外部样本。首个 fixture 覆盖 `re-format-elf/references/layout.md` 的**扩展编号三套规则**——该处原文即注明"建议配 parser fixture 验证这三条路径"。
**这一层立刻证明了价值**:fixture 抓出**当天早些时候由"修复"引入的新错误**——补充 22 里把 ELF 魔数写成"`\x7fELF`(小端读作 0x7f454c46)",而 `7f 45 4c 46` 按小端读是 **`0x464c457f`**,`0x7f454c46` 是**大端**读法。已改为给出字节序列 + 两种读法(同一文件里另有 `free`/`readelf` 的本地化坑,说明这类"看起来对"的细节最需要 fixture)。
### 六、SKILL.md 预算(re-kernel 拆分问题的结论)
**结论:不拆。** 实测口径错了——技能是**按需加载**的库,常驻成本只有 SKILL.md(re-kernel 177 行,与 re-rtos 197 / re-hypervisor 169 / re-analyze 117 同量级),分支用到才读。拆分反而要新增 5+ 技能(计数同步六处)并割裂最有价值的**失败模式决策表**。
真正要防的是 SKILL.md 膨胀,已加 `tests/skill-budget.test.mjs`(SKILL.md ≤240、单分支 ≤600、**必备章节仍在**——最后一条防的是"为了满足预算而削壳")。顺带发现 `re-kernel` 用「## 通用主线」代替模板规定的「## 操作步骤」,已对齐。
### 七、本轮校验
- `npm test`:`OK: 122 skills validated` + **103 项测试全过**(上轮 67 + 新增 36)
- 新增测试文件 5 个:`counts` / `fingerprints` / `format-fixtures` / `audit-regressions` / `skill-budget`
- 新增脚本:`bin/probelist.mjs`(`npm test` 已含 `--check`)
---
## 补充 27:Dart/Flutter 格式错误 + 三处版本漂移(2026-09-15)
来源为外部监控的第三批。6 条全部处理(3 条格式错误 + 3 条版本漂移)。
### 一、明确错误:re-flutter 的 Dart 格式(两条高影响 + 一条中影响)
| # | 原文 | 核验 | 修正 |
|---|---|---|---|
| 1 | `kernel_blob.bin` 头部是 **ASCII `"KERNEL"` magic** | **错**。`runtime/vm/kernel_binary.h` 定义 `kMagicProgramFile = 0x90abcdefu`——是**数值**,文件里为小端字节 `ef cd ab 90` | 识别改为按 4 字节魔数;并补上同源事实:**header 共 8 字节 = magic + formatVersion**(格式版本可作版本判别)。明确写"不要用字符串 grep 判断 kernel 格式" |
| 2 | 快照头 = magic `"SNAPSHOT"` 8B + **版本串 12B** + 长度 8B LE;用 `data.find(b'SNAPSHOT')` 搜索 | **错**。真实头部是 **magic `0xdcdcf5f5`(4B) + length(8B) + kind(8B) = 20 字节基础头**;**不存在 ASCII `SNAPSHOT`,也没有固定 12 字节版本串** | 解析代码改为按 `0xdcdcf5f5` 定位 + `struct.unpack('<qq', data[off+4:off+20])`;**删去写死的子 blob 分区表**,改为"版本相关的内部序列化布局,要精确解析就对着目标 SDK 的 `runtime/vm/snapshot.h` 与序列化器实现";顺带修掉依赖该错误 magic 的 `strings \| grep SNAPSHOT` 判据(改用 ELF 段符号 `_kDartIsolateSnapshot*`) |
| 3 | `kernel_blob` 只在 **debug/Profile** 构建存在 | **错**。Profile 与 Release **都是 AOT**(构建系统对 profile/release 都走 AOT 编译) | 执行模型改为 **Debug → JIT/Kernel;Profile 与 Release → AOT**;两者差别是 profiling/service/优化配置,不是执行模型 |
**两条已固化为回归断言 + 格式 fixture**(`tests/format-fixtures.test.mjs`):断言 `0x90abcdef` 的 LE 字节是 `ef cd ab 90`、`0xdcdcf5f5` 的是 `f5 f5 dc dc`、20 字节基础头的三段布局——**同时锁定"这两个 magic 不是可 grep 的 ASCII 串"**,日后写回去会直接红。
### 二、版本漂移(三条)
| # | 位置 | 原文 | 修正 |
|---|---|---|---|
| 4 | `re-analyze/references/preferences.md` | IDA Free"**当前 8.x**" | 已过时(2025 年已发布 9.x 线)→ **删掉版本代际的写死**,只留能力矩阵(x86/x86-64 限定、无 SDK/IDAPython、非商用),需要时以官方发布为准 |
| 5 | `re-netcap/SKILL.md` | mitmproxy"(Python 3.10+)" | 核验后比审查意见更早:**v12.0.0 的 pyproject 就已 `requires-python >=3.12`**(不限于 12.1.0)→ 改为"当前 12.x 要求 Python >=3.12;旧环境需 pin 对应旧版"。因 re-tls / re-drm 把安装委托给本技能,只改一处 |
| 6 | `re-exploit/SKILL.md` | "9.x 支持 Python 3.9–3.11 系" | 与 re-angr 已修正的表述**直接冲突**(angr 9.3.0 起要求 3.12+)→ **删掉 re-exploit 自维护的版本矩阵**,改为"兼容性以 [[re-angr]] 工具准备为准"——同一事实只维护一份 |
### 三、一条"尚未过时但即将过时"的记录
监控同时核验了 Ghidra 的 JDK 21 描述并**判定暂不报**:当前最新正式 release 仍是 12.1.3(2026-08-18),master 已进入 12.2 文档并改为 JDK 25,但 12.2 尚未正式发布。**12.2 发布后该条会立刻成为高优先级过时项**——这类"预告式"结论值得保留,它说明版本监控不只在事后抓。
### 四、本轮校验
- `npm test`:`OK: 122 skills validated` + **110 项测试全过**(上轮 103 + 新增 7)
- 登记表回填 `mitmproxy`(现 7 项已核验);审查状态:已复核 120 / 待复核 0
- 初版新断言有一条误报(把"kernel magic 0x90abcdef"这种**带正确数值的用法**也拦下)——已收紧为只禁 `"KERNEL" magic` 这一旧表述
---
## 补充 28:Mach-O 基础常量层(2026-09-15)
### 一、性质:不是措辞问题,是**解析层常量错误**
`re-format-macho/references/layout.md` 在 **CPU subtype、header flags、symbol type、fat header 四个基础解析层**都有确定性常量错误——依赖该 reference 的 Mach-O / iOS / Swift 分析会被系统性带偏。
**核验来源**:本机 **LLVM `BinaryFormat/MachO.h`**(Apple `loader.h`/`machine.h` 的忠实移植,含数值)+ Apple `fat.h` 文档。**未使用搜索摘要中的二手描述**(那几轮搜索只给了名字没给数值)。
| # | 原文 | 核验后 | 修正 |
|---|---|---|---|
| 1 | `0x0100000C=arm64`、`0x0100000B=arm64e` | **arm64 与 arm64e 的 cputype 相同**(都是 `CPU_TYPE_ARM(12) \| CPU_ARCH_ABI64(0x01000000)` = **0x0100000C**);区别在 **cpusubtype = `CPU_SUBTYPE_ARM64E`(2)** | 表格改为"**arm64e 靠 cpusubtype 区分,不要用 cputype 判**" |
| 2 | `3=x86_64`、`0x80000003=x86_64h` | `CPU_SUBTYPE_X86_64_ALL=3`、**`CPU_SUBTYPE_X86_64_H=8`**;`0x80000000` 是 **capability 位**(`CPU_SUBTYPE_LIB64`),**不把 3 变成 x86_64h** | 补全 arm64 侧 subtype(0/1/2)与 x86_64 侧(3/8),并把 capability 位单独解释;arm64e 另有 `0x80000000` 作 versioned-ptrauth-ABI 掩码 |
| 3 | `1=NOUNDEFS 2=DYLDLINK 4=TWOLEVEL … 0x800000=LAZY_INIT` | 实际是位值:`0x1` NOUNDEFS、`0x2` **INCRLINK**、`0x4` **DYLDLINK**、`0x8` BINDATLOAD、`0x10` PREBOUND、`0x20` SPLIT_SEGS、**`0x40` LAZY_INIT(已废弃)**、**`0x80` TWOLEVEL**、`0x100` FORCE_FLAT、`0x200` NOMULTIDEFS、**`0x200000` PIE**、**`0x800000` HAS_TLV_DESCRIPTORS** | 按 Apple 位值列出,明确"不要手工精简成连续编号"——原表**整体错位**,还把现代 TLS 描述符标志标成了已废弃的 lazy init |
| 4 | `0x0E=N_SECT 0x0F=N_UNDF` | `N_TYPE=0x0e` 是**掩码**:`N_UNDF=0x0`、`N_ABS=0x2`、`N_SECT=0xE`、`N_INDR=0xA`;`N_EXT=0x01`/`N_PEXT=0x10` 是可 OR 的**属性位**。`0x0f` = `N_SECT\|N_EXT`(外部节定义符号) | 改为**分层读**(`n_type & N_TYPE` + 属性位单独判),明确"不要把组合值当基础类型" |
| 5 | `FAT_MAGIC 0xCAFEBABE(LE 文件字节 be ba fe ca)`;`offset 为 4 字节对齐` | **fat 结构在磁盘上恒为大端**(Apple fat.h 明述,与宿主无关)→ 正常 FAT 文件**开头就是 `CA FE BA BE`**;小端读得 `0xbebafeca`(=`FAT_CIGAM`)是**同一份字节被小端解释**;**`fat_arch.align` 是"对齐的 2 的幂"**(slice 需 `2^align` 对齐) | 两者都改写,并加"别用宿主端序猜文件端序" |
### 二、udsoncan:示例缺少 DID codec 配置
`re-automotive` 的 VIN 示例直接 `Client(conn, request_timeout=2)` 后 `read_data_by_identifier(DataIdentifier.VIN)`,**缺 `config`**——而 `read_data_by_identifier` 依赖 `config['data_identifiers']`(DID → codec 映射)来解码响应载荷,**没有 codec 就无从解码**。
**修正**:示例补上 `config['data_identifiers'] = {0xF190: …}`(VIN 的标准 DID,17 字节 ASCII codec)并传入 `Client(..., config=config)`;同时在步骤里加了"**读/写 DID 必须先配 codec**"的说明与"只想看原始载荷就走不做解码的低层接口"的出路。
**一处刻意的克制**:`data_identifiers` 机制与 `DidCodec` 概念已核验,但**具体的 codec 辅助类名未获证实**,因此示例里用 `...` 占位并注明"用库自带的类型,或自定义 `DidCodec` 子类"——**不能用另一个未经核验的 API 去替换一个错的 API**。
### 三、固化
- **格式 fixture**(`tests/format-fixtures.test.mjs`)新增 4 条:cputype/cpusubtype 的推导与 arm64e 判别、header flags 的位值(含"按连续编号抄会全错位"的反证)、`n_type` 的分层读法、fat 的大端与 `2^align`
- **回归断言**(`tests/audit-regressions.test.mjs`)新增 2 条:常量表不得复现旧值 + udsoncan 示例必须带 config
- 写 fixture 时踩到一个**跨语言坑并顺手记进断言**:JS 的位运算是**有符号 32 位**,`0x80000000 | 3` 得 `-2147483645`,要 `>>> 0` 才是 `0x80000003`——与 C 里 `uint32_t`/有符号的区分同源
### 四、重复报告说明
本轮报告的 **IDA Free "当前 8.x"** 已在补充 27 修复(并已有回归断言);**Ghidra JDK 21** 的"暂不过时、12.2 发布后即过时"也已记录在补充 27。两条不重复处理。
### 五、本轮校验
- `npm test`:`OK: 122 skills validated` + **116 项测试全过**(上轮 110 + 新增 6)
- 初版两条断言失败均为**测试自身的 bug**(把修正行里的"而不是固定 4 字节对齐"当成旧表述;JS 有符号位运算),已修正
---
## 补充 29:Apktool 版本模型落后一个大版本(2026-09-16)
### 一、性质:不是措辞过时,是**整代 CLI 不兼容**
`re-apk` 仍把 apktool 描述为「2.x 系列」,并围绕 2.x 的 `--use-aapt2`(aapt1/aapt2 二选一)组织回编译流程。但 3.x 已是当前主线、2.x 退为维护线,而 3.x 有一批**会让 2.x 命令直接报错**的 breaking changes——照仓内现有写法执行会被工具拒绝。
### 二、核验来源(四路交叉,全部一手)
| 来源 | 拿到什么 |
|---|---|
| GitHub Releases(`gh release view v3.0.1`) | 3.0.1/3.0.2/3.0.3 的发布说明与 PR 列表;「v3.0.0 因缺 .jar 被撤回,3.0.1 与之等同」 |
| `apktool-cli/src/main/java/brut/apktool/Main.java` @ v3.0.1(源码) | **选项定义全集**——短参数、长参数、移除项的唯一事实源 |
| 官方安装页 `apktool.org/docs/install`(标 "Version: 3.x") | 「A minimum of Java 8 is required to run Apktool」;文档分 3.x / 2.x 两轨 |
| **`prebuilt/` 目录里的实际二进制**(取回后 `file`) | 32 位支持的存在与否——见下 |
### 三、逐条核验结果
| # | 原表述 | 核验后 | 依据 |
|---|---|---|---|
| 1 | 「apktool:2.x 系列」 | **3.x 为当前主线、2.x 为维护线**,两线命令不完全兼容 | Releases 页 3.0.1/3.0.2/3.0.3;官网首页显示 3.0.3 且文档分两轨 |
| 2 | `--use-aapt2` 可强制 aapt2 回编译 | **aapt1 整体移除,`--use-aapt2` 这个"二选一开关"随之不存在**;换 aapt2 二进制改用 `--aapt <file>`,且传入 aapt1 会被显式拒绝 | 发布说明 `[v3] Remove aapt1 testing`(PR #3883);`Main.java:571` — `if (getBinaryVersion(...) == 1) throw new AndrolibException("Legacy aapt is no longer supported.")` |
| 3 | (原文未涉及) | **不再提供 32 位构建** | 见下「最有分量的一条」 |
| 4 | (原文未涉及) | `--api-level` 移除(`Main.java` 中 `api.level`/`apiLevel` **命中 0 处**) | 源码全文检索 |
| 5 | (原文未涉及) | **`--only-main-classes` 由 `-a`/`--all-src` 取代,且语义相反**:前者只解主 dex,后者「Decode all sources in the apk (includes unknown dex files)」 | 发布说明 `replace --only-main-classes with -a/--all-src`(PR #4069)+ `Main.java` 的 `decodeAllSrcOption` 描述串 |
| 6 | (原文未涉及) | **高级选项只认长参数**:v3.0.1 的短参数**全集**为 `-a -f -j -l -o -p -q -r -s -t -v`,`-m`/`-k` 一类旧短参报 `Unrecognized option` | 源码里 `Option.builder("<短参>")` 穷举;佐证:Debian #1140015 — diffoscope 因 `Unrecognized option: -k`/`-m` 改用 `--keep-broken-res`/`--match-original` 才修好 |
**仓内旧调用扫描**(按报告的清单全查):只有 `--use-aapt2` 命中 4 处(`gotchas.md` ×2、`commands.md` ×2);`--api-level`、`--only-main-classes`、`-api`、`-m`、`-k`、`-resm`、`-b` **均为 0 处**。其余 apktool 调用(`d -r`、`d -s`、`b -o`)在 3.x 下仍然有效,**未做无谓改动**。
### 四、最有分量的一条:32 位支持是拿二进制本身证的
官方文档页**没有**任何架构说明,发布说明也只提了 aapt1。所以这条不能靠转述。改用直接证据——把两个 tag 的 `prebuilt/linux/` 二进制取回来自查:
| 文件 | `file` 结果 |
|---|---|
| 2.12.1 `prebuilt/linux/aapt2`(无后缀) | **ELF 32-bit LSB executable, Intel i386** |
| 2.12.1 `prebuilt/linux/aapt2_64` | ELF 64-bit LSB executable, x86-64 |
| 3.0.1 `prebuilt/linux/aapt2`(唯一一个) | **ELF 64-bit LSB executable, x86-64** |
2.x 的命名规则由此坐实:**无后缀 = 32 位,`_64` 后缀 = 64 位**。3.x 每个平台只剩一个二进制、`_64` 后缀消失、且实测为 64 位——32 位支持确实没了。这同时解释了命名变化的原因:32 位一去,`_64` 后缀就没有存在意义。目录结构也同步印证 aapt1 的消失:2.12.1 的 `prebuilt/` 带 `aapt`/`aapt_64`/`aapt2`/`aapt2_64`,3.0.1 只剩 `aapt2`。
### 五、刻意没写的两处
- **Java 要求不动**:官方安装页明写「minimum of Java 8」,构建脚本也是 `--release 8`——原文「依赖 Java 8+」**成立**,不加戏
- **`--debug` → `--debuggable` 未写入**:源码里确见 `buildDebuggableOption`/`longOpt("debuggable")`,但 2.x 侧的对应用法是第三方 changelog 转述,**未证实的旧名不写**
- **`-a` 归入 decode 步骤**:发布说明另有「promote -a/--all-src to a common option」表明它已是通用选项,仓内按主用途(解包)举例,未对 build 侧下断言
### 六、Ghidra 12.2 / JDK 25 临界项:本轮复核仍**不**转为过时
官方 master 的 12.2 文档要求最低 JDK 25,但正式 release 仍为 12.1.3(2026-08-18),12.2 未发布。且仓内现有表述**已经把两套要求分开写**——`re-ghidra/SKILL.md` 与 `gotchas.md` 均为「运行官方 release 需 JDK 21,从源码构建 Ghidra 自身需 JDK 25 + Gradle 9.1+,别混」。这正是不提前报错的原因:**JDK 25 要求属于"从源码构建",不属于"运行正式版"**。维持现状,待 12.2 正式发布再转为过时项。
### 七、固化
- `tests/audit-regressions.test.mjs` 新增 4 条:版本模型存在、「apktool 调用行」不得残留 2.x 专有选项、`--api-level` 不得写成可用选项、32 位表述与 `_64` 命名一致
- **断言只查"像命令一样写出来"的行**——迁移说明会刻意引用旧写法(「`--use-aapt2` 已随 aapt1 一并移除」),按"提到错误 ≠ 主张错误"给迁移语境豁免
- **变异测试验证非空转**:注入 `apktool b out/ --use-aapt2 -o x.apk` 与 `apktool d --api-level 34 ...` 后,两条断言精准失败;还原后全过。(第一次注入失败是因为样本里带了「旧写法」三个字、正好落进豁免词表——**是样本没造好,不是断言失效**,重造后确认有效)
- `npm test`:`OK: 122 skills validated` + **120 项测试全过**(上轮 116 + 新增 4)
---
## 补充 30:ELF 段语义 2 项(采纳)+ 一次被驳回的报告(2026-09-17)
### 一、采纳:`PT_LOAD` 的"唯一被映射"表述错误
原文「PT_LOAD:唯一被映射的段类型」把 **loadable segment** 与「运行时内存映像里可能出现的东西」混成了一件事。`elf(5)`(Linux man-pages,内容源自 gABI)原文即是反证:
- **PT_LOAD**:"The array element specifies a **loadable segment**, described by p_filesz and p_memsz. The bytes from the file are mapped to the beginning of the memory segment."
- **PT_PHDR**:"specifies the location and size of the program header table itself, **both in the file and in the memory image of the program**." ← 与"唯一被映射"直接矛盾
- **PT_TLS** 等同样带运行时内存语义
**改法**:改为「定义需要装载进进程内存映像的 loadable segment(按 p_filesz/p_memsz 建立常规文件→内存映射)」,并显式写上"不要表述成唯一被映射的段类型"+ PT_PHDR 这条反证。
### 二、采纳:`PT_GNU_STACK` 缺失的默认策略不能一律推断
原文「无 X 标志 = NX;缺失 = 假定可执行栈」——后半句是把一条**架构相关**的默认当成了跨架构规则。`elf(5)` 对 PT_GNU_STACK 只规定存在时的行为("used by the Linux kernel to control the state of the stack via the flags set in the p_flags member"),**对缺失不作规定**。内核侧 `fs/binfmt_elf.c` 的 `elf_read_implies_exec()` 才是决定项,而它是架构相关的:
| | 缺 NX 的 CPU | 有 NX,ia32 | 有 NX,x86_64 |
|---|---|---|---|
| 缺 PT_GNU_STACK | 需要 RIE | **需要 RIE** | **不需要 RIE** |
| GNU_STACK == RWX | 需要 RIE | 不需要 RIE:栈 X | 不需要 RIE:栈 X |
即:**x86-64 上缺失按不可执行处理,ia32 上缺失才走 `READ_IMPLIES_EXEC`**。仓内另有一条独立佐证(`re-format-elf/SKILL.md` 的 `dlopen` 坑):glibc 对缺该段的对象是**直接拒绝**而不是假定可执行——已在 `layout.md` 加交叉引用。
**改法**:拆成「存在时 / 缺失时」两种情形,缺失一侧指明依目标 ABI/内核而异并给出 x86-64 与 ia32 的差别。对逆向固件与跨架构 ELF 有实际意义。
### 三、驳回:udsoncan 的 `ClientConfig` 报告(附实测)
报告称 `from udsoncan.client import Client, ClientConfig` **执行到 import 就会出问题**,`ClientConfig` 不是供用户实例化的配置类,因此示例在建连前就失败,定为高影响操作级错误。**实测三条主张全部不成立**:
| 报告主张 | 实测结果 |
|---|---|
| import 会失败 | `udsoncan/client.py:17` 有 `from udsoncan.typing import ClientConfig`——该名字**已绑定在模块命名空间**,import 成功 |
| `ClientConfig` 不可实例化 | 它是 `TypedDict`(`typing.py:29`);TypedDict 运行时实例化返回**空 dict**,实测 `ClientConfig()` → `{}`,不抛错 |
| 照抄示例会失败 | `Client.__init__` 先 `self.config = dict(config)`,紧接着 `refresh_config()` —— 后者 `for k in default_client_config: if k not in self.config: self.config[k] = default_client_config[k]` **把所有缺键补齐** |
实跑记录(udsoncan **1.26.1**,master 2026-08-09,源码 clone 到本地直接执行):
```
第 1 步 from udsoncan.client import Client, ClientConfig → OK
第 2 步 config = ClientConfig() → {}(不抛错)
第 3 步 Client(Dummy(), request_timeout=2, config=config) → OK,最终 19 个键,关键键无缺失
request_timeout = 2 | data_identifiers = {0xf190: ...}
对照 dict(default_client_config) 写法 → OK,同样 19 个键、同样结果
```
**结论:示例可运行,不做"修复"。** 报告建议的 `dict(default_client_config)` 本身没错、也是官方 README 的用法,但它**不是修正**——改成它不会改变任何行为。若照报告去"修",属于为不存在的问题改动已正确的代码。
### 四、报告方向仍有价值:顺手把注释从"笼统"换成"实测签名"
既然实跑了一遍,把原文那句过于笼统的「udsoncan 会直接以配置错误终止」换成实测到的精确签名:
- 该 DID **不在**映射里 → 发送请求**之前**抛 `ConfigError`:`Actual data identifier configuration contains no definition for data identifier 0xf190`
- 映射里有、但 codec 不是 `DidCodec` 实例 → `ValueError`:`Given codec of type <class 'NoneType'> is not a valid DidCodec`
- 并写明:配置**只需给出要覆盖的键**,其余由 `default_client_config` 补齐——这正是驳倒报告的那条事实,值得让读者也知道
这三条都是跑出来的,不是推的。
### 五、方法教训
- **读代码推断不能替代实跑**:`ClientConfig()` 的真实结果、`refresh_config` 的补齐行为,都在源码里,但**分散在三处**(typing.py / client.py:114 / client.py:156);不跑一遍就只能停在"看起来会坏",分不清"看起来会坏"与"实际会坏"
- **报告的价值不等于报告的正确性**:这一条报告判错了,但它促成的实测把原本笼统的注释换成了精确的失败签名——**错误报告的净收益仍为正**,所以驳回也要给证据链,而不是简单回一句"不成立"
### 六、固化
- 回归断言 +3:PT_LOAD 表述、PT_GNU_STACK 缺失默认、udsoncan 已实测事实(第三条的注释里写明了它对应一次被驳回的报告,防止日后有人"照报告的思路"把正确的例子改错)
- **变异测试**:把两条 ELF 表述写回旧文本后,两条断言精准失败;还原后全过
- `npm test`:`OK: 122 skills validated` + **123 项测试全过**(上轮 120 + 新增 3)
---
## 补充 31:RISC-V Float ABI 判定错误(+ 扫出 ARM 同型实例)+ pwntools 迁移窗口(2026-09-18)
### 一、RISC-V:把 ISA 扩展与调用约定混为一谈,并假设软硬可混编
原文:「判定:`readelf -h` Flags 浮点 ABI 位 + 反汇编浮点指令密度(flw/fadd/fmv 等)佐证;**混编软/硬浮点编译单元时按单元确认(同 ARM 场景)**」。两处都错:
| 错误 | 实测反证 |
|---|---|
| 用浮点指令密度反推参数 ABI | `-march=rv64ifd -mabi=lp64` 合法:产物**照用**硬件浮点指令,参数却仍走整数寄存器 |
| 软/硬浮点编译单元可混编 | 链接器**直接拒绝**:`cannot link object files with different floating-point ABI` |
**实验记录**(clang `--target=riscv64`,`-march=rv64ifd`,同一份 `double mul(double,double){return x*y;}`):
```
-mabi=lp64 → readelf -h: Flags: 0x0 (软浮点 ABI)
disasm: fmv.d.x fa5, a1 / fmv.d.x fa5, a0 ← 从整型 a0/a1 搬进浮点寄存器
-mabi=lp64d → readelf -h: Flags: 0x4, double-float ABI
disasm: fsd fa0, ... / fsd fa1, ... ← 参数直接在浮点寄存器 fa0/fa1
ld.lld a_lp64.o b_lp64d.o → error: cannot link object files with different floating-point ABI
对照 两个都是 lp64d → 链接成功(产出 1344 字节)
```
`fmv.d.x fa5, a1` 这一行就是全部要害:**浮点指令在场,参数却从整型寄存器来**。所以浮点指令密度只能佐证「ISA 含 F/D/Q 扩展」,不能佐证参数 ABI。
**e_flags 编码**(本机 `/usr/include/elf.h`):`EF_RISCV_FLOAT_ABI = 0x0006` 是掩码,SOFT=0x0 / SINGLE=0x2 / DOUBLE=0x4 / QUAD=0x6。仓内 `readelf -h` 那一行的原始描述本来就对,**未改动**——错的是把它和"指令密度"并列当判据。
**改动**:判定改为以 `e_flags & EF_RISCV_FLOAT_ABI` 为准,写明 ISA 扩展与调用约定是两件事,并补上链接器的硬约束与"观察到局部约定不同时"的替代解释(手写汇编、非标准 ABI、`STO_RISCV_VARIANT_CC`、FFI/thunk、函数边界识别错误)。
### 二、扫全仓扫出的同型实例:re-arm
原文 RISC-V 那句末尾写着「同 ARM 场景」,而 `re-arm/SKILL.md` 的对应条目确实是同一缺陷:
- 「同一固件可能混编硬浮点(走 s0)与软浮点(走 r0)编译单元」
- 「vcmp/vcvt 等浮点指令出现频率佐证」← 同上,用指令反推调用约定
**已实测的部分**:`-mfloat-abi=softfp` 是「软浮点调用约定 + 允许 VFP 指令」——反汇编为 `vmov s0, r1` / `vmov s2, r0`,**从整数寄存器 r1/r0 搬进浮点寄存器 s0/s2**,与 RISC-V 的 lp64 完全同型。它照样发射 `vmov/vadd/vcmp`,所以"浮点指令频率佐证 float ABI"在这里同样不成立。
**刻意没写的部分**:ARM 侧「硬浮点与软浮点能否混编」我没能证实——LLD 在 `-r` 下对 soft+softfp、hard+soft、hard+softfp 三种组合**全部放行**(GNU ld 在此处更严格,但我没有 ARM 版 GNU ld 可验);并且 clang 产物三种 ABI 的 e_flags **完全相同**(都是 `0x5000000`),`EF_ARM_ABI_FLOAT_HARD/SOFT`(0x400/0x200) 未被设置。这两点都可能只是"LLD 宽松 / clang 不设位",**不足以推翻仓库现有表述**,因此只改掉已确证的那半句(指令频率不能作判据),并写明 `softfp` 的定位;链接兼容性保持原样不动。
### 三、pwntools:进入迁移窗口(当前仍可用,故不标过时)
官方 4.15.0 release 说明首行即:**"This is the last release supporting Python 2 and Python <3.10."** 而 4.15.0 至今仍是最新 tag(无 4.16)。所以 `pip install pwntools` 本身**现在没坏**——但 4.15.x 已是这条兼容线的末班车,继续维护成无版本限定的「Python 3.8+」会误导到"永远成立"。
**改动(含结构收敛)**:照 `re-angr` 已有的先例,把 Python 兼容矩阵**只留在 `re-pwn` 一处**,`re-exploit` 改为引用:
- `re-pwn`:写明当前正式版 4.15.0、支持 3.8+、官方已声明是最后一个支持 <3.10 的版本、后续按 >=3.10 准备、旧环境需 pin `pwntools==4.15.0`
- `re-exploit`:`pip install` 命令保留,版本兼容性改为「以 [[re-pwn]] 的工具准备为准」——**单一事实源,避免重演 angr 那种两处矩阵漂移**
### 四、本轮报告中被核验为"仍然有效"的两项:不动
- **Frida**:官方 Python binding 仍声明 Python >=3.7,`pip install frida-tools` 仍是官方推荐——仓内「Python 3.8+」不构成过时项
- **Volatility 3**:当前 PyPI 版本仍要求 Python >=3.8——`re-mem-forensics` 该项保持有效
两条都不做改动。
### 五、固化
- 回归断言 +3:RISC-V 判定(e_flags 为准 + 链接器行为 + `mabi=lp64` 反例)、re-arm(`softfp` 定位 + 不得用指令频率佐证)、pwntools 矩阵单点维护(`re-exploit` 不得出现 `Python 3.8+`、须指向 `[[re-pwn]]`)
- **变异测试**:把三处写回旧表述后三条断言全部失败,还原后全过
- `npm test`:`OK: 122 skills validated` + **126 项测试全过**(上轮 123 + 新增 3)
---
## 补充 32:8 项事实修正(2026-09-23)
本轮报告条目多,按「版本类 / 机制类」分组。**版本类全部以 PyPI 的 `requires-python` 元数据为准**(直接查元数据,不用二手转述);机制类尽量上机实测。
### 一、版本类 4 项:Python 下限已抬高,无 pin 的安装说明不再成立
| 技能 | 原表述 | PyPI 元数据(本轮实测) | 修正 |
|---|---|---|---|
| re-ai-model | torch「Python 3.9+」 | `torch 2.14.0` → **`>=3.10`**;`torchvision 0.29.0` → `!=3.14.1,>=3.10` | 标题改 `Python >=3.10`,补版本下限说明与「3.9 需 pin 2.8.x 及更早」 |
| re-ai-model | protobuf「Python 3.8+」 | `protobuf 7.36.2` → **`>=3.10`** | 改 `>=3.10`,注明 3.8/3.9 需 pin 旧版 |
| re-blockchain | web3.py「Python 3.8+」 | `web3 8.0.0` → **`<4,>=3.10`** | 改 `>=3.10`,注明 7.x 才支持 3.8 |
| re-crypto-decrypt | angr「Python 3.8+」 | `angr 10.0.0` → **`>=3.12`** | **删除本地副本**,改为「以 [[re-angr]] 的『工具准备』为准」 |
- **re-crypto-decrypt 的处理方式与报告建议一致**:`re-angr` 早已维护正确的矩阵(9.3.0+ 要求 3.12+),`re-exploit` 也已改为引用——本次把最后一处副本收掉,angr 的 Python 矩阵**现在全库只有一份**
- **web3 的 8.0 major release 影响面已核**:全仓搜 `web3.` 只有安装命令、import 验证与一句「经 RPC 只读」的描述,**没有任何 API 示例**,因此不存在「示例按 7.x 写」的迁移问题——只改版本文字即可
- **提交层面的一致性**:torch / protobuf / web3 三处的共同形态是「泛化的 X.Y+ 与新版本元数据冲突」,此前的 protobuf 与 web3.py 已在本轮一并处理,不再留同类表述
**同时核验为「仍有效、不动」的两项**(避免误报):`frida 17.18.0` → `>=3.7`;`volatility3 2.28.2` → `>=3.8.0`。仓内相关表述保持原样。
### 二、机制类 4 项:都是「把特例当通则」
这四项形态相同——**用一个窄机制的结论去覆盖整个类别**,因此都按「拆开两种情形 + 给出判定方法」修正。
#### 1. re-anti-cheat:attach 失败 ≠ PPL;内核调试 ≠ 唯一手段(高影响)
原文三处主张需要拆开:
| 原文 | 问题 |
|---|---|
| 「反作弊驱动用 PPL 保护游戏与自身进程」 | **PPL 是 Windows 自身的进程保护机制**,不是反作弊"设定"的 |
| 「受保护进程(PPL)直接 attach 不可行」 | 把 attach 失败当成 PPL 的证据 |
| 「内核调试是分析反作弊驱动的唯一动态手段」 | 把"驱动内核侧"等同于"整个反作弊系统" |
**核验来源**:Microsoft `PROCESS_PROTECTION_LEVEL_INFORMATION` 文档——该结构有明确的 protection level 枚举(`PROTECTION_LEVEL_NONE` = "The process is not protected"、`PROTECTION_LEVEL_PPL_APP` = "The process is a third party app that is using process protection" 等),**文档中不存在任何「加载某类驱动即成为 PPL」的规则**。反作弊当然可以在内核侧做访问过滤、对象回调、完整性校验与反调试而不把目标设成 PPL。
**修正**:流程改为先查真实 protection level(`GetProcessInformation(..., ProcessProtectionLevelInfo, ...)` / Process Explorer / WinDbg 读 `EPROCESS.Protection`),只有非 `PROTECTION_LEVEL_NONE` 才判 PPL;普通进程 attach 失败时分别排查句柄访问过滤/对象回调(`ObRegisterCallbacks`)、用户态反调试、自终止、调试器检测。原「唯一手段」条目**改写为两个坑**:一个专讲「把 attach 失败判成 PPL」,一个专讲「把内核调试当唯一手段」并列出用户态仍可观测的面(service/launcher、IPC、文件与注册表、ETW、网络交互、进程与模块生命周期)。
#### 2. re-zig:普通 Zig 函数不是默认 C ABI(高影响)
原文(主技能与 `references/layout.md` 各一处):「调用约定:默认 C ABI(`callconv(.c)` 为默认)」→ 并由此推出「反编译时无特殊约定负担」。
**核验来源 = 本机 Zig 编译器自带的语言定义**(`0.17.0-dev`,`lib/std/lang.zig` 的 `CallingConvention` 枚举,注释即官方定义):
- `c`:「This is an alias for the default C calling convention for this target. **Functions marked as `extern` or `export` are given this calling convention by default.**」
- `auto`:「**The default Zig calling convention when neither `export` nor `inline` is specified.** This calling convention makes no guarantees about stack alignment, registers, etc. It can only be used within this Zig compilation unit.」
即 `c` 与 `auto` 是**两个不同的枚举成员**:普通 `fn` 走 `auto`,只有 `extern`/`export` 才默认拿 `c`。**`callconv(.c)` 恰恰是显式要求 C 约定,不是普通函数的默认值。**
**修正**:两处统一改为「C ABI 只在 `extern`/`export` 或显式 `callconv(.c)` 的边界上假定」,并明确「恢复纯 Zig 内部函数原型时不能无条件套 C ABI 的寄存器/聚合传参/返回值规则」;原「C 库调用点参数布局直接按 ABI 读」的作用域收窄到**已确认的 C ABI 边界**。
#### 3. re-ics:DNP3 组 3 是静态双位输入,不是「事件」(中高影响)
原文速查「组 1 二进制输入 / **组 3 事件** / 组 10 二进制输出 / 组 30 模拟输入」——把 Object Group 3 当成了泛化的"事件"。
**核验来源**:Wireshark DNP3 解析器(`epan/dissectors/packet-dnp.c`,IEEE 1815 的独立实现)的对象定义表:
| 定义 | 注释原文 | 组号 |
|---|---|---|
| `AL_OBJ_BI_*` | Binary Input / Binary Input With Status | 1 |
| `AL_OBJ_BIC_*` | **Binary Input Change**(事件) | 2 |
| `AL_OBJ_2BI_*` | **Double-bit Input** / With Status | 3 |
| `AL_OBJ_2BIC_*` | **Double-bit Input Change**(事件) | 4 |
| `AL_OBJ_BO_*` / `AL_OBJ_BOC_*` | Binary Output Status / Change | 10 / 11 |
| `AL_OBJ_AI_*` / `AL_OBJ_AIC_*` | Analog Input / Analog Input Change | 30 / 32 |
组 3 是**静态双位量**,它的事件对象是**组 4**。
**修正**:按报告建议,把单编号速查**扩展成 static/event 成对映射**(1↔2、3↔4、10↔11、30↔32),并写明「别把静态量组当事件组」——按静态/事件成对建模正是恢复点表时实际需要的对象模型。
#### 4. re-arm:AArch32 的 8 项向量表被泛化成了整个 Cortex-A(高影响)
原文「**Cortex-A 启动代码**:复位向量 0x00000000(或高端向量 0xFFFF0000),异常向量表 8 项(Reset/Undef/SWI/…)」——这是 **AArch32/Armv7-A** 的异常模型,而该技能同时覆盖 AArch64(提供 qemu-aarch64、AAPCS64 路径),会实际误导 Armv8-A 固件入口识别。
**核验来源**:Linux `arch/arm64/kernel/entry.S`(部署中的 AArch64 实现):
```
SYM_CODE_START(vectors)
kernel_ventry 1, t, 64, sync // Synchronous EL1t
... (共 16 条:EL1t×4 + EL1h×4 + EL0-64×4 + EL0-32×4)
.org .Lventry_start\@ + 128 // Did we overflow the ventry slot?
...
msr vbar_el1, x30 // install vector table
```
`kernel_ventry` 宏以 `.align 7` + `.org +128` 固定 **0x80 步长**,全表 **16 项**,按 当前 EL/低 EL × SP_EL0/SP_ELx × AArch64/AArch32 来源 × sync/irq/fiq/error 分类;基址来自 **VBAR_EL1**。**AArch64 下不存在"固定 8 项 Reset/Undef/SWI 表"**。
**修正**:拆成 AArch32 与 AArch64 两个子项——AArch32 保留 8 项表(注明 low/high vectors 与架构版本控制位相关);AArch64 写明 VBAR_ELx + 16×0x80 布局,并给出定位线索(`msr vbar_el1/el2/el3, Xt` 序列),同时提示 **reset entry 由实现/SoC 配置决定**、不能假定固定在 0。
### 三、Ghidra 12.2 / JDK 25 临界项:本轮仍不变
官方 Releases 最新正式版仍是 12.1.3(2026-08-18),12.2 未发布,仓内「正式 release 用 JDK 21」继续成立,不改。
### 四、方法教训:变异测试的样本本身会被设计缺陷骗过
ARM 那条断言我做了**两次**变异才测通:
1. 第一次把 8 项表改写成简短形式,但**该行仍留在 AArch32 项目符号内**——它确实是被正确限定的,断言放行是对的,**是我的样本没造好**
2. 第二次直接把 AArch32 那一行删掉——结果连 needle 一起消失了,断言「无违规」成了**空真**(存在性检查被 AArch32 出现在别处满足)
只有第三次**完整还原成原始通用表述**才精准失败。教训:变异测试要复现**缺陷形态**本身,而不是"看起来相近的改动";否则会得到"断言通过"的假信号,反过来掩盖断言的空转。
### 五、固化
- 回归断言 +6:Python 下限四项、angr 矩阵单点维护、PPL/内核调试、Zig 调用约定、DNP3 对象组、AArch32 向量表
- **变异测试**:六处写回旧表述后对应断言全部失败(ARM 那条按上文重做后失败),还原后全过
- `npm test`:`OK: 122 skills validated` + **132 项测试全过**(上轮 126 + 新增 6)
---
## 补充 33:监控报告对账波——95 条逐条判定(2026-09-30)
### 一、本轮不是修,是判
2026-09-12 至 09-29 的外部监控累计报出 121 条。对账:**30 条已修、91 条未修**,未修部分自 09-24 起
再未进入审查流程(补充 32 是上一波,止于 09-23)。本轮把其中 95 条(91 未修 + 5 已修交叉验证)
**逐条判定「报告本身对不对」**,产出判定表 `docs/audit/2026-09-30-adjudication.md`。
| 判定 | 条数 |
|---|---|
| 采纳(报告成立) | 70 |
| 部分成立(改措辞不推翻原文) | 9 |
| **驳回(报告不成立,不改)** | **11** |
| 已修(无需判定) | 5 |
**驳回率 11.6%**——若不设这道闸口而直接照报告修,会把 11 处正确内容改错。
### 二、驳回的 11 条及其形态
5 条属「把可辩护的措辞当成事实错误」,且都集中在两处公式类指控上:
- **`ET_DYN` 的 `e_entry`(F036/F047/F069/F110,同句重复上报 4 次)**:报告称「相对基址的偏移」是
把 VA 写成 RVA 的事实错误。反证:gABI ch5 定义 base address = 内存地址与文件虚拟地址之差,对
executable/shared object 是同一常量;Linux `fs/binfmt_elf.c:1245` 即 `e_entry = elf_ex->e_entry + load_bias;`
——DYN 下 `e_entry` 本就是相对 base 的值,仓库措辞与该模型一致,且从未称其为文件偏移。
- **`LC_MAIN.entryoff` 入口公式(F034)**:反证为 Apple `loader.h` 注释、dyld `MachOAnalyzer.cpp:627`
`startAddress = preferredLoadAddress() + mainCmd->entryoff`,并用 ld64.lld 造样本实测命中。
其余 6 条:`pwntools` 与 `Capstone`(把开发线/预发行当成已发行——PyPI 分别仍是 4.15.0 与 5.0.9)、
`re-riscv` 入口(该句本身已写明「动态链接程序先经 ld.so(PT_INTERP)」,`gdb starti` 实测证实)、
`re-exploit` 栈对齐(仓库「`call` 时 `$rsp % 16 == 0`」与 psABI 原文逐字对应,探针实测 `==8` 触发
`movaps` SIGSEGV)、udsoncan `ClientConfig`(补充 30 已驳回,本轮 venv 独立复跑再次确认)。
### 三、部分成立 9 条:事实层成立、定性偏高
共同形态是**报告给出的影响面大于实际**,改法为加限定语而非推翻原文。其中两条修正了报告未察觉的方向:
- **`re-format-elf` 的 `PT_GNU_STACK`**:报告只说「缺失 ⇒ dlopen EINVAL」过强;实测发现更准确的分层是
glibc `dl-load.c` 在缺 header 时取 `DEFAULT_STACK_PROT_PERMS`(x86/x86-64/arm32 为 RWX、aarch64 等为 RW),
且 workaround 应为 `glibc.rtld.execstack=2` 而仓库写的 `=1` 实测失败
- **Canary 判定**:报告主张的假阴性不成立(grep 为子串匹配,strip 后仍命中),但假阳性成立
(`-static -fno-stack-protector` 的程序因 libc 自带 SSP 仍出现该符号)——报告建议的 `-Ws` 改法无效
### 四、采纳 70 条中的高影响项
- **QEMU 默认网络(`re-fw-emulate`)**:仓库把「不加网络参数」当作完全断网,实测 QEMU 11.1.1 默认创建
`type=user,net=10.0.2.0,restrict=off` + e1000 网卡。安全基线必须反转——不可信固件须显式 `-nic none`。
传播 8 处,其中 `references/commands.md:33` 最危险
- **IDA 9.x(F083)**:本机 9.4 安装目录无 `ida64`/`idat64`,64 后缀已取消,影响 15 处 / 5 文件
- **JNI 函数表(F120)**:解析 6 份头文件(JDK 8/11/17/27、GraalVM 21、NDK 30),`RegisterNatives`
恒为 index 215,表项只追加不重排;仓库 `probes.md` 的「槽号会漂移」与 `experience.md` 已写死的
`0x6b8(槽215)` 自相矛盾
- **TCP 流重组(F060)**:`re-proto-rev` 全流程把 segment payload 当应用层 message;实测 3 次连续
`send()` 在接收端合并为 1 个 chunk
- **binwalk(F005 等 4 条)**:PyPI 停在 2015 年的 2.1.0,upstream 已转 Rust 重写(v3.1.0),
README 安装走 Docker/Cargo/源码——仓库却把 pip 版写成「跨平台、版本新,推荐」
### 五、顺带实测出的、报告未提的两处
- `re-arm` 的变体误选判据:armv6m 下 `movw/movt` 报 `armv8m.base`、`clz/udiv` 报 `thumb2`,armv7m 正常
- `re-mips` 的 R6 描述:「MIPS32r6 起取消延迟槽」不准——R6 仍保留 BEQ/BNE/JALR/JR 的延迟槽,
删的是 branch-likely、新增的是 compact 无延迟槽形式
### 六、方法教训
- **「未修」≠「是缺陷」**:本轮 91 条未修项里 11 条经实测为报告错误。审查波若不设判定闸口、
直接按报告改,等于引入新缺陷
- **公式类指控需要三方交叉**:规范原文 + 上游实现源码 + 本机实测。两条公式类驳回都是这样定的,
单看规范措辞会误判
- **实跑不可替代**:构造 PNG 验证 `IEND` 搜索、连发 3 次 `send()` 看接收端合并、解析 6 份 `jni.h`
数槽位——这三条若只看报告措辞都会得出相反结论
---
## 补充 34:监控报告对账波落地(2026-10-05)
补充 33 的判定表把 95 条报告逐条定案(采纳 70 / 部分成立 9 / 驳回 11 / 已修 5)。本补充记录**落地**:
按 `docs/superpowers/plans/2026-09-30-factual-audit-wave.md` 的 17 个任务执行,改动落在 **55 个技能**上。
### 一、高影响修正
| 主题 | 原表述 | 改后 |
|---|---|---|
| **QEMU 网络(安全基线)** | 「qemu-user 无网络;qemu-system 默认 `-net none`」 | 实测 QEMU 11.1.1 不带网络参数会自建 `type=user,restrict=off` + e1000 网卡;改为「不可信固件必须显式 `-nic none`」,并补 qemu-user 不是网络沙箱。传播 8 处 |
| **IDA 9.x** | `idat`/`idat64` 分 32/64 位 | 9.x 已取消 64 后缀(本机 9.4 安装目录无该二进制),统一 `idat`,保留 ≤8.x 分支。传播 15 处 / 5 文件 |
| **JNI 函数表** | 「槽号随 jni.h/NDK/ART 漂移」 | 固定 index 215(解析 6 份头文件:JDK 8/11/17/27、GraalVM 21、NDK 30,表项只追加不重排);与同技能已写死的 `0x6b8(槽215)` 归一 |
| **TCP 流重组** | 把 segment payload 当应用层 message | 在流程中插入强制阶段「流重建 → framing」,示例改为 buffer parser;UDP 单独说明 |
| **binwalk** | pip 版「跨平台、版本新、推荐」 | PyPI 停在 2015 年的 2.1.0,upstream 已转 Rust v3;pip/发行版包标 legacy v2,v3 走官方 Docker/Cargo/源码 |
### 二、驳回项的守护
11 条驳回(e_entry / LC_MAIN 公式、SysV 栈对齐、RISC-V 入口、pwntools、Capstone、udsoncan)**未做任何修改**,
并在测试里加了**反向守护断言**——照报告去"修"会立刻红。
### 三、固化
- 回归断言 **+33**(`tests/audit-regressions.test.mjs` 78 项),覆盖采纳与部分成立的条目
- **变异测试**:抽查 4 条(Armv6-M 指令宽度、`LC_DYLD_INFO` 五组、unc0ver 版本、SysV 栈对齐守护),
写回旧表述后**全部精准失败**,还原后全过——断言不空转
- **补上测试计数的自校验**:`CLAUDE.md` 此前写「validate + 103 项测试」而实际已 168 项,与技能计数不同,
这一处无人看管。新增 `tests/counts.test.mjs` 的检查(顶层 `test(` 静态计数 == `node --test` 报告的 tests 数),
把这份人工清单也变成检查
- `npm test`:`OK: 122 skills validated` + **169 项测试全过**;`capindex --check` / `toollife check` /
`probelist --check` 均 OK;`auditstate` 回填 55 项后为「已复核未变 120|待复核 0」
### 四、方法教训:并行 agent 共用工作区的代价
本波用多个 subagent 并行执行 17 个任务,全部在**同一个工作区与 git index** 上操作,暴露了几类问题:
1. **裸 `git commit` 会卷走他人暂存的文件**——`git add <自己的文件>` 后直接 commit,会把并行 agent 已暂存的
文件一并提交,造成提交信息与内容不符。改用 `git commit -m "..." -- <paths>` 后消除。
2. **`git reset --soft` 差点造成数据丢失**——有一次连续两次 `reset --soft HEAD~1`,把恰好夹在中间的、
**另一个 agent 已完成的提交**一起摘掉了。内容靠 index 里残留的暂存态侥幸保住,靠 `git reflog` 定位并恢复。
教训:共享工作区里**禁止任何历史改写操作**,`rebase`/`amend`/`reset` 一律不许。
3. 状态台账(`review-state.json`)是共享文件,并行任务各自 `auditstate update` 会互相卷入;
收尾统一回填一次才是正确做法。
**净结论**:并行提速有效,但代价是协调开销与上述三类风险;若再来一轮,应给每个 agent 独立 worktree,
或把提交动作串行化到单一执行者。