首页
社区
课程
招聘
[翻译]查找Windows内存泄露的几种方法
发表于: 2017-12-26 13:18 13491

[翻译]查找Windows内存泄露的几种方法

2017-12-26 13:18
13491

Windows内存泄露问题和很多二进制漏洞类似,比如说uaf 释放后重引用,那么windows内存泄露则属于分配后未释放或者未使用,造成的危害虽然远不及通俗的二进制漏洞,但是在企业角度看,按数十小时级的工作时间单位来说,造成服务中断,运行效率减慢,这些问题也是普遍存在的,区别在于是否明显和带来影响,和传统的二进制漏洞比较,发现的周期更长(Fuzz除外),找出问题的成本要更高,却又是不可忽略的一个问题

下文来自:https://docs.microsoft.com/en-us/windows-hardware/drivers/debugger/finding-a-memory-leak

如果Windows性能随着时间的推移而降低,并且怀疑可能涉及内存泄漏,则本节中介绍的技术可以指示是否存在内存泄漏。它不会告诉你泄漏的来源是什么,也不知道是用户模式还是内核模式。

从开始菜单搜索 ‘性能监视器’  添加以下计数器:

将更新时间更改为600秒,以捕获一段时间内的泄漏图。您可能还想将数据记录到文件以供日后检查。启动你认为是造成泄漏的应用程序进行测试,允许应用程序在测试运行这段时间不受干扰, 在这段时间内不要使用目标计算机,泄漏通常很慢,可能需要几个小时才能检测到,等待几个小时后再判断是否发生泄漏,监视性能监视器计数器。在测试开始后,计数器值将快速变化,并且可能需要一段时间才能使内存池值达到稳定状态。用户模式内存泄漏始终位于可分页池中,并导致池分页字节计数器和页面文件使用率计数器随着时间的推移稳步增加。内核模式内存泄漏通常耗尽非分页池,导致池非分页字节计数器增加,尽管可分页内存也可能受到影响。偶尔这些计数器可能会显示误报,因为应用程序正在缓存数据。





1)使用poolmon查找内核模式的内存泄露

如果您怀疑存在内核模式的内存泄漏,最简单方法是使用PoolMon来确定哪个pool tag 是与泄漏关联的

PoolMon(Poolmon.exe)按池标记名称(pool tag)监视池的内存使用情况,此工具包含在Windows驱动程序工具包(WDK)中。有关完整说明,请参阅WDK文档中的PoolMon。

在Windows 2000和Windows XP上,您必须先使用GFlags启用池标记。Windows调试工具中包含GFlags。启动GFlags,选择“ 系统注册表”选项卡,选中“ 启用池标记”框,然后单击“ 应用”。您必须重新启动Windows才能使此设置生效。有关更多详细信息,请参阅GFlags。在Windows Server 2003和更高版本的Windows上,池标记始终处于启用状态。

PoolMon头显示总共分页和非分页池字节。这些列显示每个池标记的池使用情况。显示每隔几秒自动更新一次。例如:

PoolMon具有根据各种标准对输出进行排序的命令键。按下与每个命令关联的字母,以重新排序数据。每个命令都需要几秒钟的工作。排序命令包括:


要使用PoolMon实用工具查找内存泄漏,请执行以下过程:

启动PoolMon。

如果您确定在非分页池中发生泄漏,请按P一次,如果您确定它在分页池中发生,请按P两次。如果你不知道,不要按P键,这两种都包括在内。

按B按最大字节使用排序显示。

开始你的测试。采取屏幕截图并将其复制到记事本。

每半小时生成一个新的屏幕截图。通过比较屏幕截图,确定哪些标签的字节正在增加。

停止测试并等待几个小时。在这个时候有多少标签被释放了?

通常情况下,应用程序达到稳定运行状态后,会以大致相同的速率分配内存和空闲内存,如果分配内存比释放内存更快,内存的使用将随着时间的推移而增长。这通常表示存在内存泄漏。

确定哪个池标签与泄漏相关后,可能会显示您需要了解的泄漏信息。如果您需要确定分配例程的哪个特定实例导致泄漏,请参阅使用内核调试器查找内核模式内存泄漏。

2)使用内核调试器来查找内核模式的内存泄露

在Windows 2000和Windows XP上,您必须先使用GFlags启用池标记。Windows调试工具中包含GFlags。启动GFlags,选择“ 系统注册表”选项卡,选中“ 启用池标记”框,然后单击“ 应用”。您必须重新启动Windows才能使此设置生效。在Windows Server 2003和更高版本的Windows上,池标记始终处于启用状态。

要确定哪个池标签与泄漏相关联,通常最简单的方法是使用PoolMon工具进行此步骤。有关详细信息,请参阅上面使用poolmon来查找内核模式的内存泄露

或者,您可以使用内核调试器查找与大型池分配关联的标记,请按照以下步骤操作

1.使用.reload(重新加载模块)命令重新加载所有模块。

2.使用!poolused扩展。包含标记“4”以便按页面内存使用排序输出:

3. 确定哪个池标记与最大的内存使用相关联。在这个例子中,使用标签“Abc”的驱动程序正在使用最多的内存 – 几乎是34 MB。所以内存泄漏最有可能在这个驱动程序中。

确定与泄漏相关联的池标签后,请按照以下过程找到泄漏本身:

1.使用ed(Enter Values)命令来修改全局系统变量PoolHitTag的值。每当使用与其值匹配的池标记时,此全局变量会导致调试器中断。

2.将PoolHitTag设置为等于您怀疑是内存泄漏源的标记。模块名称“nt”应该被指定为更快的符号解析。标签值必须以little-endian格式输入(即向后)。由于池标签总是四个字符,这个标签实际上      是Abc空间,而不仅仅是Abc。所以使用下面的命令:


[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)

收藏
免费 1
支持
分享
最新回复 (3)
雪    币: 341
活跃值: (138)
能力值: ( LV7,RANK:110 )
在线值:
发帖
回帖
粉丝
2
本地保存!
2017-12-26 16:58
0
雪    币: 350
活跃值: (87)
能力值: ( LV7,RANK:110 )
在线值:
发帖
回帖
粉丝
3
内容不错啊
2017-12-26 17:35
0
雪    币: 292
活跃值: (810)
能力值: ( LV6,RANK:90 )
在线值:
发帖
回帖
粉丝
4
学习了,感谢翻译
2017-12-28 12:50
0
游客
登录 | 注册 方可回帖
返回
//