|
一:背景
1. 讲故事
在我的分析之旅中,遇到过很多程序的故障和杀毒软件扯上了关系,有杀毒软件导致的程序卡死,有杀毒软件导致的程序崩溃,这一篇又出现了一个杀毒软件导致的程序非托管内存泄露,真的是分析多了什么鬼都能撞上。
前几天有位朋友找到过,我他们的程序内存在慢慢的泄露,最后程序会出现崩溃,不知道是什么导致的,让我帮忙看一下怎么回事,简单分析后发现是非托管泄露,让朋友开启了ust并在内存超出预期时抓了一个dump下来,接下来就是分析了。
二:WinDbg 分析
1. 到底是哪里的泄露
相信一直追这个系统的朋友应该知道怎么判断,很简单, 看下 MEM_COMMIT 和 HEAP 指标即可,使用 !address -summary 命令输出如下:- 0:000> !address -summary
- --- Usage Summary ---------------- RgnCount ----------- Total Size -------- %ofBusy %ofTotal
- Heap 678 93bd0000 ( 2.308 GB) 65.39% 57.71%
- <unknown> 2610 3005d000 ( 768.363 MB) 21.26% 18.76%
- Free 515 1e133000 ( 481.199 MB) 11.75%
- Image 1526 118f8000 ( 280.969 MB) 7.77% 6.86%
- Other 19 804e000 ( 128.305 MB) 3.55% 3.13%
- Stack 390 4900000 ( 73.000 MB) 2.02% 1.78%
- TEB 73 49000 ( 292.000 kB) 0.01% 0.01%
- PEB 1 1000 ( 4.000 kB) 0.00% 0.00%
- --- State Summary ---------------- RgnCount ----------- Total Size -------- %ofBusy %ofTotal
- MEM_COMMIT 4477 c51f9000 ( 3.080 GB) 87.25% 77.00%
- MEM_FREE 515 1e133000 ( 481.199 MB) 11.75%
- MEM_RESERVE 820 1ccc4000 ( 460.766 MB) 12.75% 11.25%
- --- Largest Region by Usage ----------- Base Address -------- Region Size ----------
- Heap 38be0000 fd0000 ( 15.812 MB)
- <unknown> cc6000 7fd9000 ( 127.848 MB)
- Free f7590000 88bf000 ( 136.746 MB)
- Image 5ab2c000 e41000 ( 14.254 MB)
- Other 8cee000 7fb0000 ( 127.688 MB)
- Stack 14610000 fd000 (1012.000 kB)
- TEB ffe51000 1000 ( 4.000 kB)
- PEB fffde000 1000 ( 4.000 kB)
复制代码 从卦中看,3G的提交内存,Heap 吃了 2.3G,也就表明是 NTHEAP 的泄露,这是一块非托管内存区域,一般都是 C/C++ 语言用 malloc 或者 new 分配的内存,接下来深挖下 NTHEAP 即可,使用 !heap -s 命令。- 0:000> !heap -s
- SEGMENT HEAP ERROR: failed to initialize the extention
- NtGlobalFlag enables following debugging aids for new heaps:
- stack back traces
- LFH Key : 0x7c31b93c
- Termination on corruption : DISABLED
- Heap Flags Reserv Commit Virt Free List UCR Virt Lock Fast
- (k) (k) (k) (k) length blocks cont. heap
- -----------------------------------------------------------------------------
- 00200000 08000002 178304 138172 178304 42165 1747 56 0 34 LFH
- External fragmentation 30 % (1747 free blocks)
- 006c0000 08001002 1088 224 1088 18 8 2 0 0 LFH
- 00590000 08041002 256 4 256 2 1 1 0 0
- 006a0000 08001002 3136 1184 3136 153 82 3 0 0 LFH
- External fragmentation 12 % (82 free blocks)
- 00570000 08001002 1088 224 1088 18 8 2 0 0 LFH
- ...
- 15710000 08001002 2185152 2179432 2185152 442 1323 139 0 0 LFH
- ...
复制代码 从卦中信息看, 15710000 吃了2.18G,也就表明它是吃内存的主力,这里简单说一下,00200000 是默认的进程堆,除了这个之外都是用非托管代码调用 Win32API 的 HeapCreate 方法创建出来的,接下来就得看下是什么代码创建的。
2. 到底是谁创建的
要想知道是谁创建的,一定要在注册表中开启 ust 选项,大家可以了解下 gflags.exe 工具,参考如下:- PS C:\Users\Administrator\Desktop> gflags /i Example_17_1_7.exe +ust
- Current Registry Settings for Example_17_1_7.exe executable are: 00001000
- ust - Create user mode stack trace database
复制代码 开启之后 win32api 的 HeapAlloc 方法的内部中会到注册表中看一下是否有 ust 值,如果有就会记录分配的调用栈,这样就知道是谁创建的,抓取dump后可以用windbg的 !gflag 命令看下是否开启成功,参考输出如下:- 0:000> !gflag
- Current NtGlobalFlag contents: 0x00001000
- ust - Create user mode stack trace database
复制代码 接下来对 Heap=15710000 进行一个 block 分组,看下是否有一些有价值的信息。- 0:000> !heap -stat -h 15710000
- heap @ 15710000
- group-by: TOTSIZE max-display: 20
- size #blocks total ( %) (percent of total busy bytes)
- 2cb dea4 - 26dd40c (9.58)
- 2d7 c778 - 23675c8 (8.72)
- d0 26d64 - 1f8e140 (7.78)
- 7c5 2c50 - 1584990 (5.30)
- cb 14449 - 10125e3 (3.96)
- 83c 16c2 - bb6578 (2.89)
- cf9 bc4 - 98a1a4 (2.35)
- 1f51 3da - 789dfa (1.86)
- ...
复制代码 从卦中数据看没有哪个size占用的特别高,接下来就依次从高往低看,发现都是和 prthook 有关,参考输出如下:- 0:000> !heap -flt s 2cb
- _HEAP @ 15710000
- HEAP_ENTRY Size Prev Flags UserPtr UserSize - state
- 1571f948 005d 0000 [00] 1571f960 002cb - (busy)
- 15649d70 005d 005d [00] 15649d88 002cb - (busy)
- ...
- 3ec4b900 005d 005d [00] 3ec4b918 002cb - (busy)
- 3ec4bbe8 005d 005d [00] 3ec4bc00 002cb - (busy)
- 3ec4bed0 005d 005d [00] 3ec4bee8 002cb - (busy)
- 3ec4c1b8 005d 005d [00] 3ec4c1d0 002cb - (busy)
- ...
- 0:000> !heap -flt s 2d7
- HEAP_ENTRY Size Prev Flags UserPtr UserSize - state
- 15665550 005e 0000 [00] 15665568 002d7 - (busy)
- 1566b930 005e 005e [00] 1566b948 002d7 - (busy)
- 1566df98 005e 005e [00] 1566dfb0 002d7 - (busy)
- 1566e288 005e 005e [00] 1566e2a0 002d7 - (busy)
- ...
- 39e3acc8 0061 0061 [00] 39e3ace0 002d7 - (busy)
- 39e3c508 0061 0061 [00] 39e3c520 002d7 - (busy)
- 39e3c810 0061 0061 [00] 39e3c828 002d7 - (busy)
- 39e3cb18 0061 0061 [00] 39e3cb30 002d7 - (busy)
- 39e3ce20 0061 0061 [00] 39e3ce38 002d7 - (busy)
- 0:000> !heap -p -a 3ec4c1b8
- address 3ec4c1b8 found in
- _HEAP @ 15710000
- HEAP_ENTRY Size Prev Flags UserPtr UserSize - state
- 3ec4c1b8 005d 0000 [00] 3ec4c1d0 002cb - (busy)
- 771dd969 ntdll!RtlAllocateHeap+0x00000274
- 153e7439 prthook!MyShowWindow+0x0001d1f9
- 153e543c prthook!MyShowWindow+0x0001b1fc
- 153476ab prthook+0x000276ab
- 0:000> !heap -p -a 39e3ce20
- address 39e3ce20 found in
- _HEAP @ 15710000
- HEAP_ENTRY Size Prev Flags UserPtr UserSize - state
- 39e3ce20 0061 0000 [00] 39e3ce38 002d7 - (busy)
- 771dd969 ntdll!RtlAllocateHeap+0x00000274
- 153e7439 prthook!MyShowWindow+0x0001d1f9
- 153e543c prthook!MyShowWindow+0x0001b1fc
- 153476ab prthook+0x000276ab
复制代码 3. prthook 到底为何方神圣
从前一节的卦中数据看,貌似 prthook 在不断的弹框,在弹框中用 ntdll!RtlAllocateHeap 分配了非托管内存,那 prthook 到底是个啥呢?可以用 lmvm 看下。- 0:000> lmvm prthook
- Browse full module list
- start end module name
- 15320000 155dc000 prthook (export symbols) prthook.dll
- Loaded symbol image file: prthook.dll
- Image path: C:\Windows\SysWOW64\prthook.dll
- Image name: prthook.dll
- Browse all global symbols functions data
- Timestamp: Thu Jun 22 17:16:53 2017 (594B8B05)
- CheckSum: 001F4972
- ImageSize: 002BC000
- File version: 16.17.6.22
- Product version: 16.17.6.22
- File flags: 0 (Mask 3F)
- File OS: 40004 NT Win32
- File type: 2.0 Dll
- File date: 00000000.00000000
- Translations: 0804.04b0
- Information from resource tables:
- CompanyName: Beijing VRV Software Co.,Ltd
- ProductName: edp
- InternalName: prthook
- OriginalFilename: prthook.dll_DB
- ProductVersion: 16, 17, 6, 22
- FileVersion: 16, 17, 6, 22
- FileDescription: prthook_DB
- LegalCopyright: Copyright (C) 2016 Beijing VRV Software Co.,Ltd
- Comments: 中英文版
复制代码 从卦中数据看,prthook.dll 所属公司为 Beijing VRV Software Co.,Ltd,无语的是把这个第三方的dll放在Windows的系统目录 C:\Windows\SysWOW64 下,容易让人觉得有点 鸠占鹊巢,接下来查一下百度,发现是 北信源 的,截图如下:
有了这些信息,告诉朋友让客户把这个安全软件卸载掉就可以了。
三:总结
程序的故障如果不是我们的代码造成的,你想通过排查代码找出问题是不可能的事情,追过这个系列的朋友应该深有体会,常见的外在因素有:
来源:https://www.cnblogs.com/huangxincheng/Undeclared/17947054
免责声明:由于采集信息均来自互联网,如果侵犯了您的权益,请联系我们【E-Mail:cb@itdo.tech】 我们会及时删除侵权内容,谢谢合作! |
本帖子中包含更多资源
您需要 登录 才可以下载或查看,没有账号?立即注册
x
|