Rex: 自动化利用引擎分析
字数 3381 2025-08-24 16:48:07
Rex: 自动化利用引擎分析教程
1. Rex概述
Rex是Shellphish团队开发的自动生成exploit的引擎,是Mechaphish中的一个模块,最初用于CGC竞赛。它基于以下核心技术:
- 硬件模拟器QEMU
- 符号执行框架angr
- 混合执行(Concolic Execution)
主要功能:
- 通过混合执行复现崩溃路径
- 根据寄存器及内存信息判定漏洞类型和可利用性
- 尝试应用多种漏洞利用技术自动生成利用脚本
2. 安装方法
推荐安装方式
使用shellphish/mechaphish docker镜像:
docker pull shellphish/mechaphish
docker run -it shellphish/mechaphish
测试安装
tg = archr.targets.LocalTarget(<path_to_binary>, target_os='cgc')
crash = rex.Crash(tg, <input>)
示例测试代码:
t = archr.targets.LocalTarget(["/home/angr-dev/binaries/tests/defcon24/legit_00003"], target_os='cgc')
crash = rex.Crash(t, b"\x00\x0b 1 \xc1\x00\x0c\xeb...") # 完整输入见原文
3. 核心接口与使用流程
基本使用步骤
- 创建target对象
- 使用target和input创建Crash对象
- 对Crash进行分析
- 调用explore()探索路径
- 调用exploit()方法构建exp
- 获取exploit相关信息并导出
Crash对象
主要属性
crash_types: 返回crash的漏洞类型
主要方法
explorable(): 判断是否可用'crash explorer'探索exploitable(): 判断crash是否可利用exploit(): 返回ExploitFactory实例explore(): 探索crash以发现新bugmemory_control(): 确定我们控制的符号内存stack_control(): 确定栈上控制的符号内存
ExploitFactory
通过crash的exploit()方法获得,重要属性:
arsenal: 字典,存储对应technique的exploit
4. 漏洞类型定义
Rex定义了以下漏洞类型:
IP_OVERWRITE = "ip_overwrite" # IP完全覆盖
PARTIAL_IP_OVERWRITE = "partial_ip_overwrite" # IP部分覆盖
UNCONTROLLED_IP_OVERWRITE = "uncontrolled_ip_overwrite"
BP_OVERWRITE = "bp_overwrite" # BP覆盖
PARTIAL_BP_OVERWRITE = "partial_bp_overwrite"
WRITE_WHAT_WHERE = "write_what_where" # 任意地址写任意数据
WRITE_X_WHERE = "write_x_where" # 任意地址写固定数据
UNCONTROLLED_WRITE = "uncontrolled_write" # 目标地址不可控的写
ARBITRARY_READ = "arbitrary_read" # 任意地址读
NULL_DEREFERENCE = "null_dereference" # 空指针解引用
ARBITRARY_TRANSMIT = "arbitrary_transmit" # 完全控制buf参数的传输
ARBITRARY_RECEIVE = "arbitrary_receive" # 完全控制buf参数的接收
5. 内部实现解析
Rex内部实现主要包含三个模块:
- Crash: 重现崩溃路径,包括漏洞类型判定和可利用性判定
- Technique: 对可利用的Crash应用相应的利用技术
- Exploit: 调用各子模块自动生成Exploit
关系:crash + technique = exploit
5.1 Crash分析流程
路径重现(_trace)
- 使用给定输入获得具体trace
- 进行符号化trace
- 检查是否有crash
获取内存写操作(_filter_memory_writes)
- 获得所有写内存操作
- 分成符号内存(symbolic memory bytes)和flag内存(flag memory bytes)
漏洞类型判断(_triage_crash)
判断逻辑:
- 检查ip是否符号化(可控)及可控大小 → IP_OVERWRITE/PARTIAL_IP_OVERWRITE
- 检查bp是否符号化及可控大小 → BP_OVERWRITE/PARTIAL_BP_OVERWRITE
- 检查崩溃前State的recent_actions,筛选内存读写地址可控的操作
- 内存写且数据可控 → WRITE_WHAT_WHERE
- 内存写但数据不可控 → WRITE_X_WHERE
- 内存读 → ARBITRARY_READ
5.2 路径探索(explore)
可explore的漏洞类型:
- ARBITRARY_READ
- WRITE_WHAT_WHERE
- WRITE_X_WHERE
实现方式:
_explore_arbitrary_read: 任意读漏洞_explore_arbitrary_write: 任意写漏洞
5.3 可利用性判定
可exploitable的漏洞类型:
exploitables = [
Vulnerability.IP_OVERWRITE,
Vulnerability.PARTIAL_IP_OVERWRITE,
Vulnerability.BP_OVERWRITE,
Vulnerability.PARTIAL_BP_OVERWRITE,
Vulnerability.WRITE_WHAT_WHERE,
Vulnerability.WRITE_X_WHERE
]
6. Technique对象
每个technique都是Technique对象的子类,需要重写:
check(): 检查技术是否适用于给定crashapply(): 在崩溃状态点应用该技术
支持的利用技术
| 技术名称 | 适用漏洞类型 | 其他条件 | 平台 |
|---|---|---|---|
| call_jmp_sp_shellcode | IP_OVERWRITE/PARTIAL_IP_OVERWRITE | 栈可执行 | unix |
| call_shellcode | IP_OVERWRITE/PARTIAL_IP_OVERWRITE | 栈可执行 | unix |
| circumstantially_set_register | IP_OVERWRITE/PARTIAL_IP_OVERWRITE | - | cgc |
| rop_leak_memory | IP_OVERWRITE/PARTIAL_IP_OVERWRITE | - | cgc |
| rop_register_control | IP_OVERWRITE/PARTIAL_IP_OVERWRITE | - | unix |
| rop_set_register | IP_OVERWRITE/PARTIAL_IP_OVERWRITE | - | cgc |
| rop_to_accept_system | IP_OVERWRITE/PARTIAL_IP_OVERWRITE | 存在accept&read函数 | unix |
| rop_to_execl | IP_OVERWRITE/PARTIAL_IP_OVERWRITE | 存在execl&dup2函数 | unix |
| rop_to_system | IP_OVERWRITE/PARTIAL_IP_OVERWRITE | 存在system函数 | unix |
| rop_to_system_complicated | IP_OVERWRITE/PARTIAL_IP_OVERWRITE | libc被加载&system函数&plt | unix |
| shellcode_leak_address | IP_OVERWRITE/PARTIAL_IP_OVERWRITE | 栈可执行 | cgc |
| shellcode_set_register | IP_OVERWRITE/PARTIAL_IP_OVERWRITE | 栈可执行 | cgc |
7. Exploit对象
Exploit对象表示成功将利用技术应用于崩溃状态的结果。
ExploitFactory
用于管理和构建exploit,调用exploit()方法时:
- 依次应用每种利用技术
- 成功生成的exploit存储在arsenal属性中
- 针对CGC有专门的CGCExploitFactory类
构建exp
def exploit(self, blacklist_symbolic_explore=True, **kwargs):
factory = self._prepare_exploit_factory(blacklist_symbolic_explore, **kwargs)
factory.initialize()
return factory
8. 测试示例
CGC测试
def test_legit_00003():
inp = b"1\n" + b"A"*200
path = os.path.join(bin_location, "tests/defcon24/legit_00003")
with archr.targets.LocalTarget([path], target_os='cgc') as target:
crash = rex.Crash(target, inp, fast_mode=True,
rop_cache_path=os.path.join(cache_location, 'legit_00003'))
assert crash.explorable()
assert crash.one_of(Vulnerability.WRITE_WHAT_WHERE)
crash.explore()
arsenal = crash.exploit(blacklist_techniques={'rop_set_register', 'rop_leak_memory'})
assert len(arsenal.register_setters) >= 2
assert len(arsenal.leakers) >= 1
Linux测试
def test_linux_stacksmash_32():
inp = b"A"*227
lib_path = os.path.join(bin_location, "tests/i386")
ld_path = os.path.join(lib_path, "ld-linux.so.2")
path = os.path.join(lib_path, "vuln_stacksmash")
with archr.targets.LocalTarget([ld_path, '--library-path', lib_path, path],
path, target_arch='i386').build().start() as target:
crash = rex.Crash(target, inp, fast_mode=True,
rop_cache_path=os.path.join(cache_location, 'vuln_stacksmash'))
exploit = crash.exploit(blacklist_techniques={'rop_leak_memory', 'rop_set_register'})
assert len(exploit.arsenal) == 3
assert 'rop_to_system' in exploit.arsenal
assert 'call_shellcode' in exploit.arsenal
assert 'call_jmp_sp_shellcode' in exploit.arsenal
9. 相关库 - archr
archr实现了以target为中心的分析模型,核心概念:
Targets
- DockerImageTarget: docker镜像
- LocalTarget: 本地系统运行的target
Bows
| 名称 | 描述 |
|---|---|
| DataScoutBow | 获取进程启动时的内存映射、环境、属性 |
| AngrProjectBow | 创建angr Project |
| AngrStateBow | 创建angr State |
| QEMUTraceBow | 执行qemu tracing |
| GDBServerBow | 在gdbserver中启动target |
| STraceBow | strace目标(跟踪系统调用和信号) |
| CoreBow | 启动target并恢复core |
| InputFDBow | 确定用户输入的FD数目 |
10. 总结
Rex是一个相对简单的自动化利用引擎,特点包括:
- 基于angr和QEMU实现
- 支持多种基本漏洞类型的检测和利用
- 提供了一套完整的从crash到exploit的自动化流程
- 支持CGC和Linux平台
虽然技术实现较为基础,但其架构和思路值得学习,可以作为自动化漏洞利用研究的起点。