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,114 @@
# Unicorn / Qiling 命令速查与操作序列
两框架都是 Python 库:"命令"即 API。分工:Unicorn 只管 CPU+内存(单函数/代码段);Qiling 在 Unicorn 之上接管系统调用/文件/动态链接(程序级)。API 名以官方文档与目标版本源码为准(版本差异见 [[gotchas]])。
## Unicorn API 族
```python
from unicorn import *
from unicorn.x86_const import * # 按架构: arm_const / arm64_const / mips_const ...
mu = Uc(UC_ARCH_X86, UC_MODE_32) # 架构 × 模式
mu = Uc(UC_ARCH_ARM, UC_MODE_ARM | UC_MODE_BIG_ENDIAN) # armeb 大端
# 内存(必须先 mem_map 再 mem_write;地址与大小须页对齐)
mu.mem_map(0x1000, 0x1000) # 一页
mu.mem_write(0x1000, CODE) # 写代码/数据
data = mu.mem_read(0x2000, 0x100) # 读内存(脱壳明文落盘)
mu.mem_protect(0x1000, 0x1000, UC_PROT_ALL) # 改权限(UC_PROT_READ/WRITE/EXEC/ALL)
mu.mem_unmap(0x1000, 0x1000)
# 寄存器
mu.reg_write(UC_X86_REG_ESP, 0x2000) # 栈必须设,否则崩
rax = mu.reg_read(UC_X86_REG_EAX)
# 执行
mu.emu_start(0x1000, 0x1000 + len(CODE), timeout=0, count=0) # until 必须覆盖代码结束
mu.emu_stop()
# 钩子
mu.hook_add(UC_HOOK_CODE, hook_code) # 每指令
mu.hook_add(UC_HOOK_MEM_READ | UC_HOOK_MEM_WRITE, hook_mem) # 内存读写
mu.hook_add(UC_HOOK_MEM_UNMAPPED, hook_bad) # 未映射访问(可现场补映射继续)
mu.hook_add(UC_HOOK_MEM_FETCH, hook_fetch) # 取指(追踪执行流)
mu.hook_add(UC_HOOK_INTR, hook_intr) # 中断(syscall 类拦截)
mu.hook_del(handle) # 卸钩
```
钩子回调签名(2.x 与 1.x 一致):
```python
def hook_code(uc, address, size, user_data): ... # UC_HOOK_CODE
def hook_mem(uc, access, address, size, value, user_data): ... # 内存类
def hook_bad(uc, access, address, size, value, user_data): ... # 返回 True 继续
```
常用常数(见 [[gotchas]] 版本组):`UC_ARCH_X86/ARM/ARM64/MIPS/RISCV`;`UC_MODE_16/32/64/ARM/THUMB/BIG_ENDIAN`;`UC_PROT_READ/WRITE/EXEC/ALL`;寄存器 `UC_X86_REG_RAX/ESP/EIP/RIP` 等。
## Qiling API 族
```python
from qiling import Qiling
ql = Qiling(["./rootfs/x8664_linux/bin/target", "arg1"], "./rootfs/x8664_linux")
# 构造: Qiling(argv, rootfs, env=..., verbose=..., console=...);rootfs 下才是目标可见文件系统
ql.run() # 或 ql.run(begin, end, timeout, count)
ql.save(snapshot="stage1.qsave") # 状态存档(1.1.x+;reg/mem/fd 等可分别开关)
ql.restore(snapshot="stage1.qsave") # 恢复继续
ql.hook_address(fn, addr) # 地址断点(等价 Unicorn 按地址判断的 hook_code)
ql.hook_code(fn) # 每指令
ql.hook_mem_read(fn) / ql.hook_mem_write(fn) / ql.hook_mem_unmapped(fn)
ql.mem.read(addr, size) / ql.mem.write(addr, data)
ql.reg.read("eax") / ql.reg.write("eax", 0)
ql.os.fs # 文件系统视图(rootfs 内路径)
```
## 操作序列(组合套路)
### 1. 脱壳:摘出解密例程模拟执行拿明文
```
静态定位解密循环([[re-unpack-simple]] / [[re-unpack-advanced]] + [[re-ghidra]])
摘取: 代码段字节 + 入口寄存器初值(栈/数据指针)+ 输入密文区
Unicorn 加载: mem_map 代码页+数据页+栈页 → mem_write → reg_write → emu_start
hook_mem_write 记录目标区段写入时机 → mem_read 读出明文段 → sha256 存档
验证: 与沙箱实跑([[re-sandbox]])解密结果对照
```
### 2. 单函数逻辑验证(反编译产物 ↔ 模拟真值)
```
反编译还原算法([[re-binary-core]])→ 汇编级实现提取(objdump 段)
Unicorn 跑该段,输入用真值/边界值(0、-1、0x7fffffff)→ 输出对照反编译预期
不一致即反编译理解有误——以模拟为准修正逻辑
```
### 3. shellcode 行为分析
```
从样本提取 shellcode([[re-shellcode]])→ 映射可执行页
hook_code 记录指令序列 + hook_mem_write 记录写入(找解密循环落点)
hook_intr 拦截 int 0x80/syscall,打印 eax 与参数(不真执行系统调用)
产物(指令轨迹/写点)入证据目录
```
### 4. Qiling 全程序模拟 + 关键点 dump
```
Qiling 加载(rootfs 放好 libc/ld-linux 与输入文件)
hook_address 到 OEP/解密完成点 → ql.save 或 ql.mem.read 落盘解密段
ql.restore 回到存档点继续分支探索(多阶段流程用)
```
## 实现教训(内化)
- **页对齐**:mem_map 的地址与大小必须页(0x1000)对齐,报 `Invalid memory` 先查对齐
- **栈与 until 必设**:不设 ESP 进栈指令即崩;`emu_start` 的 until 必须覆盖代码结束地址,否则跑到非法地址
- **回调里抛异常 = 静默停**:2.x 把回调异常存起来并 emu_stop,外层可能只看到"模拟提前结束"——回调内 try/except + 打印,`emu_start` 后用 `reg_read` 检查 PC 判断停在哪
- **hook 里改 PC 可跳转**:`reg_write(UC_X86_REG_EIP, target)` 实现 patch 跳转;跳转后记得 `hook_del` 避免再进
- **系统调用不模拟**:Unicorn 裸跑遇 syscall 即停——hook_intr 假返回或换 Qiling
- **慢**:UC_HOOK_CODE 每指令回调是数量级开销,只在追踪段用;大数据区读写用 mem_read/mem_write 批量而非逐字节 hook
## 使用注意
- 模拟属动态执行,默认沙箱 + 网络隔离([[re-analyze/platform-tips]] 最高原则);模拟结论与真实沙箱执行交叉验证
- 产物(明文段/轨迹/快照)sha256 存档([[re-triage]]);结论入 [[re-analyze/analysis-contract]]

