加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 综合聚焦 > 服务器 > Windows > 正文

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

发布时间:2020-12-14 01:53:47 所属栏目:Windows 来源:网络整理
导读:如何使用GFlags设置 Enable heap tagging by DLL并从中受益? 我知道如何激活进程的设置,但我没有在WinDbg的!heap -t的输出中找到有用的信息.我期待这样的输出: 0:000 !heap -tIndex Address Allocated by 1: 005c0000 MyDll.dll2: 006b0000 AnotherDll.dl
如何使用GFlags设置 Enable heap tagging by DLL并从中受益?

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

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

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

这是对“DLL堆标记”一词的误解,还是需要更多命令来获得所需的结果?

我的研究到目前为止:

>我搜索了有关此主题的教程,但我找不到详细的说明
>我读了WinDbg的.hh!堆,但它没有详细解释.标签仅用于!heap -b

解决方法

再来一个很晚的答案

要从HeapTagging中受益,您需要先在代码中创建一个标记.
据我所知(这是xp-sp3),没有记录的APIS来创建标签

(从那时起我就没有堆乱了,所以我不知道os中的最新api> vista重写是对堆管理器进行的,所以我下面发布的很多^^^功能^^^可能已被更正或更好或者错误删除)

在xp-sp3中,您可以使用未记录的RtlCreateTagHeap为Process Heap或Private堆创建新标记

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

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

并且理论上所有的alloc和frees都必须被标记.

但实际上只有分配> 512 kB使用这些基本步骤在xp-sp3中标记

它要么是一个错误,要么是一个限制标记分配和释放的功能> 512 kB
在Allocations>的情况下,HeapAlloc通过ZwAllocateVirtualMemory. 32位进程中的512 kB参考msdn中的HeapCreate / HeapAlloc文档

作为debuging辅助工具,您可以动态修补ntdll.dll,以便为所有分配和释放启用标记.

下面是一个示例代码,演示了标记以及如何在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);
        if (RtlCreateTagHeap != NULL)
        {
            tag1 = RtlCreateTagHeap (hHeap,L"HeapTag!",L"MyTag1");
            tag2 = RtlCreateTagHeap (hHeap,L"MyTag2"); 
            tag3 = RtlCreateTagHeap (hHeap,L"MyTag3");
            tag4 = RtlCreateTagHeap (hHeap,L"MyTag4");
        }
    }
    HANDLE DefHeap = GetProcessHeap();
    if ( (RtlCreateTagHeap != NULL)  && (DefHeap != NULL ))
    {
        tag5 = RtlCreateTagHeap (DefHeap,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,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,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,pch[i]);
        }
    }
}
void _cdecl main()
{
    HeapTagwithHeapAllocPrivate();
}

使用windbg运行的已编译的exe如下所示

默认执行和检查
**只有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

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读