Debug Stack Overflow的问题

例子代码如下:

#include <stdio.h>
#include <stdlib.h>

void return_input()
{
    char array[20];
    gets(array);
    printf("%s\n", array);
}

int main(int argc, char **argv)
{
    return_input();
}

gcc -fno-stack-protector -g overflow.c -o overflow

gdb载入 overflow, 设置断点:

(gdb) list
4	void return_input()
5	{
6	    char array[20];
7	    gets(array);
8	    printf("%s\n", array);
9	}
10	
11	int main(int argc, char **argv)
12	{
13	    return_input();
(gdb) break 13
Breakpoint 1 at 0x8048428: file overflow.c, line 13.
(gdb) run
Starting program: /home/charles/overflow 

Breakpoint 1, main (argc=1, argv=0xbffff354) at overflow.c:13
13	    return_input();
观察汇编:

(gdb) disassemble 
Dump of assembler code for function main:
   0x08048422 <+0>:	push   %ebp
   0x08048423 <+1>:	mov    %esp,%ebp
   0x08048425 <+3>:	and    $0xfffffff0,%esp
=> 0x08048428 <+6>:	call   0x8048404 <return_input>
   0x0804842d <+11>:	leave  
   0x0804842e <+12>:	ret    
End of assembler dump.
(gdb) disassemble  return_input 
Dump of assembler code for function return_input:
   0x08048404 <+0>:	push   %ebp
   0x08048405 <+1>:	mov    %esp,%ebp
   0x08048407 <+3>:	sub    $0x38,%esp
   0x0804840a <+6>:	lea    -0x1c(%ebp),%eax
   0x0804840d <+9>:	mov    %eax,(%esp)
   0x08048410 <+12>:	call   0x8048310 <gets@plt>
   0x08048415 <+17>:	lea    -0x1c(%ebp),%eax
   0x08048418 <+20>:	mov    %eax,(%esp)
   0x0804841b <+23>:	call   0x8048320 <puts@plt>
   0x08048420 <+28>:	leave  
   0x08048421 <+29>:	ret    
End of assembler dump.
开始单步调试,观察sp的值:

(gdb) print /x $esp
$1 = 0xbffff2b0
(gdb) print /x $eip
$2 = 0x8048428
(gdb) stepi
return_input () at overflow.c:5
5	{
(gdb) print /x $esp
$3 = 0xbffff2ac
(gdb) x  $esp
0xbffff2ac:	0x0804842d
(gdb) 

0x0804842d 正是 main()里面,call  return_input指令的下一个指令的地址,也就是 call的返回地址

从return_input的汇编代码可以看到,这个函数的  stack frame 大小为 64字节,。

单步执行到 call gets的指令,再观察:

gdb) print /x &array
$6 = 0xbffff28c
(gdb) x $esp
0xbffff270:	0xbffff28c
(gdb) x $eax
0xbffff28c:	0x08048451
此时,eax指向了 array的首地址。 array可用的区域是28字节,加上末尾的栈上保存的 EBP和 返回地址,array刚好处于64字节的中点。

Debug Stack Overflow的问题_第1张图片

(gdb) x /32xw 0xbffff28c
0xbffff28c:	0x08048451	0xffffffff	0xb7e4e196	0xb7fc0ff4
0xbffff29c:	0xb7e4e225	0xb7fed280	0x00000000	0xbffff2b8
0xbffff2ac:	0x0804842d	0x08048430	0x00000000	0x00000000
0xbffff2bc:	0xb7e344d3	0x00000001	0xbffff354	0xbffff35c
这个时候,如果输入 超过 28个字符,就会覆盖stack 上的 EBP和函数返回地址:

(gdb) next
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
8	    printf("%s\n", array);
(gdb) x /32xw 0xbffff28c
0xbffff28c:	0x41414141	0x41414141	0x41414141	0x41414141
0xbffff29c:	0x41414141	0x41414141	0x41414141	0x41414141
0xbffff2ac:	0x41414141	0x08048400	0x00000000	0x00000000
0xbffff2bc:	0xb7e344d3	0x00000001	0xbffff354	0xbffff35c
0xbffff2cc:	0xb7fdc858	0x00000000	0xbffff31c	0xbffff35c
0xbffff2dc:	0x00000000	0x0804822c	0xb7fc0ff4	0x00000000
0xbffff2ec:	0x00000000	0x00000000	0xa4ce7c3a	0x9da2d82a
0xbffff2fc:	0x00000000	0x00000000	0x00000000	0x00000001
(gdb) 

可以看到,函数返回地址已经被覆盖掉了。

(gdb) next
0x41414141 in ?? ()
(gdb) info registers 
eax            0x25	37
ecx            0xffffffff	-1
edx            0xb7fc28b8	-1208211272
ebx            0xb7fc0ff4	-1208217612
esp            0xbffff2b0	0xbffff2b0
ebp            0x41414141	0x41414141
esi            0x0	0
edi            0x0	0
eip            0x41414141	0x41414141
eflags         0x286	[ PF SF IF ]
cs             0x73	115
ss             0x7b	123
ds             0x7b	123
es             0x7b	123
fs             0x0	0
gs             0x33	51

当从这个函数返回后, E IP的值也变成了填充的数值了

(gdb) bt
#0  0x41414141 in ?? ()
#1  0x08048400 in frame_dummy ()
Backtrace stopped: previous frame inner to this frame (corrupt stack?)


你可能感兴趣的:(Debug Stack Overflow的问题)