【发布时间】:2014-01-13 02:12:53
【问题描述】:
我编写了一个小程序来了解堆栈和缓冲区溢出是如何工作的。
#include <stdio.h>
#include <string.h>
int main(int argc, char *argv[]) {
char array[20];
printf("-=-=-=-=-=-=-=-=-=-= The prize pool is 2000$ -=-=-=-=-=-=-=-=-=--=\n");
printf("-=-=-=-=-=- Whatever you supply goes to array! -=-=-=-=-=-=-=\n");
strcpy(array, argv[1]);
printf("Array now is %p \n\n", &array);
}
我正在运行提供的程序
(gdb) run `perl -e 'print "A"x20 . "\x95\x84\x04\x08"x4'`
The program being debugged has been started already.
Start it from the beginning? (y or n) y
Starting program: /root/tests/c-tests/myownexamples/simpleover2 `perl -e 'print "A"x20 . "\x95\x84\x04\x08"x4'`
通过在最后一个 printf 中设置断点,我们可以看到:
Breakpoint 3, main (argc=134513813, argv=0x8048495 <main+65>)
at simpleover2.c:19
19 printf("Array now is %p \n\n", &array);
(gdb) info frame
Stack level 0, frame at 0xbffff4a0:
eip = 0x8048489 in main (simpleover2.c:19); saved eip **0x8048495**
source language c.
Arglist at 0xbffff498, args: argc=134513813, argv=0x8048495 <main+65>
Locals at 0xbffff498, Previous frame's sp is 0xbffff4a0
Saved registers:
ebp at 0xbffff498, eip at 0xbffff49c
(gdb) disassemble main
Dump of assembler code for function main:
0x08048454 <+0>: push ebp
0x08048455 <+1>: mov ebp,esp
0x08048457 <+3>: sub esp,0x1c
0x0804845a <+6>: mov DWORD PTR [esp],0x8048560
0x08048461 <+13>: call 0x8048384 <puts@plt>
0x08048466 <+18>: mov DWORD PTR [esp],0x80485a4
0x0804846d <+25>: call 0x8048384 <puts@plt>
0x08048472 <+30>: mov eax,DWORD PTR [ebp+0xc]
0x08048475 <+33>: add eax,0x4
0x08048478 <+36>: mov eax,DWORD PTR [eax]
0x0804847a <+38>: mov DWORD PTR [esp+0x4],eax
0x0804847e <+42>: lea eax,[ebp-0x14]
0x08048481 <+45>: mov DWORD PTR [esp],eax
0x08048484 <+48>: call 0x8048364 <strcpy@plt>
=> 0x08048489 <+53>: mov eax,0x80485e2
0x0804848e <+58>: lea edx,[ebp-0x14]
0x08048491 <+61>: mov DWORD PTR [esp+0x4],edx
0x08048495 <+65>: mov DWORD PTR [esp],eax
0x08048498 <+68>: call 0x8048374 <printf@plt>
0x0804849d <+73>: leave
0x0804849e <+74>: ret
所以我已经覆盖了 RET 地址,但地址位于当前堆栈帧中。
逐步执行直到离开和返回指令
(gdb) nexti
0x0804849e 21 }
(gdb) i r eip
eip 0x804849e 0x804849e <main+74>
(gdb) i r eip
eip 0x804849e 0x804849e <main+74>
(gdb) nexti
0x08048495 in main (argc=1435550665, argv=0xc35de589) at simpleover2.c:19
19 printf("Array now is %p \n\n", &array);
(gdb) i r eip
eip 0x8048495 0x8048495 <main+65>
我们看到执行 INDEED 到那里并跟随 nexti 我们得到:
(gdb) nexti
0x08048498 19 printf("Array now is %p \n\n", &array);
(gdb) i r eip
eip 0x8048498 0x8048498 <main+68>
(gdb) nexti
Program received signal SIGSEGV, Segmentation fault.
0xb7eeae97 in strchrnul () from /lib/tls/i686/cmov/libc.so.6
那么为什么会出现段错误?而且它看起来确实是第二次调用 printf() 但它不会出现..
./simpleover2 `perl -e 'print "A"x20 . "\x95\x84\x04\x08"x4'`
-=-=-=-=-=-=-=-=-=-= The prize pool is 2000$ -=-=-=-=-=-=-=-=-=--=
-=-=-=-=-=- Whatever you supply goes to array! -=-=-=-=-=-=-=
Array now is 0xbf8ed894
Segmentation fault
再一次,为什么它没有 printf() 显示,因为 ret 指向那个?以及自从执行了实际弹出整个堆栈帧的 leave 和 ret 指令后,如何继续执行?
【问题讨论】:
-
不清楚你的问题是什么。您正在打印
array的地址。你预计会发生什么? -
我预计打印 2 次而不是 1 次,因为执行再次转到 0x8048495 地址
标签: c++ c gdb stack stack-overflow