翼度科技»论坛 编程开发 .net 查看内容

.NET程序的 GDI句柄泄露 的再反思

2

主题

2

帖子

6

积分

新手上路

Rank: 1

积分
6
一:背景

1. 讲故事

上个月我写过一篇 如何洞察 C# 程序的 GDI 句柄泄露 文章,当时用的是 GDIView + WinDbg 把问题搞定,前者用来定位泄露资源,后者用来定位泄露代码,后面有朋友反馈两个问题:

  • GDIView 统计不准怎么办?
  • 我只有 Dump 可以统计吗?
其实那篇文章也聊过,在 x64 或者 wow64 的程序里,在用户态内存段中有一个 GDI Shared Handle Table 句柄表,这个表中就统计了各自句柄类型的数量,如果能统计出来也就回答了上面的问题,对吧。
32bit 程序的 GDI Shared Handle Table 段是没有的,即 _PEB.GdiSharedHandleTable = NULL。
  1. 0:002> dt ntdll!_PEB GdiSharedHandleTable 01051000
  2.   +0x0f8 GdiSharedHandleTable : (null)
复制代码
有了这些前置基础,接下来就可以开挖了。
二:挖 GdiSharedHandleTable

1. 测试代码

为了方便测试,我来造一个 DC句柄 的泄露。
  1.     internal class Program
  2.     {
  3.         [DllImport("Example_20_1_5", CallingConvention = CallingConvention.Cdecl)]
  4.         extern static void GDILeak();
  5.         static void Main(string[] args)
  6.         {
  7.             try
  8.             {
  9.                 GDILeak();
  10.             }
  11.             catch (Exception ex)
  12.             {
  13.                 Console.WriteLine(ex.Message);
  14.             }
  15.             Console.ReadLine();
  16.         }
  17.     }
复制代码
然后就是 GDILeak 的 C++ 实现代码。
  1. extern "C"
  2. {
  3.         _declspec(dllexport) void GDILeak();
  4. }
  5. void GDILeak()
  6. {
  7.     while (true)
  8.     {
  9.         CreateDCW(L"DISPLAY", nullptr, nullptr, nullptr);
  10.         auto const gdiObjectsCount = GetGuiResources(GetCurrentProcess(), GR_GDIOBJECTS);
  11.         std::cout << "GDI objects: " << gdiObjectsCount << std::endl;
  12.         Sleep(10);
  13.     }
  14. }
复制代码

从卦中可以看到,当前有1029个 GDICell 结构体,接下来怎么鉴别每一条记录上都是什么类型呢?其实这里是有枚举的。

  • DC = 0x01
  • Region = 0x04
  • Bitmap = 0x05
  • Palette =0x08
  • Font =0x0a
  • Brush = 0x10
  • Pen = 0x30
即 GDIView 中的 红色一列 。

到这里我们可以通过肉眼观察 + F5 检索,可以清晰的看到1029 个句柄对象,其中 1028 个是 DC 对象,其实这就是我们泄露的,截图如下:

3. 脚本处理

如果大家通读会发现这些都是固定步骤,完全可以写成比如 C++ 和 Javascript 的格式脚本,在 StackOverflow 上还真有这样的脚本。
  1. 0:000> dt ntdll!_PEB GdiSharedHandleTable @$peb
  2.    +0x0f8 GdiSharedHandleTable : 0x00000000`03560000 Void
复制代码
三:总结

如果大家想从 DUMP 文件中提取 GDI 句柄泄露类型,这是一篇很好的参考资料,相信能从另一个角度给你提供一些灵感。

来源:https://www.cnblogs.com/huangxincheng/archive/2023/07/25/17579180.html
免责声明:由于采集信息均来自互联网,如果侵犯了您的权益,请联系我们【E-Mail:cb@itdo.tech】 我们会及时删除侵权内容,谢谢合作!

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x

举报 回复 使用道具