reverse-skills-max: initial public release (restored, redacted, hardened)
This commit is contained in:
119
vendor-new/rev-skills/.claude/skills/re-variant/SKILL.md
Normal file
119
vendor-new/rev-skills/.claude/skills/re-variant/SKILL.md
Normal file
@@ -0,0 +1,119 @@
|
||||
---
|
||||
name: re-variant
|
||||
type: atomic
|
||||
description: >
|
||||
二进制变体/补丁对比:函数匹配、N-day 补丁 diff、变体溯源与相似度分析。
|
||||
触发词:二进制对比、补丁对比、N-day、变体分析、BinDiff、函数匹配、样本相似。
|
||||
capabilities: [binary-diffing]
|
||||
---
|
||||
|
||||
# 二进制变体/补丁对比
|
||||
|
||||
## 何时使用 / 何时不用
|
||||
|
||||
- 用:补丁前后对比(漏洞定位)、家族变体关联、样本溯源、N-day 分析
|
||||
- 用:同源代码复用识别(共享函数/库代码判断)
|
||||
- 用:修复覆盖审计——多分支版本逐一对比修复样本,核对哪些版本修了、哪些没修
|
||||
- 用:漏洞研究——修复前后结构与行为差异的完整还原(补丁 → 缺陷模式)
|
||||
- 不用:单样本深度分析(走 [[re-binary-core]] 通用路径)
|
||||
- 不用:无对比基线(只有单个样本、无第二版本可对比)——先走单样本路径
|
||||
- 不用:行为层面比较(动态行为差异走 [[re-behavior]];本技能只比静态代码结构)
|
||||
- 不用:需要语义级还原的对比(先 [[re-cpp-abi]] 还原 ABI/符号语义,再回到本技能做差异定位)
|
||||
|
||||
## 工具准备
|
||||
|
||||
### BinDiff / Diaphora(函数匹配插件)
|
||||
|
||||
- BinDiff(Google/Zynamics 系,Windows 商业工具,官方安装包):IDA 插件为主;BinDiff 6 起官方支持 Ghidra(需 BinExport 插件导出);BinExport 亦支持 Binary Ninja——导出格式可桥接多反编译器
|
||||
- Diaphora: 多平台开源(`git clone https://github.com/joxeankoret/diaphora`),IDA 插件为主(Ghidra 侧支持持续推进中)
|
||||
- 无 IDA 环境替代:qbindiff(Quarkslab,读 BinExport/quokka 导出)、ghidriff(headless Ghidra 对比)
|
||||
- 典型流程: 反编译器内 BinExport 导出 → 工具载入两样本 → 匹配 → 结果(相似度/变更集)导出为报告;BinExport 插件与反编译器版本需匹配(见 [[gotchas]])
|
||||
- 验证: 插件在反编译器内可加载,能导出/导入匹配结果
|
||||
|
||||
### radiff2 / rz-diff(rizin 命令行对比)
|
||||
|
||||
- 安装矩阵见 [[re-radare2]](含 radare2 兼容层),安装后以 `rizin -v` 验证
|
||||
- 验证: `rz-diff --version`;radiff2 随 radare2 包
|
||||
- 用途: 无 GUI 的快速函数级对比与批量脚本化(见步骤 1 命令);radiff2 做字节/指令级快查(`radiff2 -s` 字节、`-C` 指令)——小文件快查用,函数级对比用 rz-diff
|
||||
|
||||
### readelf(符号对齐辅助)
|
||||
|
||||
- 安装与验证见 [[re-cpp-abi]] 工具准备
|
||||
- 用途: `readelf -s`(符号表/动态符号)与 `readelf -d`(动态节)做导入导出对齐与配对核对
|
||||
|
||||
### 配对辅助(对比前置)
|
||||
|
||||
- 哈希/基线: `sha256sum`;架构/编译器判定: [[re-imports]] 导入表与工具链指纹——配对前先确认可比性(同架构/同工具链,见坑 1、3)
|
||||
- 验证: `sha256sum --version`
|
||||
- 壳检查: [[re-packer-id]] 识别加壳;加壳样本先脱壳([[re-unpack-simple]])再对比——壳代码会污染匹配(见 [[gotchas]] 反例组)
|
||||
|
||||
## 操作步骤
|
||||
|
||||
按顺序执行,每步产物存档(路径 + sha256,见 [[re-triage]]);最终差异清单按 [[re-analyze/analysis-contract]] 数据契约传递。
|
||||
|
||||
1. **配对准备(先确认可比性再对比)**:
|
||||
- 记录基线:两样本的 sha256、架构(x86_64/ARM 等)、位数、编译器指纹(版本字符串/导入库集合,[[re-imports]])
|
||||
- 可比性判定:同架构 + 同工具链 → 函数级全量匹配;跨架构/异编译器 → 降级为逻辑层对比(调用图/常量/字符串),标注局限
|
||||
- 位数/字节序:32/64 位混合或大小端混合不直接比——统一到同位数同字节序再匹配
|
||||
- 符号状态:strip/未 strip 决定匹配策略(未 strip 直接符号对齐,见步骤 2)
|
||||
|
||||
2. **函数匹配**:
|
||||
```sh
|
||||
# 命令行快速对比(rizin 系):函数级匹配(-B 自动分析后按函数对比,含相似度列)
|
||||
rz-diff -B -t functions sample_v1 sample_v2 | head -30
|
||||
```
|
||||
- 匹配维度:指令哈希(相同代码)、调用图(子图同构)、导入导出对齐、字符串/常量引用
|
||||
- 数据引用维度:全局常量/字符串引用作函数身份指纹——重构/重排后比指令哈希稳定,跨版本匹配的可靠锚点
|
||||
- 工具(BinDiff/Diaphora)输出:matched / changed / new / deleted 函数集
|
||||
- 输出解读:matched 相同、changed 变化、new/deleted 功能增减——changed 进步骤 3,new/deleted 提示功能面差异,逐类给后续动作
|
||||
- strip 后符号缺失:靠结构匹配(入口特征/调用模式/常量锚定)——匹配维度权重调整见坑 1 与 [[decision-tree]]
|
||||
- 地址差异处理:PIE/重定位后函数地址不同——按符号名/函数序对齐,不比裸地址(见坑 2)
|
||||
- 名称/注释迁移:工具支持把已命名函数的名称/注释迁移到匹配函数——已知样本先标注再对比,半自动还原新样本符号;迁移名称标注来源,仅作辅助锚点(见 [[gotchas]] 符号组)
|
||||
|
||||
3. **补丁 diff(N-day)**:
|
||||
- 修复前后对比 → `changed` 函数集 = 漏洞点候选
|
||||
- 变更函数按语义分类:新增校验/边界处理(高优先级)> 行为变化 > 纯重构(低优先级)——按类别排序候选([[decision-tree]] 分级)
|
||||
- 变更函数深挖:新条件分支/新校验/新增调用([[re-ghidra]] / [[re-ida]] 反编译)
|
||||
- 反推漏洞:旧代码的缺陷模式(缺失校验/越界/释放后使用)
|
||||
- 修复模式识别:常见修复模式(长度检查/空指针检查/越界上限收紧)与缺陷模式对应归类——按模式快速筛候选函数
|
||||
- 修复覆盖核对:多分支版本逐一对比修复样本,确认漏洞修复覆盖范围(哪些版本修了、哪些没修)
|
||||
- 产出:漏洞函数 + 缺陷模式推断(置信度标注,证据分级见 [[decision-tree]])
|
||||
|
||||
4. **变体溯源**:
|
||||
- 家族内样本两两对比 → 相似度矩阵 → 聚类(共享函数比例阈值)
|
||||
- 演进链:按时间线/相似度排序样本(早期 vs 晚期变体)
|
||||
- 共享独有函数 = 家族标志(与 [[re-attribution]] 能力证据衔接)
|
||||
- 独有函数判定:先算家族内共享集合,再取外族样本缺失的函数为家族标志——避免把通用代码当标志
|
||||
- 关联强度:共享独有函数数量 + 相似度分布综合判定,单项指标不做唯一依据
|
||||
- 样本量控制:家族样本多时两两矩阵 O(n²)——先按特征(架构/大小/导入集)粗聚类,再在簇内细比
|
||||
- 阈值校准:相似度分数先人工抽查校准再定聚类线(见坑 5),避免虚高关联
|
||||
|
||||
5. **输出差异清单与核查**:
|
||||
- 格式:变更函数表(函数名/地址/变更类型/相似度)+ 结论
|
||||
- 按 [[re-analyze/analysis-contract]] 数据契约传递(下游消费)
|
||||
- 防误报核查:排除共享库代码([[re-imports]] 依赖清单对照)、异编译器复检(同源码不同编译差异)、跨工具交叉验证([[decision-tree]] 分级)
|
||||
- 报告可复现:差异清单附工具与版本、相似度阈值、排除规则;重要结论存匹配导出文件 + 反编译人工复核记录
|
||||
|
||||
## 跨域联合
|
||||
|
||||
- [[re-binary-core]] 网关:本技能归属(选择树「补丁/N-day 对比」分支)
|
||||
- [[re-ghidra]] / [[re-ida]]:反编译底座(变更函数深挖)
|
||||
- [[re-attribution]]:变体关联的能力证据衔接
|
||||
- [[re-imports]]:导入表/工具链指纹(配对可比性与共享库排除)
|
||||
- [[re-cpp-abi]]:符号语义还原(语义级对比前置)
|
||||
- [[re-packer-id]] / [[re-unpack-simple]]:加壳样本先脱壳再对比(壳代码污染匹配)
|
||||
- [[re-analyze/analysis-contract]]:差异清单按数据契约传递
|
||||
|
||||
## 常见坑与陷阱
|
||||
|
||||
- **编译器差异干扰匹配**:现象——同源码不同编译器编译被判不相似;原因——优化/代码生成差异;对策——用调用图与常量引用加权,降低指令哈希权重
|
||||
- **strip 后符号缺失**:现象——函数名全无;原因——符号剥离;对策——结构匹配(入口特征/调用模式)、导入表锚定
|
||||
- **跨架构对比降级**:现象——x86 vs ARM 匹配率低;原因——指令集不同;对策——只比逻辑层(调用图/常量/字符串),标注跨架构局限
|
||||
- **大量相似导致误关联**:现象——共享库代码导致虚高相似度;原因——公共依赖(libc/框架);对策——排除共享库符号,只比业务代码([[re-imports]] 依赖对照)
|
||||
- **补丁 diff 定位偏差**:现象——changed 函数多,漏洞点被淹没;原因——补丁含重构;对策——按变更语义过滤(新增校验/边界处理优先)
|
||||
- **裸地址对比失效**:现象——同一函数被报为不同;原因——PIE/重定位/版本差异导致地址漂移;对策——按符号/函数序对齐,不比裸地址
|
||||
- **「没 diff 出来」≠「没修」**:现象——补丁对比无 changed 函数;原因——修复内联进相邻函数或跨函数重组;对策——扩大对比面(含内联展开后的指令哈希),结合版本历史核对
|
||||
- **名称迁移污染**:现象——新样本函数名看似已知;原因——迁移自匹配来源而非真实符号;对策——迁移名称标注来源,仅作辅助锚点,关键函数过反编译确认
|
||||
- **符号表被伪造**:现象——符号名齐全但结构对不上;原因——混淆/反分析工具改名(伪造符号);对策——符号对齐结果过结构确认(调用模式/常量),不信符号名本身
|
||||
- **只比 .text 的盲区**:现象——函数匹配全相同但行为不同;原因——数据段差异(配置/常量表)被排除在对比范围外;对策——数据引用维度纳入匹配,常量表/配置结构单独比对
|
||||
- 决策分支(可比性/匹配层级/候选排序)见 [[decision-tree]];匹配算法与工具边界见 [[gotchas]]
|
||||
@@ -0,0 +1,81 @@
|
||||
# 二进制变体/补丁对比决策树与证据分级
|
||||
|
||||
## 场景决策树(入口 → 分支)
|
||||
|
||||
### 1. 分析目标分支(第一级)
|
||||
|
||||
```
|
||||
目标
|
||||
├─ N-day 补丁定位(修复前后对比)→ 步骤 3:changed 集合 → 候选排序
|
||||
├─ 家族变体溯源 → 步骤 4:两两矩阵 → 聚类 → 演进链
|
||||
├─ 相似样本关联(这是不是同一个家族的)→ 共享函数比例判定
|
||||
└─ 共享代码识别(复用/借用判断)→ 独有函数 + 常量/字符串命中
|
||||
```
|
||||
|
||||
### 2. 可比性分支(第二级)
|
||||
|
||||
```
|
||||
配对输入
|
||||
├─ 同架构 + 同工具链 → 函数级全量匹配(指令哈希 + 调用图 + 常量)
|
||||
├─ 同架构 + 异编译器 → 降低指令哈希权重,调用图/常量为主(坑 1)
|
||||
├─ 跨架构 → 只比逻辑层(调用图/常量/字符串),标注跨架构局限
|
||||
└─ 符号状态
|
||||
├─ 未 strip → 符号对齐优先(快且准)
|
||||
└─ strip → 结构匹配(入口特征/调用模式/常量锚定)
|
||||
```
|
||||
|
||||
### 3. 匹配层级分支(第三级)
|
||||
|
||||
```
|
||||
匹配粒度
|
||||
├─ 函数级(默认)→ matched/changed/new/deleted 集合
|
||||
├─ 指令级 → 变更函数内逐指令 diff(改动点定位)
|
||||
├─ 结构级 → 调用图/数据引用对比(重排/合并检测)
|
||||
└─ 语义级 → 需先 [[re-cpp-abi]] 还原符号语义再比
|
||||
```
|
||||
|
||||
### 4. 候选排序分支(第四级,补丁 diff 时)
|
||||
|
||||
```
|
||||
changed 函数集
|
||||
├─ 新增校验/边界处理(if/长度/范围检查)→ 高优先级:漏洞点候选
|
||||
├─ 行为变化(调用新增/参数变化)→ 中优先级:功能变更/修复
|
||||
├─ 纯重构(等价重排)→ 低优先级:跳过或标注
|
||||
└─ 无 changed → 修复可能内联/跨函数重组(坑 7)→ 扩大对比面
|
||||
```
|
||||
|
||||
### 5. 结果核查分支(第五级)
|
||||
|
||||
```
|
||||
匹配结果
|
||||
├─ 跨工具一致(BinDiff + rz-diff 同结论)→ 直接采信
|
||||
├─ 冲突 → 人工抽查差异函数(反编译复核)
|
||||
├─ 相似度虚高 → 查共享库依赖([[re-imports]] 对照)排除
|
||||
└─ 阈值未校准 → 先人工抽查 10-20 个函数定阈值再批量
|
||||
```
|
||||
|
||||
## 证据分级表
|
||||
|
||||
| 级别 | 证据形态 | 示例 | 用途 |
|
||||
|---|---|---|---|
|
||||
| A 强 | 跨工具一致 + 反编译人工确认 | changed 函数差异点在反编译中确认语义(新增校验) | 可下「漏洞点/修复点」结论 |
|
||||
| B 中 | 单工具高相似 + 调用链闭合 | 函数相似度 > 阈值且调用关系对应 | 可下「高度疑似」 |
|
||||
| C 弱 | 特征级 | 仅字符串/常量命中、函数级匹配无闭合 | 只支持「关联候选」 |
|
||||
| 反证 | 良性解释 | 差异属重构/平台分支,无安全语义 | 记录并存档 |
|
||||
|
||||
- 缺陷模式推断(越界/缺失校验类)单独标注置信度,与「函数变更」事实分开陈述
|
||||
- 相似度分数是证据不是结论:分数本身不承载语义,人工复核后才定级
|
||||
|
||||
## 实现教训(内化)
|
||||
|
||||
- 先配对再对比:sha256/架构/工具链指纹先记录,可比性不成立时直接降级,别浪费全量匹配
|
||||
- 相似度阈值先校准:每个样本对集的人工抽查结果反推阈值,再定聚类线
|
||||
- 排除共享库是防虚高的第一道关:依赖清单([[re-imports]])先行,业务代码再比
|
||||
- 跨架构只比逻辑层:指令级对比在跨架构下无意义,标注局限
|
||||
- 补丁 diff 按变更语义排序而非相似度排序:新增校验/边界处理优先于重构类差异
|
||||
- 跨工具交叉验证:BinDiff 系与 rz-diff 结论一致时证据强度显著提升
|
||||
|
||||
## 使用注意
|
||||
|
||||
- 样本来源不可信时在沙箱内处理([[re-sandbox]]);对比属静态操作,动态确认走对应技能
|
||||
- 结论按本表分级标注,并注明工具版本与阈值(相似度分数、排除规则)
|
||||
@@ -0,0 +1,37 @@
|
||||
# 二进制变体/补丁对比方法论坑与边界
|
||||
|
||||
## 匹配算法组(误判来源)
|
||||
|
||||
- **指令哈希受编译差异影响**:同源码不同优化等级/编译器版本,指令级哈希就变——按指令哈希判「不同」不等于「逻辑不同」,权重低于调用图与常量
|
||||
- **调用图受内联/拆分影响**:编译器内联后函数边界漂移,调用图对比会拆错对应关系——匹配失败先怀疑内联,扩大匹配粒度或按常量锚定
|
||||
- **相似度分数不承载语义**:高分可能只是共享代码/模板实例化;低分也可能是被刻意改写的同源逻辑——分数只作排序依据,语义靠人工复核
|
||||
- **跨架构匹配率必然低**:指令集不同导致指令级维度全部失效——只比逻辑层(调用图/常量/字符串),并标注跨架构局限
|
||||
- **模板/泛型实例化干扰**:C++ 模板实例化的多个函数高度相似——按模板参数区分实例,避免把实例化当家族标志
|
||||
|
||||
## 符号与地址组
|
||||
|
||||
- **strip 后无符号锚点**:函数名全无时按入口特征/调用模式/常量匹配——错误率高,需阈值校准与人工抽查
|
||||
- **地址漂移别比裸地址**:PIE/ASLR/重定位/版本构建差异都会移动函数地址——按符号/函数序对齐;版本间比较先归一化节区布局
|
||||
- **符号名可能误导**:strip 不彻底的残留符号、伪造符号(混淆工具改名)会把不同函数粘在一起——符号对齐结果仍要过一遍结构确认
|
||||
- **导入表是稳定锚点但非全量**:导入函数对齐可靠,但内部函数不出现——导入对齐只作辅助维度,不能替代函数级匹配
|
||||
|
||||
## 工具差异组
|
||||
|
||||
- **BinDiff 与 Diaphora 算法不同,结果可能不一致**:匹配策略(指令哈希 vs 图同构的权重)不同——冲突时人工复核,一致性高时证据更强
|
||||
- **BinExport 版本与反编译器版本需匹配**:BinExport 插件与 IDA/Ghidra 版本严格绑定,版本错配导出失败或结果异常——先核对版本再导出
|
||||
- **rz-diff -B 消耗分析时间**:`-B` 先自动分析两个二进制(反汇编+函数识别),大文件耗时长——先用 `-t functions` 限定范围,大批量用脚本分批
|
||||
- **大二进制内存压力**:全函数图对比在超大二进制(内核/大型框架)上内存占用高——按节区(如 .text)分段对比,或增大工具内存
|
||||
- **qbindiff/ghidriff 的结果格式差异**:开源替代输出 CSV/BinDiff 格式不等——下游消费前统一格式(按 [[re-analyze/analysis-contract]])
|
||||
|
||||
## 反例与边界组
|
||||
|
||||
- **共享库虚高相似度**:两个无关样本都链接同一 libc/框架,共享函数比例虚高——排除共享库符号([[re-imports]] 依赖对照)再算相似度
|
||||
- **「没 diff 出来」≠「没修」**:修复可能内联进相邻函数、跨函数重组、或只改常量——扩大对比面(含内联展开)并核对版本历史
|
||||
- **changed 多 ≠ 漏洞多**:补丁常夹带重构/平台适配——按变更语义过滤(新增校验/边界处理优先),重构类排除
|
||||
- **变体「相似」≠「同源」**:同源代码跨编译器、跨平台重编译后相似度下降;刻意改写(加花指令/常量混淆)也降——溯源结论需多证据(时间线/独有函数/行为侧)闭合
|
||||
- **单工具结论不跨工具复现**:只用一个工具出的匹配,换工具可能完全不同——重要结论至少两个工具或人工复核
|
||||
|
||||
## 使用注意
|
||||
|
||||
- 样本来源不可信时在沙箱内处理([[re-sandbox]]);对比是静态操作,动态确认走对应技能
|
||||
- 结论按 [[decision-tree]] 分级标注,并注明工具版本、阈值与排除规则
|
||||
Reference in New Issue
Block a user