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,118 @@
---
name: re-ida
description: >
IDA 工作流:导入→FLIRT→Hex-Rays→idapython。
触发词:IDA、Hex-Rays、idapython
capabilities: [decompilation, debugging]
---
# IDA 逆向工作流
## 何时使用 / 何时不用
- 用:已有 IDA 授权/免费版,目标需要 FLIRT 库识别、Hex-Rays 反编译、idapython 批处理
- 用:大规模重复性标注/导出(无头批处理 `idat -A -S`,序列见 [[commands]])
- 不用:免费版无法处理时(无 Hex-Rays → 用 [[re-ghidra]] 兜底);只需快速结论([[re-triage]])
- 不用:内存受限环境(大二进制卡顿,换 [[re-radare2]]);纯命令行快速分析([[re-radare2]] 更轻)
- 不用:macOS/Linux 目标动态调试([[re-lldb]] / [[re-gdb]]);IDA 调试器只对 Windows 本地目标价值最大
## 工具准备
参考 [[re-analyze/platform-tips]]——静态分析免沙箱;用 IDA 调试器做动态调试时按最高原则默认沙箱执行。
### IDA(商业版 / 免费版)
- 下载: hex-rays.com(IDA Free 免费版,支持 x86/x64;其他架构与分析器需商业版)
- Windows: 安装程序直接运行;`choco install ida-free`(社区包,或官网手动下载)
- macOS/Linux: 官网 tar 包解压运行 `ida`(Windows 对应 `ida.exe`,无头用 `idat`/`idat.exe`)
- 验证: 启动后成功打开一个样本完成 auto-analysis,函数窗口有内容;`idat --help` 有输出;无头模式试跑 `idat -A -L"t.log" /bin/true` 能正常退出
- 版本差异: 7.5 起数据库统一 `.i64`(旧 `.idb`/`.idb64` 可升级);8.x 需 64 位宿主;9.0 起 32/64 位安装合一、内置 FLIRT 签名管理器、idalib 无头 API——**9.x 可执行文件不再带 64 后缀**(`ida`/`idat` 一个二进制同时处理 32/64 位),IDA ≤8.x 才分 `ida`/`ida64`、`idat`/`idat64`——详见 [[gotchas]]
### idapython(内置)
- IDA 6.8+ 内置 Python 环境,无需单独安装;IDA 9 用 `idapyswitch`(IDA 根目录)切换外部 Python(3.8–3.13)
- 验证: 菜单 `File > Script command`(Shift+F2)执行 `print(idaapi.IDA_SDK_VERSION)` 输出版本
### FLIRT 签名库
- IDA 自带 `sig/` 目录(flair),应用后自动标注库函数;IDA 9 的签名管理器可在线下载更多签名
- 验证: 对已知 libc 程序应用签名后,`_init`/`malloc` 等被标注为库函数
## 操作步骤
1. **导入与 auto-analysis**:
- `File > New` 选择样本 → 等左下角 `AU: analyzing` 结束(无 AU 字样且分析日志停止)
- 确认 `Options > General > Analysis` 中 Auto-analysis 开启;确认 `segments` 与 `entry point` 已识别
- 无头批处理: `idat -A -S"myscript.py" -L"log.txt" sample`(`-A` 自动模式,Windows 用 `idat.exe`)
- 无头脚本开头 `ida_auto.auto_wait()` 等分析完成、结尾 `idc.qexit(0)` 退出——缺这两行会拿到空函数列表或进程挂住
2. **FLIRT 识别库函数**:
- `File > Load file > FLIRT signature file...` 选择匹配的 `.sig`(MSVC 选 `mssdk`、`vc64rtf` 等;GNU 选 `libstdc++` 系列)
- 识别后库函数名自动应用,函数窗口内库函数(浅色)与用户函数分离——直接聚焦非库函数
- 匹配失败(加壳/混淆库)→ 说明壳或自定义编译,转 [[re-anti-analysis]]
3. **快捷键主线(静态分析日常)**:
- `x` 交叉引用;`n` 重命名(函数/变量);`y` 改类型(如 `int __cdecl f(int, char*)`);`;` 注释(repeatable 用 `:`)
- `G` 跳地址;`Alt+T` 文本搜索(字符串关键字);`Alt+B` 二进制搜索(字节模式);`Esc` 返回上级
- `F5` Hex-Rays 反编译;`Tab` 在伪代码/汇编视图间切换
- 完整快捷键与命令表见 [[commands]]
4. **Hex-Rays 反编译阅读**:
- `F5` 进伪代码:先读函数签名与局部变量,再沿调用链(双击 call 进入、`Esc` 返回)走数据流
- 重命名局部变量/参数改善可读性;`y` 修正调用约定与参数类型
- 伪代码与反汇编对不上时(优化导致的结构差异),回反汇编核对——反编译是视图不是事实
- 算法/解密还原: 反编译输出定位循环,配合 idapython 算关键常量(序列见 [[commands]] 操作序列 3)
5. **idapython 批处理(解密循环/批量标注)**:
```python
import ida_bytes, idc
# 批量 patch: 0x401000 起 0x100 字节异或 0x55
base = 0x401000
for i in range(0x100):
ida_bytes.patch_byte(base + i, idc.get_byte(base + i) ^ 0x55)
```
```python
# 批量重命名: 给所有未命名导入标注来源
import ida_funcs, ida_name
# 遍历函数: ida_funcs.get_func() / idc.get_func_name()
```
无头运行: `idat -A -S"script.py log.txt" sample`,脚本末尾 `idc.qexit(0)` 保证退出(`idc.qexit` 是 `ida_pro.qexit` 别名,IDA 7.0+ 一致)。
6. **免费版限制处理**:
- 免费版无 Hex-Rays: 用反汇编 + idapython(按步骤 5 方式人工还原循环/算法),或直接导出给 Ghidra:
菜单 `File > Produce file > Dump typeinfo` / 用 idb2pat 生成库签名;或换 [[re-ghidra]] 做反编译
- 免费版功能裁剪:无本地 Hex-Rays(有 x86/x64 云端反编译可先试)、调试器仅限本地 x86/x64、无反汇编器扩展——按裁剪范围调整流程
7. **动态调试(Windows 本地目标,商业版)**:
- `F9` 运行、`F2` 断点切换、`F8`/`F7` 单步、`Ctrl+F2` 重启——与 [[re-x64dbg]] 同习惯
- 反调试检测(`IsDebuggerPresent` 等)先静态定位再处理,边界见 [[gotchas]]
8. **证据核对(收尾)**:重命名/注释/已恢复结构随 .i64 存档(`File > Save`,副本备份原库);无头导出产物(函数清单/反编译 .c)与 [[re-triage]] 初勘值对照入档;关键结论写 [[re-analyze/analysis-contract]]——IDA 里的标注要能还原到报告,别只留在数据库里
## 函数分析上下文清单
分析每个函数前先收集(见 [[re-analyze/analysis-contract]] 上下文清单):xrefs、目标函数引用的字符串、caller/callee 签名、已命名符号表、已恢复 struct。一次性给足再分析;主动申请额外证据每函数不超过 8 次工具调用。
深分析按 [[re-analyze/analysis-contract]] 的「单函数深分析顺序」五步推进(types → constants → vtables → identity → decompilation);IDA 下类型用 idapython `get_type`/结构体定义,符号/常量证据可用 readelf / strings / objdump 导出辅助。
## 跨域联合
- [[re-binary-core]]:工作流第 5 步备选反编译器(`RE_DECOMPILER=ida`)
- [[re-cracking]]:注册算法/校验逻辑定位常用 IDA
- [[re-malware]]:恶意样本调试(IDA 调试器)与分析
- [[re-plugin-dev]]:IDAPython 是插件语言,脚本→插件工程化
- 免费版无 Hex-Rays 时对接 [[re-ghidra]]
## 常见坑与陷阱
- **免费版无反编译**:IDA Free 无 Hex-Rays——先确认版本能力,缺反编译直接走 Ghidra,别在反汇编里硬读
- **反调试检测**:样本可用 `IsDebuggerPresent`/`NtQueryInformationProcess` 检测 IDA 调试器(调试器默认标记)——静态分析为主,或用隐藏调试器插件(ScyllaHide 类)
- **大二进制卡顿**:auto-analysis 全开对 100MB+ 二进制极慢——关掉部分分析选项(如 constant propagation)或换 [[re-radare2]]
- FLIRT 匹配的是"去壳后"的真实库——带壳样本先脱壳再跑签名
- **地址型 API 返回值没判 BADADDR**:现象——idapython 脚本在部分样本上拿到 `0xFFFFFFFFFFFFFFFF` 之类的地址,后续寻址/改名全错或崩溃;原因——IDA API 用 `BADADDR`(-1)表示失败(名字不存在、地址非法、函数不存在),脚本没检查返回值就继续用;对策——每个返回地址的 API(`get_name_ea`/`get_func` 等)调用后先判 `== BADADDR`,失败先打印现场再继续;脚本先只读验证再写库(见下条)
- **修改型脚本直接在原库上跑,改坏难回滚**:现象——批处理改名/改字节脚本跑完发现一堆错误标注,撤销费劲甚至不可逆;原因——跳过只读验证直接写库,也没对副本操作;对策——官方推荐先跑只读脚本(打印库路径/架构/函数与字符串统计)确认预期,修改型脚本逐步增量验证(最小脚本→看输出→加功能);批量改动前先复制一份 .i64/.idb 或在副本上跑
- **Hex-Rays interr(decompiler 内部错误)**:现象——无头反编译跑到某个函数报 `interr: create_stkvar(...) dtype=7` 之类后整个进程崩溃,跳过/重试无效;原因——decompiler 对特定栈布局的内部 bug,与样本/脚本无关;对策——换 Ghidra 完成该目标(互证也更好),别在同一函数上硬刚;批量反编译场景先小样本试跑确认不触发再全量
- **无头批量导出没等 auto-analysis 完成(静默产出 0 个函数)**:现象——`idat -A -S"export.py" sample` 批量导出跑完,产物 0 个函数或严重不全,日志无任何报错;原因——`-A` 模式下脚本注入与 auto-analysis 异步并行,脚本在分析完成前就遍历函数列表得到空集,失败被静默吞掉;对策——收集函数前先 `ida_auto.auto_wait()` 阻塞至分析结束;导出循环逐函数 try/except,单个函数失败只记入清单(地址/名字/原因)后继续,结尾汇总 total/exported/failed,不中断全量;只导出非库函数(FUNC_LIB 标志)时无用户代码的小二进制合法产出 0 个,验证用「日志关键字 + 产物计数」双通道并容忍这种合法空产出;调用图(callers/callees)先整体算好缓存再进反编译循环,导出按便宜到贵排序(strings → imports → exports → memory → decompile),每函数一个按地址命名的文件
(来源:LazyReverse(a0yami),MIT)
- IDA 9 脚本迁移(`get_struc` 等已移除)、版本差异与反调试边界见 [[gotchas]]

