如何使用GFlags设置并从中受益?通过DLL启用堆标记?
我知道如何激活进程的设置,但我没有!heap -t在WinDbg 的输出中找到有用的信息.我期待这样的输出:
0:000> !heap -t
Index Address Allocated by
1: 005c0000 MyDll.dll
2: 006b0000 AnotherDll.dll
Run Code Online (Sandbox Code Playgroud)
这样我就可以识别哪个堆由哪个DLL创建,然后识别内存泄漏的来源.
这是对"DLL堆标记"一词的误解,还是需要更多命令来获得所需的结果?
我的研究到目前为止:
.hh !heap但它的细节也没有详细说明.标签仅用于!heap -b再来一个很晚的答案
you need to create a tag在代码中首先从HeapTagging 中受益.
据我所知(这是xp-sp3),有no Documented APIS to Create a tag
(从那以后我没有用堆破解所以我不知道os中的最新api> vista重写已经对堆管理器完成了所以^^^features^^^我下面发布的许多内容可能已被纠正或改进或删除了错误)
在xp-sp3中,您可以使用未记录的文件RtlCreateTagHeap来创建新标记Process Heap或Private Heap
在创建tha标签后,您需要设置全局标志8000 | 800
htg - Enable heap tagging
htd - Enable heap tagging by DLL
Run Code Online (Sandbox Code Playgroud)
和theoratically all allocs and frees must get tagged.
但是practically only allocations > 512 kB gets tagged在xp-sp3中有这些基本步骤
它是一个错误或一个功能,限制标记分配和释放> 512 kB
HeapAlloc goes through ZwAllocateVirtualMemory,如果分配> 512 kB在32位进程refer HeapCreate / HeapAlloc Documentation in msdn
作为一个debuging aid可以patch ntdll.dll上the fly to enable tagging的all 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();
}
Run Code Online (Sandbox Code Playgroud)
使用windbg运行的已编译的exe如下所示
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
Run Code Online (Sandbox Code Playgroud)
在系统断点上修补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
Run Code Online (Sandbox Code Playgroud)