View File

@@ -0,0 +1,42 @@
# Unicorn / Qiling 工具特有坑与边界
## 版本差异
- **Unicorn 2.x 是当前线**(pip 默认;2.1.4 于 2025-09 发布):钩子回调签名与 1.x 一致(`(uc, address, size, user_data)` / 内存类 `(uc, access, address, size, value, user_data)`),但 2.0 起 C 库 API/内部行为有调整(如部分 hook 类型、PC 保证语义)——旧教程若按 1.x C API 写 python 绑定的罕见写法会失效,Python 绑定层面基本兼容
- **Qiling 版本差异**:快照能力自 1.x 早期即有(1.1.x 起 `ql.save/restore` 已含 snapshot 参数及 reg/mem/fd 开关);1.2 起参数扩展(新增 os_context/loader 等开关);rootfs 组织(`examples/rootfs/`)随版本增删 OS profile——以 clone 的官方仓库当前结构为准
- **capstone 5.x**:`pip install capstone` 当前 5.0.x;5.x 对部分指令的助记符输出与 4.x 有差异(`capstone.x86` 命名一致),反汇编对照脚本留意
- **unidbg / Chomper 是独立工具**:unidbg(Java,Android JNI 模拟)与 Chomper(Unicorn 封装,iOS OC 模拟)不依赖 unicorn pip 包版本,走各自仓库 release
## 环境语义坑(模拟 ≠ 真实)
- **系统调用未处理**:Unicorn 不模拟内核,裸跑真实程序在 syscall/`int 2e` 处停或错——换 Qiling(自动转发系统调用),或 hook_intr 按 eax 号假返回
- **环境检测**:CPUID/rdtsc 时序、API 探测(`GetModuleHandleA` 特殊返回、dladdr 查询)可被用于察觉非真实环境——先静态定位检测点([[re-triage]] / [[re-deobfuscate]]),hook 该路径返回真实环境值;结论必须与真实沙箱执行交叉验证
- **时间/线程/网络语义缺失**:Unicorn 单线程、rdtsc 需 hook 固定、网络栈不存在——依赖这些的任务转 QEMU([[re-fw-emulate]])或真实沙箱([[re-sandbox]])
- **加载器语义**:Unicorn 不解析 ELF/PE——手动摘段加载;Qiling 有 loader 但动态链接解析与真实 ld.so 有差异,`ql.save` 在 dlopen 之后做状态存档再分支,能避开重复解析开销
## 内存坑
- **页对齐**:mem_map 地址与大小必须 0x1000 对齐(4KB),否则报错;栈页至少 1 页(0x1000),`UC_PROT_READ|UC_PROT_WRITE`
- **只读段写入**:`Invalid memory write` 可能不是没映射而是权限——`mem_protect(addr, size, UC_PROT_ALL)` 后重试
- **未映射访问回调**:`UC_HOOK_MEM_UNMAPPED` 里返回 True + 现场 `mem_map` 可让模拟继续(惰性补页);但补页是模拟器行为,真实程序可能根本没有该访问——先核对是不是地址算错
- **栈空间不足**:递归/深调用崩在栈区外——栈页多映射几页,`reg_write` 栈指针给到页顶
## 架构与平台坑
- **ARM Thumb**:Thumb 代码要 `UC_MODE_THUMB`(或 AArch32 混 Thumb 用 `UC_MODE_ARM | UC_MODE_THUMB` 组合),模式错了解码全乱
- **字节序**:armeb/mipsel 用 `UC_MODE_BIG_ENDIAN`/架构对应模式,数据端序与指令端序都要对
- **寄存器常数随架构**:x86 用 `UC_X86_REG_*`、arm 用 `UC_ARM_REG_*`——混用常数报错或拿到错寄存器
- **Android .so → unidbg**:Unicorn/Qiling 裸跑缺 JNI 语义跑不动;iOS 加固/签名 so → Chomper(见 SKILL.md 对应坑)
- **Windows 目标**:Qiling 的 `rootfs/x86_windows` 基于 wine 较重量级,启动慢、部分 API 语义不完整——先试 Linux 化目标或摘函数到 Unicorn
## 结果可信度边界
- **模拟结果"正常"不等于正确**:环境可能被检测并返回诱饵——用真实环境/服务器响应验证(JNI 回调类尤其)
- **快照不跨版本**:qsave 与 Qiling 版本强绑定,升级框架后旧快照可能恢复失败——关键阶段同时落盘明文段(mem_read),别只依赖快照
- **性能**:UC_HOOK_CODE 全量追踪会慢一个数量级——追踪段限定地址范围(hook_add 的 begin/end 参数)或改 hook 内条件判断
- **执行流修正**:hook 内改 PC 做跳转后,目标块执行完可能又落回原指令——需要 `hook_del` 或永久改写内存字节
## 使用注意
- 模拟属动态执行:默认沙箱 + 网络隔离([[re-analyze/platform-tips]] 最高原则)
- 产物(明文段/轨迹/快照)sha256 存档([[re-triage]]);结论入 [[re-analyze/analysis-contract]],与真实执行交叉验证后归档