View File

@@ -0,0 +1,94 @@
# IDA 快捷键与 idapython 命令速查
IDA 双入口:GUI 快捷键(主界面)与 IDAPython(`File > Script command` / 无头脚本)。两者可混用——脚本能完成的事先脚本验证,GUI 负责交互式确认。命令语义以官方文档(docs.hex-rays.com)与 idapython 模块源码为准。
## 快捷键速查(按任务分组)
| 任务 | 快捷键 | 说明 |
|---|---|---|
| 文本搜索 | Alt+T | 当前 IDB 内搜字符串/关键字(找提示文案、错误串) |
| 二进制搜索 | Alt+B | 字节模式搜索(支持 `?` 通配) |
| 跳转 | G | 地址/符号/表达式跳转 |
| 返回上级 | Esc | 沿导航历史回退 |
| 交叉引用 | x | 选中项被谁引用;双击 xref 列表项跳转 |
| 重命名 | n | 函数/变量/全局改名 |
| 改类型 | y | 调用约定/参数/返回类型 |
| 注释 | ; / : | 普通注释 / repeatable 注释(跟随地址显示) |
| 反编译 | F5 | 打开 Hex-Rays 伪代码 |
| 视图切换 | Tab | 伪代码 ↔ 汇编 |
| 段列表 | Alt+E | segments 窗口 |
| 函数窗口 | Shift+F3 | 函数列表(名称/地址/长度) |
| 调试运行 | F9 / F2 / F8 / F7 | 继续 / 断点切换 / 步过 / 步入 |
| 调试重启 | Ctrl+F2 | 重启调试会话 |
| 脚本命令 | Shift+F2 | 打开 Script command 对话框 |
## 无头批处理命令
- `idat -A -S"script.py" sample`:自动模式跑脚本(`-A` 分析完自动退出;不写 `-S` 则只分析)
- `idat -A -S"script.py log.txt" sample`:脚本参数 `log.txt` 传给 `sys.argv`(argv[0]=脚本路径,argv[1:]=剩余参数)
- `idat -A -S"script.py" -L"ida.log" sample`:IDA 自身日志写文件(排错必需,问题常藏在日志里)
- IDA 9.x 无头可执行文件为 `idat`(单二进制同时处理 32/64 位,无 64 后缀);Windows 加 `.exe`(`idat.exe`)。IDA ≤8.x 才分 `idat`/`idat64`
- 无头脚本固定骨架:
```python
import ida_auto, ida_pro, idc
ida_auto.auto_wait() # 等 auto-analysis 完成,否则函数列表为空
# ... 主体逻辑(逐函数 try/except,失败记清单不中断) ...
idc.qexit(0) # = ida_pro.qexit(0),必须退出否则进程挂住
```
## IDAPython 常用函数(按族)
- 字节/寻址: `idc.get_byte(a)` / `ida_bytes.patch_byte(a, v)`;`idc.get_name_ea(0, "name")`(失败返回 `BADADDR`)
- 函数: `ida_funcs.get_func(ea)`(返回 None 判空)、`idc.get_func_name(ea)`、`ida_funcs.func_size(ea)`
- 交叉引用: `idautils.XrefsTo(ea, 0)` / `idautils.XrefsFrom(ea, 0)`——遍历取 `.frm`/`.to`/`.type`
- 反编译: `ida_hexrays.decompile(ea)`(返回 cfunc,`.body` 是 ctree;失败抛异常先 try/except)
- 类型: `ida_typeinf.tinfo_t` 体系(IDA 9 推荐);旧 `get_struc`/`get_member` 在 IDA 9 已移除
- 输出: `print()` 进输出窗口;批量结果写文件比刷输出窗口稳
## 常用操作序列(组合套路)
### 1. 定位校验/注册逻辑:字符串 → xref → 函数
```
Alt+T 搜提示文案("Invalid key"/错误串)→ x 找引用 → 引用处函数 F5
伪代码里沿调用链上溯 → 找比较点(strcmp/校验 call)→ n 重命名 → 结论写注释 ;
```
### 2. 无头批量反编译导出(只读先行)
```
idat -A -S"dump.py" -L"ida.log" sample
# dump.py: auto_wait() → 遍历 idautils.Functions() 过滤 FUNC_LIB
# → 每函数 try: decompile(ea) 存 .c 文件;except: 记 (ea, name, reason) 清单
# → 结尾打印 total/exported/failed 双通道验证(配合 ida.log 关键字)
```
### 3. 解密循环批量 patch(写库前先跑只读验证)
```
先跑只读脚本: 打印目标段字节统计(读 0x100 字节 + 熵/首字节分布)确认地址与算法
再跑写库脚本: ida_bytes.patch_byte(base+i, get_byte(base+i) ^ key)
在 .i64 副本上跑;结束后 idc.qexit(0)
```
### 4. FLIRT 识别失败后的库函数对照
```
idb2pat 从某已知库构建 .pat → sigmake 转 .sig → 应用到样本
# 或先用 File > Produce file > Dump typeinfo 导出类型给其他工具
```
## 实现教训(内化)
- 无头脚本与 auto-analysis 异步并行——`auto_wait()` 之前任何函数遍历都是空的
- 返回地址的 API 一律判 `BADADDR`,返回对象的 API 判 None;失败先打印现场再继续
- 写库(patch/rename)不可逆性差——先在副本上跑,脚本先只读验证
- `idc.qexit(0)` 是唯一可靠的批量退出方式;`-L` 日志与 print 输出双通道验证结果
- 批量导出按便宜到贵排序(strings → imports → exports → memory → decompile),失败单条记录不中断
## 使用注意
- 静态分析免沙箱;IDA 调试器动态调试按 [[re-analyze/platform-tips]] 最高原则沙箱内执行
- 动态分析前先 [[re-triage]] 初勘(哈希/壳识别),FLIRT 只对脱壳后库有效
- 结论写入 [[re-analyze/analysis-contract]] 数据契约;带壳目标先 [[re-anti-analysis]]

