Package: angrop
angropangrop is a rop gadget finder and chain builderOverviewangrop is a tool to automatically generate rop chains.It is built on top of angr's symbolic execution engine, and uses constraint solving for generating chains and understanding the effects of gadgets.angrop should support all the architectures supported by angr, although more testing needs to be done.Typically, it can generate rop chains (especially long chains) faster than humans.It includes functions to generate chains which are commonly used in exploitation and CTF's, such as setting registers, and calling functions.UsageThe ROP analysis finds rop gadgets and can automatically build rop chains.>>>importangr,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; retchain+=p64(0x1337)chain+=p64(0x404dc0)# pop rbx; retchain+=p64(0x56565656)Chains# angrop includes methods to create certain common chains# setting registerschain=rop.set_regs(rax=0x1337,rbx=0x56565656)# writing to memory# writes "/bin/sh\0" to address 0x61b100chain=rop.write_to_mem(0x61b100,b"/bin/sh\0")# calling functionschain=rop.func_call("read",[0,0x804f000,0x100])# adding values to memorychain=rop.add_to_mem(0x804f124,0x41414141)# chains can be added together to chain operationschain=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; retchain+=p64(0x74632f656d6f682f)chain+=p64(0x404dc0)# pop rbx; retchain+=p64(0x61b0f8)chain+=p64(0x40ab63)# mov qword ptr [rbx + 8], rax; add rsp, 0x10; pop rbx; ret...GadgetsGadgets contain a lot of information:For example look at how the following code translates into a gadget0x403be4:andebp,edi0x403be6:movQWORDPTR[rbx+0x90],rax0x403bed:xoreax,eax0x403bef:addrsp,0x100x403bf3:poprbx0x403bf4:ret>>>print(rop.gadgets[0])Gadget0x403be4Stackchange:0x20Changedregisters:set(['rbx','rax','rbp'])Poppedregisters:set(['rbx'])Registerdependencies:rbp:[rdi,rbp]Memorywrite:address(64bits)dependson:['rbx']data(64bits)dependson:['rax']The dependencies describe what registers affect the final value of another register.
In the example above, the final value of rbp depends on both rdi and rbp.
Dependencies are analyzed for registers and for memory actions.
All of the information is stored as properties in the gadgets, so it is easy to iterate over them and find gadgets which fit your needs.>>>forginrop.gadgets:if"rax"ing.popped_regsand"rbx"noting.changed_regs:print(g)Gadget0x4032b3Stackchange:0x10Changedregisters:set(['rax'])Poppedregisters:set(['rax'])Registerdependencies:TODO'sAllow strings to be passed as arguments to func_call(), which are then written to memory and referenced.Add a function for open, read, write (for ctf's)Allow using of angr objects such as BVV, BVS to make using symbolic values easyThe segment analysis for finding executable addresses seems to break on non-elf binaries often, such as PE files, kernel modules.Allow setting constraints on the generated chain e.g. bytes that are valid.Common gotchasMake sure to import angrop before calling proj.analyses.ROP()Make sure to call find_gadets() before trying to make chains