标题: 快速定位出问题的源码行 创建: 2006-02-17 14:34 更新: 链接: https://scz.617.cn/misc/200602171802.txt -------------------------------------------------------------------------- 目录: ☆ 问题程序 ☆ cdb.exe ☆ 快速定位出问题的源码行 ☆ 参考资源 -------------------------------------------------------------------------- ☆ 问题程序 -------------------------------------------------------------------------- /* * For x86/EWindows XP SP1 & VC 7 * cl x.c /Fex.exe /nologo /Os /G6 /Gz /Gs65536 /W3 /WX /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /link /RELEASE * cl x.c /Fex.exe /Zi /Fax.asm /Fdx.pdb /nologo /Od /Oi /Gz /Gs65536 /W3 /WX /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /link /RELEASE */ #include #include #include #include #pragma comment( linker, "/INCREMENTAL:NO" ) #pragma comment( linker, "/merge:.rdata=.text" ) #pragma comment( linker, "/subsystem:console" ) static void * Calloc ( size_t nelem, size_t elsize ) { void *buf = NULL; if ( NULL == ( buf = calloc( nelem, elsize ) ) ) { fprintf( stderr, "calloc() failed\n" ); exit( EXIT_FAILURE ); } return( buf ); } /* end of Calloc */ static void usage ( char *arg ) { fprintf ( stderr, "Usage: %s \n", arg ); exit( EXIT_FAILURE ); } /* end of usage */ static void vulfunc ( unsigned int len_a, unsigned int len_b ) { unsigned char *buf_a = NULL; unsigned char *buf_b = NULL; buf_a = ( unsigned char * )Calloc( len_a, 1 ); buf_b = ( unsigned char * )Calloc( len_b, 1 ); CopyMemory( buf_a, buf_b, len_a ); free( buf_b ); buf_b = NULL; free( buf_a ); buf_a = NULL; return; } /* end of vulfunc */ int __cdecl main ( int argc, char * argv[] ) { unsigned int len_a, len_b; if ( 3 != argc ) { usage( argv[0] ); } len_a = ( unsigned int )strtoul( argv[1], NULL, 0 ); len_b = ( unsigned int )strtoul( argv[2], NULL, 0 ); vulfunc( len_a, len_b ); return( EXIT_SUCCESS ); } /* end of main */ #if 0 > x.exe 0xE000 8 #endif -------------------------------------------------------------------------- vunlfunc()调用CopyMemory()时没有检查第三形参len_a的有效性,尽管buf_a足够大, 但buf_b不够大,内存复制过程中可能出现内存访问违例。 接下来就以x.c为例讲解如何利用cdb.exe快速定位出问题的源码行。 ☆ cdb.exe cdb.exe来自"Debugging Tools for Windows"([1]),这个程序一直在更新中,请随 时下载最新版本。 > cdb.exe -version cdb version 6.6.0003.5 ☆ 快速定位出问题的源码行 关键就两点,一是编译时指定"/Zi /Fd... /Od /Oi",二是用"lsa eip 0,1"定位源 码行。 > cl x.c /Fex.exe /Zi /Fdx.pdb /nologo /Od /Oi /Gz /Gs65536 /W3 /WX /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /link /RELEASE > cdb.exe -g -G -hd -o -lines x.exe 0xE000 8 (f18.898): Access violation - code c0000005 (first chance) First chance exceptions are reported before any exception handling. This exception may be expected and handled. eax=00370fe8 ebx=7ffdf000 ecx=00002ffa edx=0000e000 esi=00373000 edi=00412060 eip=00401cba esp=0012febc ebp=0012fecc iopl=0 nv up ei pl nz na po nc cs=001b ss=0023 ds=0023 es=0023 fs=0038 gs=0000 efl=00010206 x!vulfunc+0x40: 00401cba f3a5 rep movsd ds:00373000=???????? es:00412060=00000000 0:000> lsa eip 0,1 > 45: CopyMemory( buf_a, buf_b, len_a ); 0:000> ls 40,10 40: unsigned char *buf_a = NULL; 41: unsigned char *buf_b = NULL; 42: 43: buf_a = ( unsigned char * )Calloc( len_a, 1 ); 44: buf_b = ( unsigned char * )Calloc( len_b, 1 ); 45: CopyMemory( buf_a, buf_b, len_a ); 46: free( buf_b ); 47: buf_b = NULL; 48: free( buf_a ); 49: buf_a = NULL; 0:000> 可用如下命令查看当前调用栈回溯: 0:000> kp (与kP类似,单行显示) ChildEBP RetAddr 0012fecc 00401c50 x!vulfunc(unsigned int len_a = 0xe000, unsigned int len_b = 8)+0x40 [y:\x\x.c @ 45] 0012fee4 00402493 x!main(int argc = 3, char ** argv = 0x00371408)+0x50 [y:\x\x.c @ 65] 0012ffc0 77e8141a x!mainCRTStartup(void)+0x170 [f:\vs70builds\9466\vc\crtbld\crt\src\crt0.c @ 259] 0012fff0 00000000 kernel32!BaseProcessStart+0x23 0:000> kP (与kp类似,多行显示) ChildEBP RetAddr 0012fecc 00401c50 x!vulfunc( unsigned int len_a = 0xe000, unsigned int len_b = 8)+0x40 [y:\x\x.c @ 45] 0012fee4 00402493 x!main( int argc = 3, char ** argv = 0x00371408)+0x50 [y:\x\x.c @ 65] 0012ffc0 77e8141a x!mainCRTStartup(void)+0x170 [f:\vs70builds\9466\vc\crtbld\crt\src\crt0.c @ 259] 0012fff0 00000000 kernel32!BaseProcessStart+0x23 0:000> kb (固定显示三个形参) ChildEBP RetAddr Args to Child 0012fecc 00401c50 0000e000 00000008 0000e000 x!vulfunc+0x40 [y:\x\x.c @ 45] 0012fee4 00402493 00000003 00371408 00371430 x!main+0x50 [y:\x\x.c @ 65] 0012ffc0 77e8141a 00000000 00000000 7ffdf000 x!mainCRTStartup+0x170 [f:\vs70builds\9466\vc\crtbld\crt\src\crt0.c @ 259] 0012fff0 00000000 00402323 00000000 78746341 kernel32!BaseProcessStart+0x23 0:000> kn (显示帧号) # ChildEBP RetAddr 00 0012fecc 00401c50 x!vulfunc+0x40 [y:\x\x.c @ 45] 01 0012fee4 00402493 x!main+0x50 [y:\x\x.c @ 65] 02 0012ffc0 77e8141a x!mainCRTStartup+0x170 [f:\vs70builds\9466\vc\crtbld\crt\src\crt0.c @ 259] 03 0012fff0 00000000 kernel32!BaseProcessStart+0x23 0:000> r ebp ebp=0012fecc 0:000> dd ebp l 4 0012fecc 0012fee4 00401c50 0000e000 00000008 ☆ 参考资源 [ 1] Debugging Tools for Windows - Overview http://www.microsoft.com/whdc/ddk/debugging/default.mspx Install Debugging Tools for Windows 32-bit Version http://www.microsoft.com/whdc/devtools/debugging/installx86.mspx