Reputation: 671
I am working my way through an example in "The Shellcoder's Handbook". However, it is not going all that well. I am running a Debian 2.6.32-5-686 kernel, i386.
The following walkthrough is to guide the reader through the guts of what is happening when a buffer overflow occurs.
The program:
include <stdio.h>
include <string.h>
void return_input(void)
{
char array[30];
gets (array);
printf("%s\n", array);
}
int main ()
{
return_input();
return 0;
}
The aim of the game to to pass "AAAAAAAAAABBBBBBBBBBCCCCCCCCCCDDDDDDDDDD" to the array which, in turn, will overwrite the return address with the excess 'D's.
I compiled like so:
gcc -ggdb -m32 -o test -fno-stack-protector -mpreferred-stack-boundary=2 test.c
I run gdb test
and start investigating:
(gdb) disas return_input
Dump of assembler code for function return_input:
0x080483f4 <return_input+0>: push %ebp
0x080483f5 <return_input+1>: mov %esp,%ebp
0x080483f7 <return_input+3>: sub $0x24,%esp
0x080483fa <return_input+6>: lea -0x1e(%ebp),%eax
0x080483fd <return_input+9>: mov %eax,(%esp)
0x08048400 <return_input+12>: call 0x804830c <gets@plt>
0x08048405 <return_input+17>: lea -0x1e(%ebp),%eax
0x08048408 <return_input+20>: mov %eax,(%esp)
0x0804840b <return_input+23>: call 0x804832c <puts@plt>
0x08048410 <return_input+28>: leave
0x08048411 <return_input+29>: ret
End of assembler dump.
(gdb) break *0x08048400
Breakpoint 1 at 0x8048400: file test.c, line 7.
(gdb) break *0x08048411
Breakpoint 2 at 0x8048411: file test.c, line 9.
At this point we introduced two break points. One just before the call to gets
. And another just before the function returns. Now we run it:
(gdb) run
Starting program: ./test
Breakpoint 1, 0x08048400 in return_input () at test.c:7
7 gets (array);
(gdb) x/20x $esp
0xbffff3ac: 0xbffff3b2 0xb7fca304 0xb7fc9ff4 0x08048440
0xbffff3bc: 0xbffff3d8 0xb7eb75a5 0xb7ff1040 0x0804844b
0xbffff3cc: 0xb7fc9ff4 0xbffff3d8 *0x0804841a* 0xbffff458
0xbffff3dc: 0xb7e9ec76 0x00000001 0xbffff484 0xbffff48c
0xbffff3ec: 0xb7fe18c8 0xbffff440 0xffffffff 0xb7ffeff4
This what the stack looks like just before the call to gets
. I have marked the return address with asterisk (0x0804841a
). Let's overwrite this:
(gdb) continue
Continuing.
AAAAAAAAAABBBBBBBBBBCCCCCCCCCCDDDDDDDDDD
AAAAAAAAAABBBBBBBBBBCCCCCCCCCCDDDDDDDDDD
Breakpoint 2, 0x08048411 in return_input () at test.c:9
9 }
(gdb) x/20x 0xbffff3ac
0xbffff3ac: 0xbffff3b2 0x4141a304 0x41414141 0x41414141
0xbffff3bc: 0x42424242 0x42424242 0x43434242 0x43434343
0xbffff3cc: 0x43434343 0x44444444 *0x44444444* 0xbf004444
0xbffff3dc: 0xb7e9ec76 0x00000001 0xbffff484 0xbffff48c
0xbffff3ec: 0xb7fe18c8 0xbffff440 0xffffffff 0xb7ffeff4
The above is what the stack looks like just before returning from the function. As you can see, we've overwritten the return address with those excess 'D's. Result. Let's finish up:
(gdb) x/li $eip
0x8048411 <return_input+29>: ret
(gdb) stepi
Cannot access memory at address 0x44444448
Um, eh? This 0x44444448
has come from the arse-end of nowhere. Somehow gcc has modified the return address just before we return. Thanks.
Any ideas? Am I correct in assuming gcc has done its own internal checking whether the return address is valid. And if not, it's stuck some crap in it to prevent us from crafting a nasty return address?
Any way around this? I've tried everything here - http://www.madhur.co.in/blog/2011/08/06/protbufferoverflow.html. Same result.
Upvotes: 1
Views: 564
Reputation: 7348
This is the expected result—a page fault. Your program ist stopped by the operating system because you are accessing virtual memory that is not assigned to any physical memory.
The message you see is just the debugger notifying you of that fact.
Upvotes: 4