2.4.3 Stack overrun/corruption
另外一种内存问题是Stack overrun和Stack corruption。Stack overrun很简单,一般是递归函数缺少结束条件导致,函数调用过深从而把stack地址用光,比如下面的代码:
只要在调试器里重现问题,调试器立刻就会收到Stack overflow Exception。检查callstack就可以立刻看出问题所在:
0:001> g (cd0.4b0): Stack overflow - code c00000fd (first chance) First chance exceptions are reported before any exception handling. This exception may be expected and handled. eax=cccccccc ebx=7ffdd000 ecx=00000000 edx=10312d18 esi=0012fe9c edi=00033130 eip=004116f9 esp=00032f9c ebp=0003305c iopl=0 nv up ei pl nz na po nc cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00010206 *** WARNING: Unable to verify checksum for c:\Documents and Settings\Li Xiong\My Documents\My code\MyTest\debug\MyTest.exe MyTest!foo+0x9: 004116f9 53 push ebx 0:000> k ChildEBP RetAddr 0003305c 00411713 MyTest!foo+0x9 00033130 00411713 MyTest!foo+0x23 00033204 00411713 MyTest!foo+0x23 000332d8 00411713 MyTest!foo+0x23 000333ac 00411713 MyTest!foo+0x23 00033480 00411713 MyTest!foo+0x23 00033554 00411713 MyTest!foo+0x23 00033628 00411713 MyTest!foo+0x23 000336fc 00411713 MyTest!foo+0x23 000337d0 00411713 MyTest!foo+0x23 000338a4 00411713 MyTest!foo+0x23 00033978 00411713 MyTest!foo+0x23 00033a4c 00411713 MyTest!foo+0x23 |
第二种情况,Stack corruption往往是Stack buffer overflow导致的。这样的bug不单单会造成程序崩溃,还会严重威胁到系统安全性。在网上搜索Stack buffer overflow,可以看到无数用Stack buffer进行攻击的例子。
在当前的计算机架构上,Stack是保存运行信息的地方。当Stack损坏后,当前执行情况的所有信息都丢失了,所以调试器在这种情况下没有用武之地。比如下面的代码:
void killstack() { char c; char *p=&c; for(int i=10;i<=100;i++) *(p+i)=0; } int main(int, char*) { killstack(); return 0; }
|
在VS2005中用下面的参数,在debug模式下编译:
/Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_UNICODE" /D "UNICODE" /Gm /EHsc /RTC1 /MDd /Gy /Fo"Debug\\" /Fd"Debug\vc80.pdb" /W3 /nologo /c /Wp64 /Zi /TP /errorReport:prompt |
在调试器中运行,看到的结果是:
0:000> g ModLoad: 76290000 762ad000 C:\WINDOWS\system32\IMM32.DLL ModLoad: 62d80000 62d89000 C:\WINDOWS\system32\LPK.DLL ModLoad: 75490000 754f1000 C:\WINDOWS\system32\USP10.dll (1d0.1504): Access violation - code c0000005 (first chance) First chance exceptions are reported before any exception handling. This exception may be expected and handled. eax=0012ff5b ebx=7ffda000 ecx=fffffffb edx=0012ffbf esi=00000000 edi=00000000 eip=000000f8 esp=0012ff68 ebp=0012ff68 iopl=0 nv up ei pl zr na po nc cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00010246 000000f8 ?? ??? 0:000> kb ChildEBP RetAddr Args to Child WARNING: Frame IP not in any known module. Following frames may be wrong. 0012ff64 00000000 00000000 00000000 00000000 0xf8 0:000> dds esp 0012ff68 00000000 0012ff6c 00000000 0012ff70 00000000 0012ff74 00000000 0012ff78 00000000 0012ff7c 00000000 0012ff80 00000000 0012ff84 00000000 0012ff88 00000000 0012ff8c 00000000 0012ff90 00000000 0012ff94 00000000 0012ff98 00000000 0012ff9c 00000000 0012ffa0 00000000 0012ffa4 00000000 0012ffa8 00000000 0012ffac 00000000 0012ffb0 00000000 0012ffb4 00000000 0012ffb8 00000000 0012ffbc 00000000 0012ffc0 0012fff0 0012ffc4 77e523cd kernel32!BaseProcessStart+0x23
|
在Windbg里面看到EIP,EBP都指向非法地址,callstack的信息已经被冲毁,根本找不到任何线索进行调试。对于Stack corruption,行之有效的方法是首先对问题作大致定位,然后检查相关函数,在可疑函数中添加代码写log文件。当问题发生后从log文件中找到线索。
【责任编辑:
雪花 TEL:(010)68476606】