reverse-skills-max: initial public release (restored, redacted, hardened)

This commit is contained in:
baradok609hecl1pq6qi
2026-10-20 02:17:15 +03:00
commit da24c2bd20
2227 changed files with 443931 additions and 0 deletions

View File

@@ -0,0 +1,602 @@
import { test } from 'node:test';
import assert from 'node:assert/strict';
import { readFileSync, existsSync } from 'node:fs';
// 审查记录的回归断言:把「已修的事实性缺陷」变成永久检查。
// 价值有两层——① 复核(确认修正确实落地)② 防回归(日后有人重写技能时,不会把错的说法写回去)。
// 每条对应 docs/audit/2026-09-13-factual-audit.md 的一个编号。
const S = '.claude/skills/';
const read = (p) => readFileSync(S + p, 'utf8');
// 「提到错误写法」与「把错误写法当对的用」是两回事——技能里的迁移说明会刻意写出旧写法
// (如"旧写法 Module.findExportByName(null, n) 已移除")。因此断言只认**非否定语境**下的出现。
const NEGATION = /已移除|已废弃|弃用|无此|没有|不再|不是|勿用|不应|错误|旧写法|过时|不携带|不具备|不支持|不存在/;
/** 断言:这些串不该再以"正确写法"的身份出现 */
function absent(t, file, needles, note) {
const lines = read(file).split('\n');
const hit = [];
for (const n of needles) {
const offenders = lines.filter((l) => l.includes(n) && !NEGATION.test(l));
if (offenders.length) hit.push(`${n}(${offenders.length} 处,如:${offenders[0].trim().slice(0, 70)})`);
}
assert.deepEqual(hit, [], `${file} 仍把已修正的错误表述当作正确写法(${note})`);
}
/** 断言:文件里应出现这些串(修正后的表述) */
function present(t, file, needles, note) {
const text = read(file);
const miss = needles.filter((n) => !text.includes(n));
assert.deepEqual(miss, [], `${file} 缺少修正后的表述(${note}):${miss.join(' / ')}`);
}
test('#1/#2 re-android-crypto:KeyInfo 的 API 用对', () => {
const f = 're-android-crypto/SKILL.md';
absent(null, f, ['getKeyAlias'], 'KeyStore 无此方法');
present(null, f, ['getSecurityLevel'], 'API 31+ 判安全等级');
});
test('#3 re-macos:Secure Enclave 密钥不能用导入 API', () => {
const f = 're-macos/SKILL.md';
present(null, f, ['SecKeyCreateRandomKey'], 'SE 密钥只能设备内生成');
});
test('#4 re-ai-model:Safetensors 头长度是小端', () => {
const f = 're-ai-model/SKILL.md';
absent(null, f, ['大端 u64 头长度'], '字节序反了');
present(null, f, ['<Q'], '小端解析');
});
test('#5/#6/#7 re-mobile-forensics:备份索引是 Manifest.db、fileID 由路径派生、IsEncrypted 判加密', () => {
const f = 're-mobile-forensics/SKILL.md';
present(null, f, ['Manifest.db'], '文件索引在 SQLite');
present(null, f, ['IsEncrypted'], '加密判定读 Manifest.plist 的该键');
});
test('#8 re-riscv:QEMU virt 的 reset 向量在 MROM 0x1000', () => {
const f = 're-riscv/SKILL.md';
present(null, f, ['0x1000'], 'MROM 地址');
present(null, f, ['0x80000000'], 'DRAM 基址(stub 跳转目标)');
});
test('#9 re-dotnet:EntryPoint 是 union,不总是 RVA', () => {
const f = 're-dotnet/SKILL.md';
present(null, f, ['EntryPointToken'], 'union 写法');
present(null, f, ['COMIMAGE_FLAGS_NATIVE_ENTRYPOINT'], '按标志位决定解释');
});
test('#10 re-automotive:candump 的过滤语法与写文件是两件事', () => {
const f = 're-automotive/SKILL.md';
present(null, f, ['candump can0,7E0:7FF'], '过滤在接口名后的逗号位');
absent(null, f, ['candump can0 -f 0x7E0'], '-f 是写文件,不是过滤');
});
test('#11 re-forensics:gcore 产物走进程级复盘,不走 Volatility 整机路径', () => {
const f = 're-forensics/SKILL.md';
present(null, f, ['gcore'], '分流说明应保留');
});
test('#12 re-ai-model:ONNX 起始字节不是固定 signature', () => {
const f = 're-ai-model/SKILL.md';
present(null, f, ['ir_version'], '首字段是 ir_version,随版本递增');
});
test('#13 re-dotnet:版本串是典型默认值,不是不变量', () => {
const f = 're-dotnet/SKILL.md';
absent(null, f, ['产物恒定'], '不应作恒定断言');
});
test('#14 re-macos:可访问性与访问控制是两个属性', () => {
const f = 're-macos/SKILL.md';
present(null, f, ['kSecAttrAccessControl'], '访问控制是它,不是 kSecAttrAccessible');
});
test('#15 re-mem-forensics:volatility3 只要求 Python 3.8+,无 3.11 上限', () => {
const f = 're-mem-forensics/SKILL.md';
absent(null, f, ['Python 3.8-3.11'], '官方无该上限');
});
test('#16 高熵不等于加密(ransomware 与 proto-rev 两处)', () => {
const r = read('re-ransomware/SKILL.md');
assert.ok(!/>7\.0 已加密/.test(r), 're-ransomware 不应把高熵当加密判定');
const p = read('re-proto-rev/SKILL.md');
assert.ok(!/几乎肯定加密/.test(p), 're-proto-rev 不应出现"几乎肯定加密"');
});
test('#17 Frida 17:静态查找/枚举 API 已移除,须用模块实例方法', () => {
const files = [
're-frida/SKILL.md', 're-frida/references/frida-scripts.md',
're-android-native/SKILL.md', 're-android-native/references/probes.md',
're-crypto-id/SKILL.md', 're-ios-jb/SKILL.md', 're-flutter/SKILL.md',
're-address-space/SKILL.md',
];
const offenders = [];
for (const f of files) {
if (!existsSync(S + f)) continue;
const lines = read(f).split('\n');
for (const bad of ['Module.findExportByName(', 'Module.getExportByName(', 'Module.findBaseAddress(']) {
const badLines = lines.filter((l) => l.includes(bad) && !NEGATION.test(l));
if (badLines.length) offenders.push(`${f}: ${bad}(${badLines[0].trim().slice(0, 70)})`);
}
}
assert.deepEqual(offenders, [], `仍在使用 Frida 17 已移除的静态 API:\n${offenders.join('\n')}`);
});
test('#18 re-frida-script-author:改返回值必须用 onLeave 的 retval.replace', () => {
const f = 're-frida-script-author/SKILL.md';
present(null, f, ['retval.replace'], 'onLeave 的 retval 才是改返回值的入口');
absent(null, f, ['this.returnValue'], '`this` 上没有 returnValue');
});
test('#19 re-ics:scapy Modbus 字段名是 camelCase startAddr', () => {
const f = 're-ics/SKILL.md';
present(null, f, ['startAddr'], 'scapy 定义的字段名');
absent(null, f, ['start_addr='], '下划线写法在 scapy 上不成立');
});
test('#20 re-angr:9.2.x 不是固定 Python 区间', () => {
const f = 're-angr/SKILL.md';
absent(null, f, ['支持 Python 3.8–3.11', '支持 Python 3.8-3.11'], '下限随补丁版本抬高');
present(null, f, ['requires-python'], '以目标版本元数据为准');
});
test('#21 re-ios-jb:读 C 字符串是 NativePointer 实例方法', () => {
const f = 're-ios-jb/SKILL.md';
absent(null, f, ['Memory.readCString'], 'Memory 下无此方法');
});
test('补充 22:analysis-contract 的 ELF 魔数表述与字节序正确', () => {
const f = 're-analyze/references/analysis-contract.md';
const text = read(f);
assert.ok(text.includes('7f 45 4c 46'), '应给出字节序列');
assert.ok(text.includes('0x464c457f'), '小端 u32 读法');
assert.ok(!/小端读作 0x7f454c46/.test(text), '旧表述把大端读法写成了小端');
assert.ok(!text.includes('0x202'), '最初的错误值不应复现');
});
test('补充 22:system-fingerprints 的 FreeBSD 标识是 .note.tag', () => {
const f = 're-analyze/references/system-fingerprints.md';
const text = read(f);
assert.ok(text.includes('.note.tag'), '现代 FreeBSD 由 crtbrand.S 生成 .note.tag');
assert.ok(!text.includes('`.note.ABI-tag`(FreeBSD)'), '不应把 note type 与 section name 混写');
});
test('补充 22:ET_REL 不单独断定 Linux 内核模块', () => {
const f = 're-analyze/references/system-fingerprints.md';
const text = read(f);
assert.ok(!/ET_REL\s*\*\*\s*→.*Linux 内核模块/s.test(text) || !/\[强\]\s*Linux 内核模块/.test(text),
'ET_REL 只说明"可重定位 ELF",需组合判据才升 Linux kmod');
});
test('补充 28:Mach-O 基础常量表与 Apple 头文件一致', () => {
const f = 're-format-macho/references/layout.md';
const text = read(f);
// 旧的错误表述不得复现
assert.ok(!text.includes('0x0100000B=arm64e'), 'arm64e 的 cputype 不是 0x0100000B');
assert.ok(!text.includes('0x80000003=x86_64h'), '0x80000003 是 ALL+LIB64 位,不是 x86_64h');
assert.ok(!/4=TWOLEVEL/.test(text), 'TWOLEVEL 是 0x80 不是 4');
assert.ok(!/0x800000=LAZY_INIT/.test(text), '0x800000 是 HAS_TLV_DESCRIPTORS');
assert.ok(!/0x0F=N_UNDF/.test(text), '0x0f = N_SECT|N_EXT');
assert.ok(!/LE 文件字节 be ba fe ca/.test(text), 'fat 恒为大端,文件开头是 CA FE BA BE');
assert.ok(!/offset 为 4 字节对齐的绝对文件偏移/.test(text), 'align 是 2 的幂,不是固定 4 字节对齐');
// 修正后的取值应在文中
for (const s of ['0x0100000C', 'ARM64E', '0x40', 'TWOLEVEL', '0x800000', 'N_SECT', 'CA FE BA BE', '2 的幂']) {
assert.ok(text.includes(s), `缺少修正后的表述:${s}`);
}
});
test('补充 28:udsoncan 示例带 config 的 data_identifiers', () => {
const f = 're-automotive/SKILL.md';
const text = read(f);
assert.ok(text.includes('data_identifiers'), 'DID 解码依赖配置里的 codec 映射');
assert.ok(text.includes('config=config'), '示例必须把 config 传给 Client');
assert.ok(!/with Client\(conn, request_timeout=2\) as client/.test(text), '不带 config 的旧示例会解码失败');
});
test('补充 27:re-flutter 的 Dart 格式 magic 是数值不是 ASCII 串', () => {
const f = 're-flutter/SKILL.md';
absent(null, f, ['"KERNEL" magic'], 'KERNEL 不是 magic(正确写法是数值 0x90abcdef)');
present(null, f, ['0x90abcdef'], 'kernel magic 实为该数值');
present(null, f, ['0xdcdcf5f5'], 'snapshot magic 实为该数值');
absent(null, f, ["b'SNAPSHOT'"], '快照头里没有 ASCII SNAPSHOT');
absent(null, f, ['版本串 12B'], '不存在固定 12 字节版本串');
});
test('补充 27:re-flutter 的 Profile 属 AOT 一侧', () => {
const f = 're-flutter/SKILL.md';
absent(null, f, ['kernel_blob 只在 debug/Profile 构建存在'], 'Profile 用的是 AOT');
present(null, f, ['Profile 与 Release 都是 AOT'], '执行模型划分');
});
test('补充 27:不写死 IDA Free 的版本代际', () => {
const f = 're-analyze/references/preferences.md';
absent(null, f, ['当前 8.x'], '版本代际会漂移');
});
test('补充 27:mitmproxy 的 Python 下限为 3.12', () => {
const f = 're-netcap/SKILL.md';
present(null, f, ['Python >=3.12'], '当前 12.x 的要求');
absent(null, f, ['(Python 3.10+)'], '旧的 Python 下限');
});
test('补充 27:angr 的 Python 版本矩阵只维护一处(re-angr)', () => {
const f = 're-exploit/SKILL.md';
absent(null, f, ['9.x 支持 Python 3.9–3.11'], '与 re-angr 冲突的旧矩阵');
present(null, f, ['[[re-angr]]'], '指向唯一事实源');
});
test('补充 32:Python 版本下限与无 pin 安装一致(torch/protobuf/web3)', () => {
absent(null, 're-ai-model/SKILL.md', ['Python 3.9+'], 'torch 当前要求 >=3.10');
present(null, 're-ai-model/SKILL.md', ['>=3.10'], 'torch 下限');
absent(null, 're-ai-model/SKILL.md', ['(Python 3.8+,onnx'], 'protobuf 当前要求 >=3.10');
absent(null, 're-blockchain/SKILL.md', ['Python 3.8+'], 'web3 8.x 要求 >=3.10');
present(null, 're-blockchain/SKILL.md', ['7.x'], '3.8/3.9 需 pin 的出路');
});
test('补充 32:angr 的 Python 矩阵只在 re-angr 维护一处', () => {
const f = 're-crypto-decrypt/SKILL.md';
absent(null, f, ['(Python 3.8+,依赖多'], '与 re-angr 冲突的旧副本');
present(null, f, ['[[re-angr]]'], '指向唯一事实源');
});
test('补充 32:attach 失败不得直接判成 PPL,内核调试不是唯一手段', () => {
const f = 're-anti-cheat/SKILL.md';
absent(null, f, ['内核调试是分析反作弊驱动的唯一动态手段', '唯一可用的动态手段',
'反作弊驱动用 PPL(Protected Process Light)保护游戏与自身进程'], 'PPL 是 Windows 的机制,不由反作弊驱动"设定"');
present(null, f, ['ProcessProtectionLevelInfo', 'PROTECTION_LEVEL_NONE'], '先查真实 protection level');
present(null, f, ['ObRegisterCallbacks'], '普通进程 attach 失败的替代解释');
});
test('补充 32:Zig 普通函数不是默认 C ABI', () => {
const files = ['re-zig/SKILL.md', 're-zig/references/layout.md'];
const bad = [];
for (const f of files) {
const lines = read(f).split('\n');
for (const l of lines) {
if (/默认调用约定即 C ABI|为默认.*x86-64 SysV|调用约定:默认 C ABI/.test(l) && !/只在|不是|仅/.test(l)) {
bad.push(`${f}: ${l.trim().slice(0, 80)}`);
}
}
}
assert.deepEqual(bad, [], '普通 Zig fn 用 Zig 默认约定,只有 extern/export/callconv(.c) 才是 C ABI');
present(null, files[0], ['extern'], 'C ABI 边界的来源');
present(null, files[1], ['callconv(.c)'], '显式要求 C 约定');
});
test('补充 32:DNP3 组 3 是静态双位输入,不是事件', () => {
const f = 're-ics/SKILL.md';
absent(null, f, ['组 3 事件'], '组 3 = Double-bit Binary Input(静态);其事件对象是组 4');
present(null, f, ['Double-bit Binary Input'], '正确的对象名');
present(null, f, ['组 4'], '配对的静态/事件关系');
});
test('补充 32:AArch32 的 8 项向量表不得泛化到整个 Cortex-A', () => {
const f = 're-arm/SKILL.md';
const lines = read(f).split('\n');
const bad = lines.filter((l) => l.includes('异常向量表 8 项') && !/AArch32|Armv7/.test(l));
assert.deepEqual(bad, [], 'AArch64 用 VBAR_ELx + 16×0x80,不存在固定 8 项表');
present(null, f, ['AArch32', 'AArch64'], '两套异常模型必须分开写(缺一侧则等于把结论删掉而非改正)');
present(null, f, ['VBAR_EL', '0x80'], 'AArch64 向量表的基址寄存器与槽位步长');
present(null, f, ['vbar_el1'], '定位异常表的线索(MSR VBAR_ELx 序列)');
});
test('补充 31:RISC-V Float ABI 以 e_flags 判定,不用浮点指令反推', () => {
const f = 're-riscv/SKILL.md';
absent(null, f, ['混编软/硬浮点编译单元时按单元确认'], 'linker 会直接拒绝不同 Float ABI 的输入');
present(null, f, ['EF_RISCV_FLOAT_ABI'], '以 e_flags 掩码判定');
present(null, f, ['cannot link object files with different floating-point ABI'], '链接期实际行为');
present(null, f, ['mabi=lp64'], 'ISA 扩展与调用约定是两件事的反例');
});
test('补充 31:re-arm 不得用浮点指令频率佐证 float ABI(同型缺陷)', () => {
const f = 're-arm/SKILL.md';
absent(null, f, ['vcmp/vcvt 等浮点指令出现频率佐证'], 'softfp 即反例:有 VFP 指令但参数仍走 r0-r3');
present(null, f, ['softfp'], 'softfp 的定位必须写明');
present(null, f, ['浮点指令出现频率不能佐证'], '修正后的表述');
});
test('补充 31:pwntools 的 Python 兼容矩阵只维护一处', () => {
const e = 're-exploit/SKILL.md';
absent(null, e, ['Python 3.8+'], '与 re-pwn 冲突的旧表述');
present(null, e, ['[[re-pwn]]'], '指向唯一事实源');
const p = 're-pwn/SKILL.md';
present(null, p, ['pwntools==4.15.0'], '旧环境需 pin');
present(null, p, ['最后一个支持'], '迁移窗口说明');
});
test('补充 30:PT_LOAD 不得表述成"唯一被映射的段类型"', () => {
const f = 're-format-elf/references/layout.md';
const lines = read(f).split('\n');
const offenders = lines.filter((l) => l.includes('唯一被映射') && !/不要|不是|不能|而非/.test(l));
assert.deepEqual(offenders, [], 'ELF gABI 只规定 PT_LOAD 是 loadable segment;PT_PHDR 同样描述内存映像中的位置');
present(null, f, ['loadable segment'], '应保留 loadable segment 的定位');
present(null, f, ['PT_PHDR'], '反证应写明');
});
test('补充 30:PT_GNU_STACK 缺失不得一律判定为可执行栈', () => {
const f = 're-format-elf/references/layout.md';
const lines = read(f).split('\n');
const offenders = lines.filter(
(l) => /缺失.*假定可执行|缺失\s*=\s*可执行栈|缺失.*= *可执行/.test(l) && !/不能|依目标|而异|不可/.test(l)
);
assert.deepEqual(offenders, [], '缺失 PT_GNU_STACK 的默认策略依目标 ABI/内核而异,不存在统一规则');
present(null, f, ['存在时'], '存在与缺失两种情形必须分开写');
present(null, f, ['READ_IMPLIES_EXEC', 'x86-64', 'ia32'], '跨架构差异(ia32 缺失才走 RIE)');
});
test('补充 30:udsoncan 示例保留"部分配置可用"这一已实测事实', () => {
const f = 're-automotive/SKILL.md';
// 这条对应一次**被驳回的报告**:报称示例里 ClientConfig() 会让 import/实例化失败,实测均不成立
//(client.py 运行时 import 了 ClientConfig;TypedDict 实例化得空 dict;refresh_config 会补齐缺键)。
// 断言的作用是把这个已核事实钉住,防止日后被"修"成别的说法。
present(null, f, ['default_client_config'], 'Client 会用默认配置补齐缺键(实测 1.26.1)');
present(null, f, ['ConfigError'], '未配该 DID 的失败签名(发送前抛出)');
present(null, f, ['DidCodec'], 'codec 必须是 DidCodec 实例');
});
test('补充 29:re-apk 的 apktool 版本模型是 3.x 主线 / 2.x 维护线', () => {
const g = 're-apk/references/gotchas.md';
present(null, g, ['3.x 为当前主线', '2.x 为维护线'], '版本模型');
present(null, g, ['--all-src'], '取代 --only-main-classes 的选项');
present(null, g, ['--aapt'], '3.x 的 aapt2 二进制入口');
present(null, g, ['Unrecognized option'], '旧短参在 3.x 的失败表现');
present(null, 're-apk/SKILL.md', ['3.x 为当前主线'], '工具准备段须先定 major version');
});
test('补充 29:apktool 调用行里不得残留 2.x 专有选项', () => {
// 迁移说明会**刻意引用**旧写法("--use-aapt2 已移除"),因此只查"像命令一样写出来"的行;
// 判据是行内出现 apktool d/b 调用,且整行不在迁移语境里。
const MIGR = /移除|消失|取代|不再|没有|无此|旧写法|过时|改用|2\.x|须写/;
const BANNED = ['--use-aapt2', '--use-aapt1', '--api-level', '--only-main-classes'];
const files = ['re-apk/SKILL.md', 're-apk/references/gotchas.md', 're-apk/references/commands.md'];
const bad = [];
for (const f of files) {
for (const l of read(f).split('\n')) {
if (!/\bapktool\s+[bd]\b/.test(l) || MIGR.test(l)) continue;
for (const opt of BANNED) if (l.includes(opt)) bad.push(`${f}: ${l.trim().slice(0, 90)}`);
}
}
assert.deepEqual(bad, [], `apktool 调用行里仍有 2.x 专有选项:\n${bad.join('\n')}`);
});
test('补充 29:apktool 的 --api-level 不得写成可用选项', () => {
const files = ['re-apk/SKILL.md', 're-apk/references/gotchas.md', 're-apk/references/commands.md'];
const offenders = [];
for (const f of files) {
for (const l of read(f).split('\n')) {
if (l.includes('--api-level') && !/移除|不再|消失|没有|无此|旧写法|过时/.test(l)) {
offenders.push(`${f}: ${l.trim().slice(0, 90)}`);
}
}
}
assert.deepEqual(offenders, [], '--api-level 在 apktool 3.x 已移除(API 等级不再由命令行指定)');
});
test('补充 29:不再支持 32 位的表述与 2.x 的 _64 后缀命名一致', () => {
const g = 're-apk/references/gotchas.md';
present(null, g, ['32 位'], '3.x 无 32 位产物');
assert.ok(!/老环境用 `aapt`(34 前默认).*apktool/.test(read(g)), 'aapt 与 apktool 的版本线不得混写');
});
test('补充 23:re-angr 的 recv hook 返回值是长度不是指针', () => {
const f = 're-angr/SKILL.md';
present(null, f, ['ssize_t'], '返回值语义');
absent(null, f, ['hook 返回符号指针'], '旧写法会把控制流建歪');
});
// ===== 补充 34:监控报告对账波落地(2026-10-05)=====
// 对 95 条外部报告逐条判定后采纳 70 条。下列断言锁住修正后的表述,防止日后重写时把错的说法写回;
// 文件末尾另有「驳回项守护」——那 11 条经实测判定为报告有误,仓库原表述是对的,不得被"修"错。
test('补充 34:Ghidra 版本不再钉死 patch 号', () => {
const f = 're-ghidra/SKILL.md';
absent(null, f, ['2026-08 最新 12.1.3'], '易腐化的版本写法');
present(null, f, ['12.x 为当前主线'], '改为以官方 Releases 为准');
});
test('补充 34:angr 主线已到 10.x(不再是 9.3.x)', () => {
const f = 're-angr/SKILL.md';
absent(null, f, ['最新 9.3.x 线'], '9.3.x 已不是主线');
present(null, f, ['10.x'], '当前主线');
});
test('补充 34:binwalk 的 pip 渠道标为 legacy v2,v3 走官方安装方式', () => {
const f = 're-fw-extract/SKILL.md';
absent(null, f, ['版本新、签名库全'], '把 2015 年的 pip 包说成"版本新"');
present(null, f, ['legacy', 'v3'], 'v2 遗留 / v3 主线要分清');
});
test('补充 34:rizin 的 apt 安装不得再作为可用安装方式(副本技能)', () => {
const files = [
're-variant/SKILL.md', 're-patching/SKILL.md', 're-license/SKILL.md',
're-imports/SKILL.md', 're-deobfuscate/SKILL.md', 're-unpack-advanced/SKILL.md',
];
// 提醒「apt 装不上」是允许的写法,只禁把 apt 当作可用安装方式
const offenders = [];
for (const f of files) {
for (const l of read(f).split('\n')) {
if (l.includes('apt install rizin') && !/会失败|无 rizin|无包|不再|不是|旧写法|勿用/.test(l)) {
offenders.push(`${f}: ${l.trim().slice(0, 90)}`);
}
}
}
assert.deepEqual(offenders, [], 'Debian/Ubuntu 仓库无 rizin 包,apt 装不上');
present(null, files[0], ['re-radare2'], '安装矩阵应指向单一事实源');
});
test('补充 34:QEMU 默认网络是 user 后端不是断网(安全基线)', () => {
const files = ['re-fw-emulate/SKILL.md', 're-fw-emulate/references/commands.md', 're-fw-emulate/references/gotchas.md'];
for (const f of files) absent(null, f, ['默认 `-net none`', '默认无网络'], 'QEMU 不加参数会自建 NIC + user 后端');
present(null, files[1], ['-nic none'], '不可信固件必须显式断网');
});
test('补充 34:IDA 9.x 无 64 后缀(无头统一 idat)', () => {
const f = 're-ida/SKILL.md';
absent(null, f, ['idat64(64 位无头)'], '9.x 已取消 64 后缀二进制');
present(null, f, ['idat'], '以 idat 为基线');
});
test('补充 34:JNIEnv 槽位是固定 ABI(RegisterNatives = 215)', () => {
const f = 're-android-native/SKILL.md';
absent(null, f, ['槽号是易变参数'], '槽位是 JNI ABI 固定布局');
present(null, f, ['215'], 'RegisterNatives 的规范 index');
present(null, 're-android-native/references/probes.md', ['215'], '探测层也不得再写"槽号随头文件漂移"');
});
test('补充 34:eBPF helper 号是 UAPI 稳定编号,不"漂移"', () => {
const f = 're-ebpf/SKILL.md';
absent(null, f, ['随内核版本增删漂移'], '已有 ID 不随内核重编号');
present(null, f, ['稳定'], '编号稳定性');
});
test('补充 34:Delphi 经典 VMT 负偏移(vmt-0x20 一类写法已纠正)', () => {
const f = 're-format-pe/SKILL.md';
absent(null, f, ['vmt-0x20'], '原值落进了 TObject 虚方法槽区');
present(null, f, ['-0x3C'], '经典 Win32 的 TypeInfo 偏移');
});
test('补充 34:Itanium typeinfo 布局按指针宽度,不写死 64 位', () => {
const f = 're-cpp-abi/SKILL.md';
absent(null, f, ['首 8 字节 vptr'], '32 位下为 +0/+4');
present(null, f, ['pointer-sized'], 'vptr 后接一个指针宽度的槽');
});
test('补充 34:lambda closure type 不是"无 RTTI"', () => {
const f = 're-cpp-abi/SKILL.md';
absent(null, f, ['lambda 无 RTTI'], '缺 _ZTI 既不能排除也不能反推');
present(null, f, ['_ZTI'], '按 mangling/捕获布局识别');
});
test('补充 34:DT_SYMENT 不硬编码 24(ELF32 为 16)', () => {
const f = 're-format-elf/SKILL.md';
absent(null, f, ['DT_SYMENT`(24 字节/条)'], '只对 ELF64 成立');
present(null, f, ['ELF32'], '按目标 class 取步长');
});
test('补充 34:.fini_array 在退出阶段执行,不与 .init_array 同时机', () => {
const f = 're-format-elf/SKILL.md';
absent(null, f, ['main 之前执行)'], 'fini_array 在 main 之后');
present(null, f, ['退出'], '退出清理阶段');
});
test('补充 34:缺 PT_GNU_STACK 的 workaround 是 execstack=2', () => {
const f = 're-format-elf/SKILL.md';
absent(null, f, ['rtld.execstack=1'], '=1 实测无效');
present(null, f, ['execstack=2'], '实测有效的取值');
});
test('补充 34:Mach-O 的 LC 最小长度是 8 字节不是 16', () => {
const f = 're-format-macho/SKILL.md';
absent(null, f, ['64 位下 LC 最小 16 字节'], 'load_command 头本身即 8 字节');
present(null, f, ['至少 8 字节'], '以结构体最小尺寸为准');
});
test('补充 34:LC_DYLD_INFO 是五组信息流(含 weak_bind)', () => {
const f = 're-format-macho/SKILL.md';
absent(null, f, ['四张表'], '漏了 weak_bind');
present(null, f, ['weak_bind'], '弱符号合并有独立语义');
});
test('补充 34:PIE 判定要看 DF_1_PIE,不能由 ET_DYN 直接推', () => {
const f = 're-triage/SKILL.md';
absent(null, f, ['ET_DYN=PIE'], '共享库同样是 ET_DYN');
present(null, f, ['DF_1_PIE'], 'readelf -d 的 FLAGS_1: PIE');
});
test('补充 34:TLS 1.3 的 ALPN 结果在 EncryptedExtensions', () => {
const f = 're-tls/SKILL.md';
present(null, f, ['EncryptedExtensions'], 'TLS 1.3 的落点');
});
test('补充 34:私有协议恢复必须先做 TCP 流重组', () => {
const f = 're-proto-rev/SKILL.md';
present(null, f, ['流重建'], 'segment payload ≠ 应用层 message');
});
test('补充 34:密文长度不能区分分组/流密码', () => {
const f = 're-crypto-id/SKILL.md';
absent(null, f, ['密文长度是块大小整数倍'], 'CTR/OFB 可产出与明文等长密文');
present(null, f, ['等长'], '长度只辅助判断 mode');
});
test('补充 34:zipalign 与签名方案的顺序关系', () => {
const f = 're-apk/references/gotchas.md';
absent(null, f, ['v1 签名需要 zipalign'], '用 apksigner 时必须先对齐后签名');
present(null, f, ['zipalign'], '把顺序要求写清');
});
test('补充 34:Armv6-M 有合法的 32 位编码(BL 不是幻觉)', () => {
const f = 're-arm/SKILL.md';
absent(null, f, ['只有 16 位 Thumb'], 'Armv6-M 含 32 位 BL/DMB/DSB/ISB/MRS/MSR');
present(null, f, ['Armv6-M'], '按具体 opcode 判定变体是否选错');
});
test('补充 34:MIPS 延迟槽要区分 Branch Likely 的 annul', () => {
const f = 're-mips/SKILL.md';
absent(null, f, ['无条件执行'], 'likely 分支 not-taken 时延迟槽被取消');
present(null, f, ['Branch Likely'], 'annul 语义');
});
test('补充 34:Game Boy 用 SM83,不是 Z80 变体', () => {
const f = 're-console/SKILL.md';
absent(null, f, ['Z80 变体'], 'SM83 与 Z80 不兼容');
present(null, f, ['SM83'], '专用 processor definition');
});
test('补充 34:unc0ver 的 iOS 版本范围', () => {
const f = 're-ios/references/gotchas.md';
absent(null, f, ['unc0ver(iOS 14-15 系)'], 'unc0ver 不支持 iOS 15');
present(null, f, ['11.0-14.8'], '实际支持范围');
});
test('补充 34:Frida host 与 frida-server 只需 major 一致', () => {
const f = 're-frida/SKILL.md';
absent(null, f, ['版本必须与主机 frida 完全一致'], '官方判据是 major 匹配 + 功能存在');
present(null, f, ['major'], '兼容判据');
});
test('补充 34:运行时基线不再是 EOL 的 Node 18', () => {
const pkg = JSON.parse(readFileSync('package.json', 'utf8'));
assert.ok(pkg.engines.node !== '>=18', 'engines.node 不得停留在已 EOL 的 18');
present(null, 're-crash-triage/SKILL.md', ['coredumpctl'], 'core 取回补全');
});
// ===== 驳回项守护(2026-10-05)=====
// 这 6 组经实测判定为「报告有误」,仓库原表述正确。照报告去"修"会把正确内容改错,
// 因此反向锁住:正确表述必须在位。(依据见 docs/audit/2026-09-30-adjudication.md 第四节)
test('驳回守护:ET_DYN 的 e_entry 措辞不得被改成"文件偏移"', () => {
const f = 're-format-elf/references/layout.md';
present(null, f, ['相对基址'], 'gABI ch5 的 base address 定义 + 内核 +load_bias 支持此措辞');
absent(null, f, ['e_entry 是文件偏移'], 'e_entry 从来不是文件偏移');
});
test('驳回守护:LC_MAIN 入口公式不得被改', () => {
const f = 're-format-macho/SKILL.md';
present(null, f, ['vmaddr'], 'Apple loader.h 与 dyld 源码均按 vmaddr + entryoff 计算');
});
test('驳回守护:x86-64 SysV 栈对齐表述不得被改', () => {
const f = 're-exploit/SKILL.md';
present(null, f, ['% 16 == 0'], 'psABI 原文即"call 指令执行前 16 字节对齐"');
});
test('驳回守护:pwntools 4.15.0 仍是当前正式版', () => {
present(null, 're-pwn/SKILL.md', ['4.15.0'], 'PyPI 至今无 5.x 发行版');
});
test('驳回守护:capstone 5.x 仍是稳定版', () => {
present(null, 're-emulation/references/gotchas.md', ['5.0'], '6.0.0 仅有预发行');
});
test('驳回守护:udsoncan 的 ClientConfig() 示例可运行,不得照报告改', () => {
present(null, 're-automotive/SKILL.md', ['ClientConfig'], 'TypedDict 实例化返回空 dict,refresh_config 补齐缺键');
});
test('补充 34:AI 模型格式信号以字节为准(实测 file(1) 输出)', () => {
const f = 're-ai-triage/SKILL.md';
// 实测:onnx/safetensors/tflite 三种样本 file(1) 都报 `data`;老式 pickle 被误报为 XENIX
absent(null, f, ['`08 08`'], 'onnx 第二字节随 ir_version 递增,不是常量');
present(null, f, ['TFL3'], 'tflite 的文件标识符在字节 4–7');
present(null, f, ['小端头长度'], 'safetensors 先 8 字节长度再 JSON');
present(null, f, ['XENIX'], '老式 pickle 的 file(1) 误报可作为识别线索');
});