angrop
angrop是一个ROP小工具查找器和链构建器
概述
angrop是一个自动生成ROP链的工具。
它基于angr的符号执行引擎构建,使用约束求解来生成链并理解小工具的效果。
angrop应该支持angr支持的所有架构,尽管还需要进行更多测试。
通常,它可以比人类更快地生成ROP链(尤其是长链)。
它包含了一些生成常用于漏洞利用和CTF的链的函数,如设置寄存器和调用函数。
架构
支持的架构:
- x86/x64
- ARM
- MIPS
支持其他由angr
支持的架构应该相对容易。
如果你想在其他架构上使用angrop
,请创建一个issue,我们会研究一下 :)
使用方法
ROP分析会查找ROP小工具并可以自动构建ROP链。
>>> import angr, angrop
>>> p = angr.Project("/bin/ls")
>>> rop = p.analyses.ROP()
>>> rop.find_gadgets()
>>> chain = rop.set_regs(rax=0x1337, rbx=0x56565656)
>>> chain.payload_str()
b'\xb32@\x00\x00\x00\x00\x007\x13\x00\x00\x00\x00\x00\x00\xa1\x18@\x00\x00\x00\x00\x00VVVV\x00\x00\x00\x00'
>>> chain.print_payload_code()
chain = b""
chain += p64(0x410b23) # pop rax; ret
chain += p64(0x1337)
chain += p64(0x404dc0) # pop rbx; ret
chain += p64(0x56565656)
链
# angrop包含创建某些常见链的方法
# 设置寄存器
chain = rop.set_regs(rax=0x1337, rbx=0x56565656)
# 移动寄存器
chain = rop.move_regs(rax='rdx')
# 写入内存
# 将"/bin/sh\0"写入地址0x61b100
chain = rop.write_to_mem(0x61b100, b"/bin/sh\0")
# 调用函数
chain = rop.func_call("read", [0, 0x804f000, 0x100])
# 向内存添加值
chain = rop.add_to_mem(0x804f124, 0x41414141)
# 移动栈指针,类似于add rsp, 0x8; ret(这个小工具将rsp移动0x10)
chain = rop.shift(0x10)
# 生成ret-sled链,如ret*0x10,但也适用于ARM/MIPS
chain = rop.retsled(0x40)
# 可以指定坏字节来生成不包含坏字节的链
rop.set_badbytes([0x0, 0x0a])
chain = rop.set_regs(eax=0)
# 可以将链加在一起以串联操作
chain = rop.write_to_mem(0x61b100, b"/home/ctf/flag\x00") + rop.func_call("open", [0x61b100,os.O_RDONLY]) + ...
# 可以打印链以便复制粘贴到漏洞利用中
>>> chain.print_payload_code()
chain = b""
chain += p64(0x410b23) # pop rax; ret
chain += p64(0x74632f656d6f682f)
chain += p64(0x404dc0) # pop rbx; ret
chain += p64(0x61b0f8)
chain += p64(0x40ab63) # mov qword ptr [rbx + 8], rax; add rsp, 0x10; pop rbx; ret
...
小工具
小工具包含大量信息:
例如,看看下面的代码如何转换为一个小工具
0x403be4: and ebp,edi
0x403be6: mov QWORD PTR [rbx+0x90],rax
0x403bed: xor eax,eax
0x403bef: add rsp,0x10
0x403bf3: pop rbx
0x403bf4: ret
>>> print(rop.rop_gadgets[0])
Gadget 0x403be4
Stack change: 0x20
Changed registers: set(['rbx', 'rax', 'rbp'])
Popped registers: set(['rbx'])
Register dependencies:
rbp: [rdi, rbp]
Memory write:
address (64 bits) depends on: ['rbx']
data (64 bits) depends on: ['rax']
依赖关系描述了哪些寄存器影响另一个寄存器的最终值。 在上面的例子中,rbp的最终值依赖于rdi和rbp。 分析了寄存器和内存操作的依赖关系。 所有信息都作为属性存储在小工具中,因此很容易遍历它们并找到符合你需求的小工具。
>>> for g in rop.rop_gadgets:
if "rax" in g.popped_regs and "rbx" not in g.changed_regs:
print(g)
Gadget 0x4032b3
Stack change: 0x10
Changed registers: set(['rax'])
Popped registers: set(['rax'])
Register dependencies:
待办事项
允许将字符串作为参数传递给func_call(),然后将其写入内存并引用。
添加open、read、write函数(用于CTF)。
允许使用angr对象(如BVV、BVS)以便轻松使用符号值。
用于查找可执行地址的段分析似乎经常在非ELF二进制文件(如PE文件、内核模块)上失效。
允许对生成的链设置约束,例如有效字节。
常见问题
确保在调用proj.analyses.ROP()之前导入angrop。
确保在尝试制作链之前调用find_gadets()。