d4em0n/exrop

GitHub: d4em0n/exrop

基于 Triton 的 x86-64 自动 ROP 链生成工具,支持寄存器设置、内存写入、函数调用、栈迁移及内核模式利用链自动构造。

Stars: 295 | Forks: 21

# Exrop Exrop 是一款自动 ROP 链生成工具,可以根据给定的二进制文件和约束自动构建 gadget 链 依赖项:[Triton](https://github.com/JonathanSalwan/Triton),[ROPgadget](https://github.com/JonathanSalwan/ROPgadget) 目前仅支持 x86-64! 功能: - 处理非返回 gadgets(jmp reg, call reg) - 设置寄存器(`rdi=0xxxxxx, rsi=0xxxxxx`) - 设置寄存器到寄存器(`rdi=rax`) - 写入内存(常量和基于寄存器的地址/值) - 将字符串/字节写入内存 - 函数调用(`open('/etc/passwd',0)`) - 在函数调用中传递寄存器(`read('rax', bss, 0x100)`) - 避免坏字符 - 栈迁移(`Exrop.stack_pivot`) - 使用 JOP 链搜索进行内核风格的寄存器迁移(`Exrop.stack_pivot_reg`) - syscall(`Exrop.syscall`) - 内核模式,支持自动 retpoline thunk 重写(`kernel_mode=True`) - 仅纯净模式,过滤掉具有危险副作用内存写入的 gadgets - 基于后缀的提前退出:从已分析的后缀组合多指令 gadgets,跳过冗余的 Triton 执行 - 采用按长度分轮策略的多进程 gadget 分析,并显示进度条 - gadget 缓存,支持快速复用 - 查看[示例](examples) # 安装 1. 安装 Python 3.6+ 2. 安装 [Triton](https://triton-library.github.io/documentation/doxygen/index.html#linux_install_sec) 3. 安装 [ROPgadget](https://github.com/JonathanSalwan/ROPgadget) 4. 可选:安装 [Keystone](https://www.keystone-engine.org/)(仅在运行测试时需要) 5. 将 exrop 添加到您的 Python 路径:`export PYTHONPATH=/path/to/exrop:$PYTHONPATH` # demo ``` from Exrop import Exrop rop = Exrop("/bin/ls") rop.find_gadgets(cache=True) print("write-regs gadgets: rdi=0x41414141, rsi:0x42424242, rdx: 0x43434343, rax:0x44444444, rbx=0x45454545") chain = rop.set_regs({'rdi':0x41414141, 'rsi': 0x42424242, 'rdx':0x43434343, 'rax':0x44444444, 'rbx': 0x45454545}) chain.dump() print("write-what-where gadgets: [0x41414141]=0xdeadbeefff, [0x43434343]=0x110011") chain = rop.set_writes({0x41414141: 0xdeadbeefff, 0x43434343: 0x00110011}) chain.dump() print("write-string gadgets 0x41414141=\"Hello world!\\n\"") chain = rop.set_string({0x41414141: "Hello world!\n"}) chain.dump() print("func-call gadgets 0x41414141(0x20, 0x30, \"Hello\")") chain = rop.func_call(0x41414141, (0x20, 0x30, "Hello"), 0x7fffff00) chain.dump() ``` 输出: ``` write-regs gadget: rdi=0x41414141, rsi:0x42424242, rdx: 0x43434343, rax:0x44444444, rbx=0x45454545 $RSP+0x0000 : 0x00000000000060d0 # pop rbx; ret $RSP+0x0008 : 0x0000000044444444 $RSP+0x0010 : 0x0000000000014852 # mov rax, rbx; pop rbx; ret $RSP+0x0018 : 0x0000000000000000 $RSP+0x0020 : 0x0000000000004ce5 # pop rdi; ret $RSP+0x0028 : 0x0000000041414141 $RSP+0x0030 : 0x000000000000629c # pop rsi; ret $RSP+0x0038 : 0x0000000042424242 $RSP+0x0040 : 0x0000000000003a62 # pop rdx; ret $RSP+0x0048 : 0x0000000043434343 $RSP+0x0050 : 0x00000000000060d0 # pop rbx; ret $RSP+0x0058 : 0x0000000045454545 write-what-where gadgets: [0x41414141]=0xdeadbeefff, [0x43434343]=0x110011 $RSP+0x0000 : 0x0000000000004ce5 # pop rdi; ret $RSP+0x0008 : 0x000000deadbeefff $RSP+0x0010 : 0x000000000000d91f # mov rax, rdi; ret $RSP+0x0018 : 0x0000000000004ce5 # pop rdi; ret $RSP+0x0020 : 0x0000000041414139 $RSP+0x0028 : 0x000000000000e0fb # mov qword ptr [rdi + 8], rax; ret $RSP+0x0030 : 0x0000000000004ce5 # pop rdi; ret $RSP+0x0038 : 0x0000000000110011 $RSP+0x0040 : 0x000000000000d91f # mov rax, rdi; ret $RSP+0x0048 : 0x0000000000004ce5 # pop rdi; ret $RSP+0x0050 : 0x000000004343433b $RSP+0x0058 : 0x000000000000e0fb # mov qword ptr [rdi + 8], rax; ret write-string gadgets 0x41414141="Hello world!\n" $RSP+0x0000 : 0x0000000000004ce5 # pop rdi; ret $RSP+0x0008 : 0x6f77206f6c6c6548 $RSP+0x0010 : 0x000000000000d91f # mov rax, rdi; ret $RSP+0x0018 : 0x0000000000004ce5 # pop rdi; ret $RSP+0x0020 : 0x0000000041414139 $RSP+0x0028 : 0x000000000000e0fb # mov qword ptr [rdi + 8], rax; ret $RSP+0x0030 : 0x0000000000004ce5 # pop rdi; ret $RSP+0x0038 : 0x0000000a21646c72 $RSP+0x0040 : 0x000000000000d91f # mov rax, rdi; ret $RSP+0x0048 : 0x0000000000004ce5 # pop rdi; ret $RSP+0x0050 : 0x0000000041414141 $RSP+0x0058 : 0x000000000000e0fb # mov qword ptr [rdi + 8], rax; ret func-call gadgets 0x41414141(0x20, 0x30, "Hello") $RSP+0x0000 : 0x0000000000004ce5 # pop rdi; ret $RSP+0x0008 : 0x0000006f6c6c6548 $RSP+0x0010 : 0x000000000000d91f # mov rax, rdi; ret $RSP+0x0018 : 0x0000000000004ce5 # pop rdi; ret $RSP+0x0020 : 0x000000007ffffef8 $RSP+0x0028 : 0x000000000000e0fb # mov qword ptr [rdi + 8], rax; ret $RSP+0x0030 : 0x0000000000004ce5 # pop rdi; ret $RSP+0x0038 : 0x0000000000000020 $RSP+0x0040 : 0x000000000000629c # pop rsi; ret $RSP+0x0048 : 0x0000000000000030 $RSP+0x0050 : 0x0000000000003a62 # pop rdx; ret $RSP+0x0058 : 0x000000007fffff00 $RSP+0x0060 : 0x0000000041414141 python3 tests.py 1,48s user 0,05s system 97% cpu 1,566 total ``` ## 内核模式 对于启用了 retpoline 缓解措施的 Linux 内核,`kernel_mode=True` 会自动检测 thunk 符号,重写 gadgets,并限制在 `.text` 段内: ``` from Exrop import Exrop rop = Exrop("/path/to/vmlinux") rop.find_gadgets(cache=True, kernel_mode=True) # 使用 clean_only 排除具有危险副作用内存写入的 gadgets # (例如,add byte ptr [rcx + 0x415d5be8], cl — 在未映射内存上崩溃) rop.clean_only = True # 设置寄存器 chain = rop.set_regs({'rdi': 0x41414141, 'rsi': 0}) chain.dump() # 查找 pivot gadgets(直接、JOP 链式、间接) pivots = rop.stack_pivot_reg('rdi') for p in pivots[:5]: p.dump() # 为 pivot 构建 payload payload = pivots[0].build_payload(chain) ``` ## 用户空间示例 另一个示例:open-read-write gadgets! ``` from pwn import * import time from Exrop import Exrop binname = "/lib/x86_64-linux-gnu/libc.so.6" libc = ELF(binname, checksec=False) open = libc.symbols['open'] read = libc.symbols['read'] write = libc.symbols['write'] bss = libc.bss() t = time.mktime(time.gmtime()) rop = Exrop(binname) rop.find_gadgets(cache=True) print("open('/etc/passwd', 0)") chain = rop.func_call(open, ("/etc/passwd", 0), bss) chain.set_base_addr(0x00007ffff79e4000) chain.dump() print("read('rax', bss, 0x100)") # register can be used as argument too! chain = rop.func_call(read, ('rax', bss, 0x100)) chain.set_base_addr(0x00007ffff79e4000) chain.dump() print("write(1, bss, 0x100)") chain = rop.func_call(write, (1, bss, 0x100)) chain.set_base_addr(0x00007ffff79e4000) chain.dump() print("done in {}s".format(time.mktime(time.gmtime()) - t)) ``` 输出: ``` open('/etc/passwd', 0) $RSP+0x0000 : 0x00007ffff7a05a45 # pop r13 ; ret $RSP+0x0008 : 0x00000000003ec860 $RSP+0x0010 : 0x00007ffff7a7630c # xor edi, edi ; pop rbx ; mov rax, rdi ; pop rbp ; pop r12 ; ret $RSP+0x0018 : 0x00007ffff7a0555f $RSP+0x0020 : 0x0000000000000000 $RSP+0x0028 : 0x0000000000000000 $RSP+0x0030 : 0x00007ffff7a06b8a # mov r9, r13 ; call rbx: next -> (0x0002155f) # pop rdi ; ret $RSP+0x0038 : 0x00007ffff7a0555f # pop rdi ; ret $RSP+0x0040 : 0x7361702f6374652f $RSP+0x0048 : 0x00007ffff7b251c7 # mov qword ptr [r9], rdi ; ret $RSP+0x0050 : 0x00007ffff7a05a45 # pop r13 ; ret $RSP+0x0058 : 0x00000000003ec868 $RSP+0x0060 : 0x00007ffff7a7630c # xor edi, edi ; pop rbx ; mov rax, rdi ; pop rbp ; pop r12 ; ret $RSP+0x0068 : 0x00007ffff7a0555f $RSP+0x0070 : 0x0000000000000000 $RSP+0x0078 : 0x0000000000000000 $RSP+0x0080 : 0x00007ffff7a06b8a # mov r9, r13 ; call rbx: next -> (0x0002155f) # pop rdi ; ret $RSP+0x0088 : 0x00007ffff7a0555f # pop rdi ; ret $RSP+0x0090 : 0x0000000000647773 $RSP+0x0098 : 0x00007ffff7b251c7 # mov qword ptr [r9], rdi ; ret $RSP+0x00a0 : 0x00007ffff7a62c70 # xor esi, esi ; mov rax, rsi ; ret $RSP+0x00a8 : 0x00007ffff7a0555f # pop rdi ; ret $RSP+0x00b0 : 0x00000000003ec860 $RSP+0x00b8 : 0x000000000010fc40 read('rax', bss, 0x100) $RSP+0x0000 : 0x00007ffff7a71362 # mov dh, 0xc5 ; pop rbx ; pop rbp ; pop r12 ; ret $RSP+0x0008 : 0x0000000000000000 $RSP+0x0010 : 0x0000000000000000 $RSP+0x0018 : 0x00007ffff7a0555f $RSP+0x0020 : 0x00007ffff7aea899 # mov r8, rax ; call r12: next -> (0x0002155f) # pop rdi ; ret $RSP+0x0028 : 0x00007ffff7b4a3b1 # pop rax ; pop rdx ; pop rbx ; ret $RSP+0x0030 : 0x00007ffff79e5b96 $RSP+0x0038 : 0x0000000000000000 $RSP+0x0040 : 0x0000000000000000 $RSP+0x0048 : 0x00007ffff7a7fa08 # mov rdi, r8 ; call rax: next -> (0x00001b96) # pop rdx ; ret $RSP+0x0050 : 0x00007ffff79e5b96 # pop rdx ; ret $RSP+0x0058 : 0x0000000000000100 $RSP+0x0060 : 0x00007ffff7a07e6a # pop rsi ; ret $RSP+0x0068 : 0x00000000003ec860 $RSP+0x0070 : 0x0000000000110070 write(1, bss, 0x100) $RSP+0x0000 : 0x00007ffff7a0555f # pop rdi ; ret $RSP+0x0008 : 0x0000000000000001 $RSP+0x0010 : 0x00007ffff79e5b96 # pop rdx ; ret $RSP+0x0018 : 0x0000000000000100 $RSP+0x0020 : 0x00007ffff7a07e6a # pop rsi ; ret $RSP+0x0028 : 0x00000000003ec860 $RSP+0x0030 : 0x0000000000110140 done in 3.0s (Running on: A9-9420 RADEON R5 2C+3G (2) @ 3.000GHz (using cached)) ```
标签:0day挖掘, CTF工具, Go语言工具, Hpfeeds, JOP, Python, ROP链生成, Triton, Web报告查看器, x86-64, XXE攻击, 二进制安全, 云资产清单, 内核安全, 无后门, 栈溢出, 栈迁移, 溢出攻击, 漏洞搜索, 符号执行, 系统调用, 网络安全, 网络监控, 自动攻击, 逆向工具, 逆向工程, 隐私保护, 面向跳转编程, 面向返回编程