注册 登录  
 加关注
   显示下一条  |  关闭
温馨提示!由于新浪微博认证机制调整,您的新浪微博帐号绑定已过期,请重新绑定!立即重新绑定新浪微博》  |  关闭

_

_

 
 
 

日志

 
 

检查内存越界错误  

2013-02-26 22:05:44|  分类: 默认分类 |  标签: |举报 |字号 订阅

  下载LOFTER 我的照片书  |

检查内存越界错误

?

第一步:

在命令行中运行PageHeap.Exe。如果你以前设置过启用Global Page Heap标志,那么你将看到一个列表,给出所有已经启用了的应用程序的名字,不含路径。

如下所示:

C:\\>pageheap

pgh.exe enabled

testSplit.exe enabled

第二步:

编译一个小程序,其中有如下代码:

void main()
{
int m_len = 5;
char *m_p = (char *)HeapAlloc (GetProcessHeap (), HEAP_ZERO_MEMORY, m_len);
m_p[m_len] = 0;
HeapFree (GetProcessHeap (),0, m_p);
}

Build出一个Debug版本。运行之,你看不到有任何异常的报告。

但其实m_p[m_len]=0这句话就是越界写了,因为只分配到了m_p[m_len-1]!这种情况就叫Dynamic memory overrun。用BoundsChecker是可以查到的。

这时,表面上看不出任何问题,但是一颗定时炸弹已经埋下了。

第三步:

在命令行中运行PageHeap /enable YourApplicationName.exe 0x01。

再运行一次不带参数的PageHeap,察看上面的命令是否生效。你的应用程序应该在启用的列表中。

注意:千万不要在YourApplication.Exe前面加上路径!!

0x01的含义在后面说明。

第四步:

再次运行你的程序。

你将会注意到在Output窗口的加载各种DLL之前,多了几句话:

Loaded exports for \'C:\\WINNT\\System32\\ntdll.dll\'
Page heap: process 0x57C created heap @ 00130000 (00230000, flags 0x1)
Loaded \'C:\\WINNT\\system32\\MFC42D.DLL\', no matching symbolic information found.
..
Loaded \'C:\\WINNT\\system32\\MSVCP60D.DLL\', no matching symbolic information found.
Page heap: process 0x57C created heap @ 00470000 (00570000, flags 0x1)
Loaded exports for \'C:\\WINNT\\system32\\imm32.dll\'

这就是Page Heap的监视机制在发挥作用!他告诉你你的堆00470000被创建出来了。

然后程序退出后,Output窗口有这么几句话表明一定有什么错误发生了:

Page heap: block @ 0015AFF8 is corrupted (reason 10)
Page heap: reason: corrupted suffix pattern
Page heap: process 0x57C destroyed heap @ 00471000 (00570000)[Page]
The thread 0x8A8 has exited with code 0 (0x0).

这说明在销毁堆00470000时遇到了麻烦,就是数据块0015AFF8被误用了,原因是误用了下标语法。看,说得多么清楚!也节省了许多翻来覆去查代码的工作!

PageHeap的使用中有几点值得注意:

1:启用PageHeap不能够影响正在运行中的应用程序。如果你需要启用一些正在运行且不能重启的程序的PageHeap,那请运行PageHeap启用后,重新启动机器。

2:要想查看PageHeap把信息放到哪里了,请打开你的注册表,来到HKLM\\SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Image File Execution Options

你将会看到你的应用程序也在这个项下面。你的应用程序的GlobalFlag被设置为了0x02000000,PageHeapFlags被设置为了0x01。

3: PageHeap的原理是这样,它在已分配的内存的后面放上几个守护字节(Guard Bytes),再跟上一个标记为PAGE_NOACCESS的内存页。这样,已分配内存的后面如果被重写了,那么守护字节就会被改变,于是当内存被释放 时,PageHeap就会引发一个AV(Access Violation)。大体上就是这样。所以只有最后释放这块问题内存时,才会有PageHeap的报告!这就是PageHeap的局限性吧。

参数0x01的含义:

FLAGS hex value (0x...) has the following structure:

B7-B0 Bit flags 1 - enable page heap

01 - enable page heap. If zero normal heap is used. In 99% of the cases you will want this to be set.
02 - collect stack traces (default on checked builds)
04 - minimize memory impact
08 - minimize randomly(1)/based on size range(0)
10 - catch backward overruns

看到了吗?你还可以设置参数为0x10,从而可以检查内存向前的越界写!

Gflags.Exe 是微软的Debugging Tools里面的工具。在Windows 2000的Resource Kit中也可以找得到。我们也可以用它来完成和PageHeap相同的任务。当然,Gflags.EXE还能做许许多多其他的事情。这里我们就不介绍了, 总之物超所值。

具体的使用办法是:

1) 运行Gflags.Exe;

2) 你将看到一个对话框。在”Image File”的编辑框中写下你的应用程序的名字,如YourApp.Exe。注意不要路径!

3) 选择”Image File Options”的单选钮;

4) 这时,你会看到对话框的内容突然一变。选中“Place heap

[NextPage]

allocations at ends of pages”前的复选框。

5) 点击Apply按钮。

这样,就达到了PageHeap的效果。现在运行你的程序,overwrite你的堆,就应该生成一个AV了!

  评论这张
 
阅读(313)| 评论(0)
推荐 转载

历史上的今天

在LOFTER的更多文章

评论

<#--最新日志,群博日志--> <#--推荐日志--> <#--引用记录--> <#--博主推荐--> <#--随机阅读--> <#--首页推荐--> <#--历史上的今天--> <#--被推荐日志--> <#--上一篇,下一篇--> <#-- 热度 --> <#-- 网易新闻广告 --> <#--右边模块结构--> <#--评论模块结构--> <#--引用模块结构--> <#--博主发起的投票-->
 
 
 
 
 
 
 
 
 
 
 
 
 
 

页脚

网易公司版权所有 ©1997-2017