如何从 DLL 的堆标记中受益?

2023-12-27

如何使用 GFlags 设置并从中受益通过 DLL 启用堆标记 http://msdn.microsoft.com/en-us/library/windows/hardware/ff542915%28v=vs.85%29.aspx?

我知道如何激活进程的设置,但我没有在输出中找到有用的信息!heap -t在WinDbg中。我期待一些像这样的输出:

0:000> !heap -t
Index   Address   Allocated by 
1:      005c0000  MyDll.dll
2:      006b0000  AnotherDll.dll

这样我就可以识别哪个堆是由哪个 DLL 创建的,然后例如确定内存泄漏的来源。

这是对术语“DLL 堆标记”的误解还是我需要更多命令才能获得所需的结果?

到目前为止我的研究:

  • 我在谷歌上搜索了有关该主题的教程,但找不到详细说明
  • 我读过WinDbg的.hh !heap但那里也没有详细解释。标签仅用于!heap -b

又是一个很晚的答案

从堆标记中受益you need to create a tag首先在你的代码中。
据我所知(直到xp-sp3)有no Documented APIS to Create a tag

(从那时起我就没有搞过堆了,所以我不知道 os > vista 中最新的 api 重写是对堆管理器完成的,所以可能有很多^^^features^^^我在下面发布的内容可能已得到纠正或改进或错误已被删除)

在 xp-sp3 中,您可以使用未记录的RtlCreateTagHeap创建一个新标签Process Heap or Private Heap

创建标签后,您需要设置全局标志 8000 | 800

htg - Enable heap tagging
htd - Enable heap tagging by DLL

and theoratically all allocs and frees must get tagged .

but practically only allocations > 512 kB gets tagged在 xp-sp3 中,执行以下基本步骤

它要么是一个错误,要么是一个将标记限制为分配和释放 > 512 kB 的功能
HeapAlloc goes through ZwAllocateVirtualMemory如果 32 位进程中分配 > 512 kBrefer HeapCreate / HeapAlloc Documentation in msdn

并作为debuging aid你可以patch ntdll.dll on the fly to enable tagging for all Allocations and frees .

下面是一个示例代码,演示了标记以及如何在 Windbg 中查看所有内容

编译使用cl /Zi /analyze /W4 <src> /link /RELEASE

使用windbg执行应用程序并观察标记!heap * -t command

#include <windows.h>
#include <stdio.h>

//heaptags are kinda broken or they are intentionally 
//given only to allocations > 512 kb // allocation > 512 kb
//go through VirtualAlloc Route for Heap created with maxsize 
//set to 0 uncomment ALLOCSIZE 0xfdfd2 and recompile to watch 
// tagging increase by 100% with ALLOCSIZE  0xfdfd1 only 50 allocs 
// and frees that are > 512 kB will be tagged these magic numbers 
// are related to comment in HeapCreate Documentation that state 
// slightly less than 512 kB will be allocated for 32 bit process 
// tagging can be dramatically increased by patching ntdll when 
// stopped on system breakpoint patch 7c94b8a4 (xpsp3 ntdll.dll) 
// use the below command in windbg for finding the offset of pattern
// command must be in single line no line breaks
// .foreach /pS 4 /ps 4 ( place  { !grep -i -e call -c 
// "# call*RtlpUpdateTagEntry 7c900000 l?20000" } ) { ub place }
// the instruction we are searching to patch is 
//7c94b8a1 81e3ff0fffff    and     ebx,0FFFF0FFFh 
// patch 0f to 00 at system breakpoint with eb 7c94b8a1+3 00 

#define BUFFERSIZE 100
#define ALLOCSIZE  0xfdfd1
//#define ALLOCSIZE  0xfdfd2

typedef int ( __stdcall *g_RtlCreateTagHeap) ( 
    HANDLE hHeap ,
    void * unknown, 
    wchar_t * BaseString, 
    wchar_t * TagString 
    );

void HeapTagwithHeapAllocPrivate()
{
    PCHAR pch[BUFFERSIZE] = {};
    HANDLE hHeap    = 0;
    ULONG tag1      = 0;
    ULONG tag2      = 0;
    ULONG tag3      = 0;
    ULONG tag4      = 0;
    ULONG tag5      = 0;
    g_RtlCreateTagHeap RtlCreateTagHeap = 0;
    HMODULE hMod = LoadLibrary("ntdll.dll");
    if(hMod)
    {
        RtlCreateTagHeap = (g_RtlCreateTagHeap) 
            GetProcAddress( hMod,"RtlCreateTagHeap");
    }
    if (hHeap == 0)
    {
        hHeap = HeapCreate(0,0,0);
        if (RtlCreateTagHeap != NULL)
        {
            tag1 = RtlCreateTagHeap (hHeap,0,L"HeapTag!",L"MyTag1");
            tag2 = RtlCreateTagHeap (hHeap,0,L"HeapTag!",L"MyTag2"); 
            tag3 = RtlCreateTagHeap (hHeap,0,L"HeapTag!",L"MyTag3");
            tag4 = RtlCreateTagHeap (hHeap,0,L"HeapTag!",L"MyTag4");
        }
    }
    HANDLE DefHeap = GetProcessHeap();
    if ( (RtlCreateTagHeap != NULL)  && (DefHeap != NULL ))
    {
        tag5 = RtlCreateTagHeap (DefHeap,0,L"HeapTag!",L"MyTag5");
        for ( int i = 0; i < BUFFERSIZE ; i++ )
        {
            pch[i]= (PCHAR) HeapAlloc( DefHeap,HEAP_ZERO_MEMORY| tag5, 1 );
            HeapFree(DefHeap,NULL,pch[i]);
        }

    }
    if(hHeap)
    {
        for ( int i = 0; i < BUFFERSIZE ; i++ )
        {
            pch[i]= (PCHAR) HeapAlloc( hHeap,HEAP_ZERO_MEMORY| tag1, 1 );
            //lets leak all allocs patch ntdll to see the tagging details
            //HeapFree(hHeap,NULL,pch[i]);
        }
        for ( int i = 0; i < BUFFERSIZE ; i++ )
        {
            pch[i]= (PCHAR) HeapAlloc( hHeap,HEAP_ZERO_MEMORY| tag2, 100 );
            // lets leak 40% allocs patch ntdll to see the tagging details
            if(i >= 40)
                HeapFree(hHeap,NULL,pch[i]);
        }
        // slightly less than 512 kb no tagging
        for ( int i = 0; i < BUFFERSIZE / 2 ; i++ ) 
        {
            pch[i]= (PCHAR) HeapAlloc( 
                hHeap,HEAP_ZERO_MEMORY| tag3, ALLOCSIZE / 2 );
        }
        // > 512 kb  default tagging 
        for ( int i = BUFFERSIZE / 2; i < BUFFERSIZE ; i++ ) 
        {
            pch[i]= (PCHAR) HeapAlloc( 
                hHeap,HEAP_ZERO_MEMORY | tag4 ,ALLOCSIZE );
        }
        for (int i =0 ; i < BUFFERSIZE ; i++)
        {
            HeapFree(hHeap,NULL,pch[i]);
        }
    }
}
void _cdecl main()
{
    HeapTagwithHeapAllocPrivate();
}

编译后的exe可以用windbg运行,如下所示

默认执行和检查
**只有 50 个标签可见,所有标签都 > 512 kB 分配

cdb -c "g;!heap * -t;q" newheaptag.exe | cdb -c "g;!heap * -t;q" newheaptag.exe | grep 标签**

heaptag:\>cdb -c "g;!heap * -t;q" newheaptag.exe | grep Tag
 Tag  Name                   Allocs    Frees   Diff  Allocated
 Tag  Name                   Allocs    Frees   Diff  Allocated
 Tag  Name                   Allocs    Frees   Diff  Allocated
0004: HeapTag!MyTag4             50       50      0        0

在系统断点上修补 ntdll 应该使所有标签可见

eb = 写入字节 修补并在退出时运行带有标签的检查堆的exe cdb -c "eb 7c94b8a1+3 00;g;!heap * -t;q" newheaptag.exe | grep 标签

heaptag:\>cdb -c "eb 7c94b8a1+3 00;g;!heap * -t;q" newheaptag.exe | grep Tag
 Tag  Name                   Allocs    Frees   Diff  Allocated
0012: HeapTag!MyTag5            100      100      0        0  <-our tag in process heap
 Tag  Name                   Allocs    Frees   Diff  Allocated
 Tag  Name                   Allocs    Frees   Diff  Allocated
0001: HeapTag!MyTag1            100        0    100     3200  <--- leak all
0002: HeapTag!MyTag2            100       60     40     5120  <--- leak 40 %
0003: HeapTag!MyTag3             50       50      0        0  <--- clean < 512 kB
0004: HeapTag!MyTag4             50       50      0        0  <----clean > 512 kB
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何从 DLL 的堆标记中受益? 的相关文章

  • 进程堆段及其必要性

    在转储 win32 进程的堆时 主要是在像 IE 这样具有高堆内存消耗的进程中 使用 堆 a 004e0000我发现特定堆的多个段 例如 Heap entries for Segment00 in Heap 004e0000 Heap en
  • 在哪里可以找到 Andrew Richards 为 WinDBG 编写的 pde 扩展?

    我在网上的一些资源中看到提到它 但我找不到它 它似乎没有包含在 WinDBG 发行版中 有一个公共 OneDrive 其中包含它的 ZIP 文件
  • !clrstack -p 不给出调用堆栈中方法的参数值

    我们正在尝试使用 Windbg 分析 w3wp 内存转储 我们发现 w3wp 进程由于堆栈溢出而崩溃 我加载了 psscor4 dll 并通过发出 clrstack 获取了调用堆栈 但我也想知道传递给方法的参数 如果我发出 clrstack
  • 诊断无法停止的应用程序

    我们的Windows应用程序经常挂在内存中 我正在尝试使用windbg来跟踪 下问题 我对 Windbg 很陌生 需要一些建议 我 已经开始阅读高级 Windows 调试 该应用程序是用 VB 编写的 C 和 COM 对象的混合体 偶尔当
  • IE 100% CPU 挂起/获取堆栈跟踪

    我遇到过 IE7 挂起访问我的网络应用程序的情况 立足于优秀建议 https stackoverflow com questions 574423 ie hanging using 100 of the cpu 574595 574595
  • WinDbg 在 MS 符号服务器上找不到 ntdll 的符号

    我正在尝试调试可执行文件 notepad exe 来自 Windows 10 发行版 并且需要来自 Microsoft 符号服务器的符号 ntdll pdb 但调试器返回错误 指出找不到指定的文件 0 000 gt reload Reloa
  • 我的堆是否碎片化

    0 000 gt dumpheap stat total 1755874 objects Statistics MT Count TotalSize Class Name 7b9b0c64 1 12 System Windows Forms
  • 如何设置 Windows 符号服务器

    我在网络上有一个备用服务器 我想用它来托管我们所有的构建符号 我已经知道如何在本地开发系统上设置符号缓存并将调试器 例如 Windbg 指向 符号文件路径 中的该路径 我认为我可以对网络上具有自己的符号缓存 例如 host symbols
  • 垃圾收集期间崩溃的原因

    一段时间以来 我一直在努力解决 C 应用程序崩溃的问题 该应用程序也使用相当多的 C CLI 模块 这些模块主要是本地库的包装器来访问设备驱动程序 崩溃并不总是很容易重现 但我能够收集六个崩溃转储 这些崩溃转储表明程序总是在垃圾收集期间因访
  • Windbg内存映射?

    如何在 Windbg 中获得类似于 Ollydbg 内存映射功能的内存映射 我想查看按顺序显示加载到每个范围的内容的地址空间列表 最好带有指示的内存保护 这是 Ollydbg 内存映射的屏幕截图 address准确显示此信息 它可以在用户模
  • sos.dll 返回的对象大小与内存中进程大小不匹配

    我使用以下 sos 命令来枚举正在运行的 asp 应用程序 托管在 Windows xp 4 GB 计算机上 中特定类型的所有实例 foreach obj dumpheap type my type short start of addre
  • WinDbg - 将字符串参数与内存中的字符串进行比较

    我需要比较一个字符串 作为参数传递给WinDbg用记忆中的字符串 如何才能实现这一目标 例如 该字符串位于加载的 PE 内的特定偏移处 所以 我可以通过执行轻松读取字符串da c 100
  • 如何在 WinDbg 扩展中基于转储文件内存创建对象?

    我负责开发一个大型应用程序 并经常使用 WinDbg 根据客户提供的 DMP 文件来诊断问题 我为 WinDbg 编写了一些小扩展 事实证明它们对于从 DMP 文件中提取信息非常有用 在我的扩展代码中 我发现自己以相同的方式一遍又一遍地手动
  • Windbg 设置取决于调用堆栈的条件断点

    问题 我需要制作一个脚本或表达式 如果调用堆栈上的某处是具有特定名称的函数 则该脚本或表达式不会中断 具体问题 如何将调用堆栈上的函数获取到字符串列表 Example Module MyFunctionWithConditionalBrea
  • Windbg:psscor4 不起作用

    我搜索并尝试了很多东西 但无法让 psscor4 正常工作 当我调用 threads 我总是得到 请求ThreadStore失败 我检查的内容如下 我有一个为 X86 平台编译的 NET 4 应用程序 我使用的是Windbg版本6 2 92
  • 如何更改年龄不匹配的 PDB 以使其正确匹配?

    我们的夜间构建过程被破坏了很长一段时间 因此它生成的 PDB 文件与相应的图像文件的年龄相差几个小时 我已经解决了这个问题 但是 我想开始使用符号服务器 但由于必须使用这些年龄不匹配的 pdb 文件而无法开始 我通过使用 Windbg 中的
  • WinDbg:APPLICATION_HANG_WRONG_SYMBOLS

    我对 WinDbg 还很陌生 我正在尝试找到一个导致我的应用程序无缘无故挂起的错误 我不确定我做的事情是否正确 但我知道我需要系统 dll 以及我正在调试的 exe 的符号 因此 我这样设置符号路径 srv c websymbols htt
  • 如何通过 WinDBG 在 Dump 中查找非托管内存中的内容

    我在 WinDbg 命令中运行转储文件 地址 摘要 我的结果是这样的 Usage Summary RgnCount Total Size ofBusy ofTota Free 3739 7ff5 dbbae000 127 960 Tb 99
  • WinDbg中出现“SOS版本与您正在调试的CLR版本不匹配”怎么办?

    我的某些应用程序出现问题 它是一个基于 wcf 的应用程序 在 Windows 2003 Server x86 的 IIS6 下运行 在事件日志中 我从 W3SVC WP 源 EventID 2262 收到这样的错误 ISAPI C WIN
  • 警告:Windows 调试器中的 [something] 与 [something] 重叠是什么意思?

    我正在为 uni 项目的一部分编辑 Windows Research Kernel WRK 有时当我启动运行我的内核的虚拟机时 Windows 调试器会显示如下内容 WARNING rdpdr overlaps raspptp baa740

随机推荐