2016-12-01 69 views
7

我正在调试潜在的GDI手柄泄漏。由于@Alois Kraus,有一个WinDbg script它执行句柄计数。我是否需要WOW64转储进行GDI句柄分析?

从我的调试会话especially for .NET中,我发现通常最好是32位进程的32位转储和64位进程的64位转储。

不幸的是,在收到2次崩溃转储后,脚本无法运行。展望深入,我发现该GdiSharedHandleTable是null在那些垃圾堆:

0:000> dt ntdll!_PEB GdiSharedHandleTable @$peb 
    +0x094 GdiSharedHandleTable : (null) 

现在,his website,阿洛伊斯提到

重要:如果您在64位操作系统上运行,你需要即使您调试32位应用程序,也要附加64位Windbg!

不幸的是,在32位故障转储中使用64位WinDbg并没有帮助。结果仍然是一样的。

现在,这里的一个理论:

  • 在32位过程中的一些DLL是64个DLL(请参阅Windows内部5,第3章, “系统机制,” 211页)
  • ntdll是一个(它在64位版本和32位版本中被加载两次)
  • 虽然GDI对象是用户对象(而不是内核对象),但它们仍然需要由操作系统绘制等。因此,可以要求他们在WOW64层管理
  • 这意味着,我必须有一个WOW64崩溃转储,使其工作

所以我的问题是:做我有很少的情况下在这里,我需要一个WOW64崩溃转储?我的理论更详细的解释会很棒。如果在某本书中有一个很好的解释,那么对这一章的引用就足够了。如果我还没有,我会买它。

回答

1

对于GDI句柄转储,即使它是Win64机器上的32位进程,也需要进行64位转储。如果你在64位机器上进行32位转储,则指向GDI共享句柄表的指针为空。它看起来像只有64位转储才能捕获此信息。

这很有意义,因为您需要处理32位进程中的64位指针,因为您的进程的GDI句柄表部分已从内核空间映射到您的地址空间。我想这是为了保持与32位进程只应包含相同位数的指针的规则一致。

2

如果转储过程之前拍摄达到了WinMain函数/主/ WinmainCrtStartup /等
即如果初始化代码没有然后运行GdiSharedHandleTable可以为空

这不是一个转储的情况下在正常操作期间坠毁,但如果您开始计算,则需要注意的一点是
。exe文件在WinDbg中,检查GdiSharedHandleTable当它是第一个系统上打破GdiSharedHandle可以为NULL
,但如果你设置@ $ exentry或计算的突破将填补!WinMain函数

生成此输出的脚本已张贴的答案linked thread

0:000> dd @@c++(@$Peb->GdiSharedHandleTable) 

00000000 ???????? ???????? ???????? ???????? 
00000010 ???????? ???????? ???????? ???????? 
00000020 ???????? ???????? ???????? ???????? 
00000030 ???????? ???????? ???????? ???????? 
00000040 ???????? ???????? ???????? ???????? 
00000050 ???????? ???????? ???????? ???????? 
00000060 ???????? ???????? ???????? ???????? 
00000070 ???????? ???????? ???????? ???????? 

0:000> g calc!WinMain 

calc!WinMain: 
00591635 8bff   mov  edi,edi 

0:000> dd @@c++(@$Peb->GdiSharedHandleTable) 

00470000 00000000 00000000 40000000 00000000 
00470010 00000000 00000000 00000000 00000000 
00470020 00000000 00000000 00000000 00000000 
00470030 00000000 00000000 00000000 00000000 
00470040 00000000 00000000 00000000 00000000 
00470050 00000000 00000000 00000000 00000000 
00470060 00000000 00000000 00000000 00000000 
00470070 00000000 00000000 00000000 00000000 

0:000> $$>a< c:\wdscr\dumpgdi.txt 

gdioffs Kaddr  Pid  Count Handle Type  Tname IsLive UAddr  
00472b30 fe6b5728 00000ca4 00000000 0d0102b3 00000001 DC  00000040 000e0cb0 
00472be0 fdf73da8 00000ca4 00000000 420502be 00000005 Bitmap 00000040 00000000 
004737b0 fddac108 00000ca4 00000000 9605037b 00000005 Bitmap 00000040 00000000 
00474030 fe76eda8 00000ca4 00000000 eb050403 00000005 Bitmap 00000040 00000000 
00474c90 fddde008 00000ca4 00000000 d70a04c9 0000000a Font  00000040 001fb1e8 
0047ab80 fddab008 00000ca4 00000000 ba050ab8 00000005 Bitmap 00000040 00000000 
0047f270 fddbcda8 00000ca4 00000000 16050f27 00000005 Bitmap 00000040 00000000 
0047fef0 fdee4da8 00000ca4 00000000 cd050fef 00000005 Bitmap 00000040 00000000 
004809f0 fe72eda8 00000ca4 00000000 3405109f 00000005 Bitmap 00000040 00000000 
00480e50 fdda5aa8 00000ca4 00000000 0e0510e5 00000005 Bitmap 00000040 00000000 
00481cf0 ffb0fda8 00000ca4 00000000 df0511cf 00000005 Bitmap 00000040 00000000 
00481d70 fddb0da8 00000ca4 00000000 930511d7 00000005 Bitmap 00000040 00000000 
00482020 ff4a1da8 00000ca4 00000000 d4051202 00000005 Bitmap 00000040 00000000 
00482060 fddd4008 00000ca4 00000000 39051206 00000005 Bitmap 00000040 00000000 
00482170 fddb6008 00000ca4 00000000 20051217 00000005 Bitmap 00000040 00000000 
00483140 ff4a0008 00000ca4 00000000 4e051314 00000005 Bitmap 00000040 00000000 
00483870 ff427980 00000ca4 00000000 6d051387 00000005 Bitmap 00000040 00000000 
00483d80 fe7d04b0 00000ca4 00000000 bd0513d8 00000005 Bitmap 00000040 00000000 
00484620 ff437eb8 00000ca4 00000000 0d101462 00000010 Brush 00000040 000f0fd8 
004846a0 fddc2da8 00000ca4 00000000 d305146a 00000005 Bitmap 00000040 00000000 
00484b80 fdf1a728 00000ca4 00000000 530114b8 00000001 DC  00000040 000e0ae0 


Gdi Handles for C:\Windows\system32\calc.exe 
Total Gdi Handles = 21 
DC  = 2 
Font  = 0 
Region = 17 
Brush = 0 
Bitmap = 1 
Pen  = 1 
Pallete = 0 
Unknpown = 0 

enter image description here

+0

你使用哪种钙?在Win 7 x64上,calc是64位。在调试会话,'DD @@ C++(@ $ Peb-> GdiSharedHandleTable)''返回00000000 00000000',所以它的零和脚本不应该工作。但是,当您运行脚本时,它会返回正确的结果。这似乎对我来说是一个矛盾。 –

+0

对不起,我无法理解什么矛盾,你看我做DD POI()2倍时首先应用在systembp和第二,当应用程序是在它的WinMain第一时间表为空和第二时间表指向有效的内存 – blabb

+0

对不起,我故障。 –