windbg简单调试内存泄漏
0x00
首先使用 gflags 设置heap堆栈追踪参数: Gflags.exe /i +ust 设置完成后后,我们可以在 “HKEY_LOCAL_MACHINESOFTWAREMicrosoftWindows NTCurrentVersionImage File Execution Options<Image Name>” GlobalFlag 中看到刚才设置的参数。 设置完不需要重启机器,直接启动需要跟踪的exe。 对于需要跟踪的exe可以使用windbg live调试或者dump调试。
0x01
使用 !heap –s 获取堆分配的情况,找到可疑的堆。 使用 !heap –stat –h ,获取特定堆各种size分配的block数量。注意,这里的heap handle就是 !heap –s 获取的第一列参数,实际上就是 _HEAP 的地址 这里我们随便找一个堆分析。 接下来,我们假设大小为 10ada0出现泄漏(一般是整体占比比较大的size在泄漏)。我们对这个size进行分析: 注意,这个命令会查找系统中所有堆的分配情况,所以列出的条目可能不只有你需要查看的堆。具体这个条目在不在需要分配的堆上,可以查看 _HEAP @ 字段。 接下来,我们检查当前条目的分配堆栈,这里需要用到 UserPtr字段: 到这里,这个堆分配的堆栈就已经找到了。
0x02
回到刚才 !heap –s之后,我们看到下图: 其中 Heap列对应的地址即 ntdll!_HEAP的地址 其中有两个字段: +0x04c EncodeFlagMask : 0x100000 +0x050 Encoding : _HEAP_ENTRY
其中 EncodeFlagMask 表示是否对 _HEAP_ENTRY的数据进行异或处理。 我们看看 +0x50(Encoding字段)的数据: 在_HEAP结构中我们可以看到第一个有效的 _HEAP_ENTRY 地址为:11480498 通过 !heap –x 命令获取这个entry的信息: 但是我们 dt _HEAP_ENTRY 之后会发现长度数据是错乱的: 这里实际就是 Encoding的用处了,上面对 Encoding的打印,我们看到前四个字节为: 0x 57bf3d15,后四个字节为 0000a0e7。 我们对 11480489同样做dd操作: 头四个字节为 0x51be3d12,后四个字节为 4200a074。 分别作异或处理: 其中的低两位是size字段,32位上粒度为8,64位上粒度为16。 因此第一个size = 7 * 8 = 56 = 0x38 也就是我们上图打印的size 第二个size = 0x93 * 8 = 0x498,就是上图的PreSize.
0x03
!heap –a 可以查看heap的所有block信息 !heap –x 可以查看某个block的信息
0x04
完成调试后,使用 Gflags.exe /i -ust 删除调试选项。