gflags调试访问越界
2011-9-27
烛秋
昨天、今天调dump,对windbg相当的不熟悉,但也慢慢的知道了一些常用的命令,几周前听说到有gflags这样个工具,今天正好测试下。
gflags.exe是<Debugging Tools for Windows>中的一个小工具。
安装下载链接:http://msdn.microsoft.com/en-us/windows/hardware/gg463016
安装好之后,把gflags所在文件夹(这里边还有很多好东西)设置到环境变量的path中,方便命令行使用。(我的电脑-->右键-->属性-->高级-->环境变量-->系统变量-->path)
在命令行cmd里输入:cdb -iae 。
设置cdb为默认JIT(just in time) debugger,这样在命令行执行遇到崩溃的时候就会停下来。
(本文最后的学习资料相当好)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
|
测试程序:
///
int
main()
{
char
*p =
new
char
[10];
for
(
int
i = 0; i != 11; ++i)
p[i] = i;
return
0;
}
///
|
这是一个非常简单的越界程序,当i = 10时,访问越界了。但是如果不采用测试工具,这里是不会发生崩溃的。一般情况下,程序获取的空间是16字节对齐的,所以p[10]访问到的是对齐之后增加的空间,不会导致越界崩溃。但这是隐患,为了使隐患尽早被发现,使用工具是很好的选择。
gflags用来跟踪这个程序的执行,可以设置每一次new分配的堆空间都单独的占有一块空间,并且这个空间相邻的位置被设置为不可访问的,一旦访问越界立即触发访问无效错误,尽早的触发崩溃。
测试过程如下:
1、用vc编译出release版本的可执行文件:test.exe。(注意:不是debug版本)
2、用gflag注册需要监控的可执行文件test.exe。
在cmd下,输入命令如下:gflags /p /enable test.exe /full /unaligned。
回车,显示如下信息:
*************************************************************************************
path: SOFTWARE\Microsoft\Windows NT\CurrentVersion\Image File Execution Options
test.exe: page heap enabled。
*************************************************************************************
这个时候,已经把要监控的test.exe注册上了。
/p /enable是必备的。
/full说明分配的空间是独占的,并且相邻的是不可访问的空间。
/unaligned说明分配空间时不对齐,保证一旦越界立即发现,不会因为内存对齐而隐藏起来。
3、接着双击执行test.exe,这个时候,会中断下来:
*************************************************************************************
(17f8.5d0): Access violation - code c0000005 (!!! second chance !!!)
eax=0161eff6 ebx=7c80ac61 ecx=0000000a edx=015c5000 esi=00000002 edi=00000a28
eip=00401010 esp=0012ff74 ebp=0012ffc0 iopl=0 nv up ei ng nz ac pe cy
cs=001b ss=0023 ds=0023 es=0023 fs=003b gs=0000 efl=00000297
WindbgTest!main+0x10:
00401010 880c01 mov byte ptr [ecx+eax],cl ds:0023:0161f000=??
*************************************************************************************
如果把exe放到windbg里执行,用命令:!address,可以发现eax是可以读写的,
eax+ecx是不可访问的:
*************************************************************************************
0:000> !address eax
015c0000 : 0161e000 - 00001000
Type 00020000 MEM_PRIVATE
Protect 00000004 PAGE_READWRITE
State 00001000 MEM_COMMIT
Usage RegionUsagePageHeap
Handle 015c1000
0:000> !address eax+ecx
015c0000 : 0161f000 - 000a1000
Type 00020000 MEM_PRIVATE
Protect 00000001 PAGE_NOACCESS
State 00001000 MEM_COMMIT
Usage RegionUsagePageHeap
Handle 015c1000
*************************************************************************************
4、取消跟踪:
通过/p命令可以看到当前跟踪的程序有哪些:
*************************************************************************************
C:\Documents and Settings\cs_wuyg>gflags /p
path: SOFTWARE\Microsoft\Windows NT\CurrentVersion\Image File Execution Options
player.exe: page heap enabled with flags (full traces )
program: page heap enabled with flags (full unaligned traces )
test.exe: page heap enabled with flags (full unaligned traces )
windbgtest.exe: page heap enabled with flags (full unaligned traces )
*************************************************************************************
通过/p /disble取消跟踪:情况如下:
*************************************************************************************
C:\Documents and Settings\cs_wuyg>gflags /p /disable player.exe
path: SOFTWARE\Microsoft\Windows NT\CurrentVersion\Image File Execution Options
player.exe: page heap disabled
C:\Documents and Settings\cs_wuyg>gflags /p
path: SOFTWARE\Microsoft\Windows NT\CurrentVersion\Image File Execution Options
program: page heap enabled with flags (full unaligned traces )
test.exe: page heap enabled with flags (full unaligned traces )
windbgtest.exe: page heap enabled with flags (full unaligned traces )
*************************************************************************************
发现program是无法取消的,很奇怪。另外,发现注册表里相应的项目在disable之后,仍然存在,只不过一些键值被删除掉了。
同事跟我说,不使用gflags的时候,最好把注册表里的项目删除,gflags对机器性能的影响很大。
注册表的位置是:HKEY_LOCAL_MACHINE/SOFTWARE/Microsoft/WindowsNT/Image File Execution Options
5、注意事项
一、gflags要跟踪的程序,是把这个程序的名称记录到了注册表中,在设置的时候不需要可执行文件的路径名,只需要文件名称。
二、可以使用命令行,也可以使用GUI界面。GUI界面中的前两个TAB页面是对所有的可执行程序都有效的。第三个才是设置想要跟踪的程序。
三、还有其它更强大的工具。
6、总结
通过这个工具的简单使用,就可以很快发现代码中有访问越界。
在大工程下,是否也非常有用,现在还没实践过。
使用gflags,并且在VS下调试,有源代码更方便。
7、附今天用上的几个windbg命令:
1\ !analyze -v
2\ kv kf kb
3\ ~*k
4\ .ecxr
5\ lmvm xxx.exe
分析dump的时候,看调用堆栈是从下往上看的。
调用堆栈前部分的数值一部分是参数,一部分是无用的信息。
设置好source file path之后,.ecxr命令可以看到当前的寄存器信息,还可以看到源代码。
发现很多的崩溃是由于空指针、野指针导致的。而空指针、野指针是由于多线程导致卸载、装载重叠导致的。
学习资料:
http://www.cppblog.com/sandy/archive/2007/03/13/19723.html
http://blog.csdn.net/ayw_hehe/article/details/6796333
http://www.cppblog.com/sandy/archive/2008/09/27/62877.html
http://www.cnblogs.com/awpatp/archive/2011/01/01/1923913.html
http://blog.sina.com.cn/s/blog_484f16880100jrwj.html