View File

@@ -0,0 +1,43 @@
# IDA 工具特有坑与边界
## 版本差异(7.x / 8.x / 9.x)
- **数据库格式**:IDA 7.5 起统一 `.i64`(32/64 位同一格式);7.4 及以前 32 位 `.idb`、64 位 `.idb64`——旧库首次打开会走升级流程,升级后不可回退,重要库先备份
- **宿主系统**:IDA 8.x 起仅支持 64 位宿主(不再有 32 位安装包);Linux 需 Qt 运行库,headless 无头模式不需要图形环境
- **IDA 9.0(2024)**:32/64 位安装合一(不再有独立 IDA32);新增 FLIRT 签名管理器(在线下载签名);新增 idalib(在 IDA 外调 C++/Python API 做无头处理);Python 支持 3.8–3.13,用 `idapyswitch` 切换(9.0 SP1 起支持 3.13)
- **IDAPython 8→9 破坏性变更**:`get_struc`/`get_member`/`ida_typeinf.get_ordinal_qty` 等移除,结构体 API 迁移到 `tinfo_t`/`til_t`;`idautils.StructMembers` 返回值改三元组——旧插件/脚本先对照迁移指南(idapython-porting-guide-ida-9)再跑
- **Hex-Rays 版本**:伪代码输出随版本变化(IDA 9 起 x64 MSVC 异常处理可反编译出 try/catch)——不同版本对同一函数输出不同,跨版本互证时注明版本
## 免费版(IDA Free)边界
- **仅 x86/x64**:分析器不支持 ARM/MIPS 等其他架构;云端反编译同样只覆盖 x86/x64
- **无本地 Hex-Rays**:只有反汇编 + idapython;云端反编译按函数付费额度使用
- **调试器仅限本地 x86/x64 用户态**:不能远程调试、不能内核调试;反调试对抗能力弱于商业版
- **无插件/无 FLIRT 扩展**:不能安装第三方插件(反编译插件类都不可用);FLIRT 只能用自带 sig
- 结论:免费版定位是「反汇编 + 脚本化」,需要反编译能力直接 [[re-ghidra]]
## 无头批处理坑
- **不写 `auto_wait()` 产出空集**:`-A` 模式下脚本与 auto-analysis 并行,遍历函数列表前必须 `ida_auto.auto_wait()`
- **不写 `qexit` 进程挂住**:脚本跑完不退出,CI/批量场景卡死——`idc.qexit(0)`(别名 `ida_pro.qexit(0)`)
- **日志不落盘难排错**:`-L"ida.log"` 输出 IDA 日志;脚本 print 进输出窗口不进 stdout 文件(重定向无效)
- **修改型脚本不可逆**:先在副本 .i64 上跑,先只读验证再写库(详见 SKILL.md 坑 5/6)
- **`-A` 与 `-c` 区别**:`-c` 强制重新分析(丢弃已有分析结果);对已有 .i64 再跑脚本时不加 `-c` 会沿用旧分析
- **合法空产出**:只导出非库函数时,无用户代码的小二进制产出 0 个函数是合法的——用「日志关键字 + 产物计数」双通道判断
## 反调试与动态调试边界
- **调试器特征可检测**:IDA 调试器有默认标记(进程名/窗口类/模块特征),样本可枚举检测——静态定位检测点(`IsDebuggerPresent`/`NtQueryInformationProcess` xrefs)后处理,见 [[re-anti-analysis]]
- **PPL/受保护进程无法附加**:Windows 内核保护进程超出 IDA 用户态调试能力,换内核调试([[re-windbg]])或放弃
- **TLS 回调/入口前逻辑**:调试启动时停在系统断点,入口前逻辑可能已执行——需要时在调试选项里开事件断点
- **wow64 目标**:32 位样本在 64 位系统上运行,栈/寄存器视图是 x64 上下文——切到 x86 视图或用 [[re-x64dbg]](x32dbg)更省事
## 大二进制与性能
- auto-analysis 全开对 100MB+ 二进制极慢:`Options > General > Analysis` 关掉 constant propagation 等非必要 pass;只对重点段手工 `MakeCode`/`MakeFunction`
- 无头模式比 GUI 快但资源占用高(多核分析全开)——批量任务排队跑,别一次开多个
## 使用注意
- 全部在沙箱内执行([[re-analyze/platform-tips]] 最高原则);动态调试按默认沙箱
- 脚本/插件/数据库与 IDA 版本强绑定——换版本先跑 `File > Script command` 的 `idaapi.IDA_SDK_VERSION` 确认