gpt4 book ai didi

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

转载 作者:行者123 更新时间:2023-12-04 19:06:21 27 4
gpt4 key购买 nike

我如何使用 GFlags 设置并从中受益 Enable heap tagging by DLL ?

我知道如何激活进程的设置,但我在 !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
  • 最佳答案

    又是一个很晚的答案

    受益于 HeapTagging you need to create a tag首先在您的代码中。
    据我所知(最多 xp-sp3)有 no Documented APIS to Create a tag
    (从那时起我就没有处理过堆,所以我不知道 os > vista 中的最新 api 对堆管理器进行了重写,因此我在下面发布的许多 ^^^features^^^ 可能已得到纠正或改进或删除了错误)

    在 xp-sp3 中,您可以使用未记录的 RtlCreateTagHeapProcess Heap 创建一个新标签或 Private Heap
    创建 tha 标签后,您需要设置全局标志 8000 | 800

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

    theoratically all allocs and frees must get tagged .

    但是 practically only allocations > 512 kB gets tagged在 xp-sp3 中使用这些基本步骤

    它要么是一个错误,要么是一个将标记限制为分配和释放 > 512 kB 的功能 HeapAlloc goes through ZwAllocateVirtualMemory如果在 32 位进程中分配 > 512 kB refer HeapCreate / HeapAlloc Documentation in msdn
    并作为 debuging aid您可以 patch ntdll.dllthe fly to enable taggingall Allocations and frees .

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

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

    使用 windbg 执行应用程序并使用 !heap * -t 观看标记命令
    #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一起运行,如下所示

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


    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

    关于windbg - 如何从 DLL 的堆标记中受益?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23264272/

    27 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com