angrop是一个自动化生成rop链的工具。他是基于angr的符号执行引起,并且用约束求解去生成rop链,而且可以理解gadget的作用。
angrop这个工具构造长的rop链要比人工快多了。
docker安装
拉取angr的镜像
sudo docker pull angr/angr
基于镜像创建容器
sudo docker run -it --name=angr_container angr/angr
angrop用法
github上给出了一个简单的示例。
>>> 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)
这里的rop链只是实现了一个设置寄存器rax、rbx的值分别为0x1337、0x56565656。如果想实现别的功能的话,angrop也能做到。github官网上列举了这几种:
# angrop includes methods to create certain common chains
# setting registers
chain = rop.set_regs(rax=0x1337, rbx=0x56565656)
# writing to memory
# writes "/bin/sh\0" to address 0x61b100
chain = rop.write_to_mem(0x61b100, b"/bin/sh\0")
# calling functions
chain = rop.func_call("read", [0, 0x804f000, 0x100])
# adding values to memory
chain = rop.add_to_mem(0x804f124, 0x41414141)
# chains can be added together to chain operations
chain = rop.write_to_mem(0x61b100, b"/home/ctf/flag\x00") + rop.func_call("open", [0x61b100,os.O_RDONLY]) + ...
# chains can be printed for copy pasting into exploits
>>> 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
...
此外,打印gadget,也能获取到很丰富的gadget信息。
>>> print(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']
这里的寄存器依赖关系指的是哪些寄存器影响了最终的寄存器的值。在上面的例子中,rdi和rbp影响了rbp的值。所有的信息都存在gadget对象的属性里,所以很容易来迭代他们,来找到适合你需要的gadget。
>>> for g in 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: