GOT I Shall Pwn Thee

September 18, 2011

This post is about a new tool I’ve been working on, rop_tools. This is a tool for working with rop gadgets in ELF binaries (currently only 32-bit). But first I’ll talk about the reasons why I wrote the tool.

I was recently working on exploiting a binary in linux. This binary was small, and I needed all the gadgetry I could find. I turned first to msfrop, but it wasn’t hacking it. I needed to look 2, 3, 4, any arbitrary number of instructions back. I was interested in not just ret gadgets, but gadgets that jump to registers and call registers.

So I wrote my own tool, rop_tools. I’m not going to run against my target binary for this post, but we’ll run against the ravm assembler which comes in at 28k. Here are some examples:

rop_tools arguments

./rop_tools
rop_tools
brought to you by rainbowsandpwnies

./rop_tools [-cjr] [-d depth] (-e  | -l  depth, in instructions, to search backwards
  -e    filename of elf to analyze
  -j         search for jmp reg gadgets
  -k         search for conditional jmp reg gadgets (for when your day is
             really going that bad, and probably won't return anything)
  -l    runs lua script
  -r         search for ret gadgets

Simple ret gadgets

./rop_tools -e ~/sigsac/ravm/assembler -r | tail
section: .fini
_fini + b
  0804a177:  00 5b 81 -- -- -- -- --   add [ebx-0x7f], bl
  0804a17a:  c3 -- -- -- -- -- -- --   ret 

_fini + 1a
  0804a186:  c9 -- -- -- -- -- -- --   leave
  0804a187:  c3 -- -- -- -- -- -- --   ret 

65 gadgets

ret gadgets with a depth of 3

./rop_tools -e ~/sigsac/ravm/assembler -r -d 3 | tail -n 16
  0804a169:  c3 -- -- -- -- -- -- --   ret 

section: .fini
_fini + 18
  0804a184:  59 -- -- -- -- -- -- --   pop ecx
  0804a185:  5b -- -- -- -- -- -- --   pop ebx
  0804a186:  c9 -- -- -- -- -- -- --   leave
  0804a187:  c3 -- -- -- -- -- -- --   ret 

_fini + 15
  0804a181:  e5 ff -- -- -- -- -- --   in eax, 0xff
  0804a183:  ff 59 5b -- -- -- -- --   call dword far [ecx+0x5b]
  0804a186:  c9 -- -- -- -- -- -- --   leave
  0804a187:  c3 -- -- -- -- -- -- --   ret 

67 gadgets

Why 67 gadgets for depth 3 when depth 1 only returned 65? If you look at these last two rop gadgets, you’ll notice ret is in the same place, but we can get gadgets of depth 3 (we don’t count the ret in depth) by going 3 bytes back from the ret or 6 bytes back from the ret. We can’t afford to miss gadgets when all our libraries start out ASLRed!

Showing the jmp reg and call reg gadgets

 ./rop_tools -e ~/sigsac/ravm/assembler -j -c | tail -n 20
  08049460:  ff e9 -- -- -- -- -- --   jmp ecx

lexer + 3b5
  08049495:  ff 89 95 3c ff ff -- --   dec dword [ecx+0xffff3c95]
  0804949b:  ff e9 -- -- -- -- -- --   jmp ecx

frame_dummy + 1d
  0804874d:  04 08 -- -- -- -- -- --   add al, 0x8
  0804874f:  ff d0 -- -- -- -- -- --   call eax

__do_global_ctors_aux + 19
  0804a159:  eb 04 -- -- -- -- -- --   jmp 0x6
  0804a15b:  ff d0 -- -- -- -- -- --   call eax

__do_global_ctors_aux + 18
  0804a158:  83 eb 04 -- -- -- -- --   sub ebx, 0x4
  0804a15b:  ff d0 -- -- -- -- -- --   call eax

section: .fini
6 gadgets

A note on performance (performance is important). All ret, jmp reg and call reg gadgets from libc

time ./rop_tools -e /lib/i386-linux-gnu/libc-2.13.so -r -j -c | tail

__libc_thread_freeres_fn + 1222b7
  001222b7:  fd -- -- -- -- -- -- --   std
  001222b8:  ff e8 -- -- -- -- -- --   jmp eax

__libc_thread_freeres_fn + 1222bc
  001222bc:  fd -- -- -- -- -- -- --   std
  001222bd:  ff e8 -- -- -- -- -- --   jmp eax

9598 gadgets

real	0m4.472s
user	0m3.920s
sys	0m0.232s

That’s enough of that, let’s talk about the GOT. In this binary I was exploiting, I needed to make a call to setreuid(). If I could add/subtract to the GOT, I would be golden. However, I could only add/subtract 8-bit values. This… this was an issue. I didn’t have infinite size for my rop chain, and I needed to add some pretty big offsets.

The next step was find a rop gadget with the following criteria:

  • add [some_register], some_other_register
  • Was not far from the address of a function that would be loaded into the GOT of my target binary

I could then modify the GOT to give me access to the ROP gadget I needed, ret to an address in the PLT to execute my target gadget, and then use that target gadget to add a 32-bit value to the GOT. rop_tools didn’t support the finding of these gadgets in libc… yet.

So I added lua scripting to rop_tools, wrote a script, and found exactly what I needed:

sprintf -00000095
  0004785b add [ecx-0x1], ebx
  0004785e dec ecx
  00047860 ret 

Now all I need to do is subtract 0×95 bytes from the sprintf GOT entry and I’m golden. How automated is this process? Here are the variable you set to fire off the script:

ROP_OFFSET_SIZE = 256
DEPTH = 2
-- set TARGET_MNEMONICS to nil if you want to show all possibilities
TARGET_MNEMONICS = {"add", "sub"}

LIBC_FILENAME = "/lib/i386-linux-gnu/libc-2.13.so"
TARGET_FILENAME = "/path/to/target"

I would call that pretty automated. If you find this helpful, let me know. I’ll continue to add scripts to rop_tools as I find a need and write them.

posted in Uncategorized by endeavormac

Follow comments via the RSS Feed | Leave a comment | Trackback URL

Leave Your Comment


+ eight = 12

 
Powered by Wordpress and MySQL. Theme by Shlomi Noach, openark.org