Как извлечь выгоду из кучи тегов DLL?
Как я могу использовать и извлекать выгоду из настройки GFlags включить тегирование кучи DLL ?
Я знаю, как активировать настройку для процесса, но я не нашел полезной информации в выводе !heap -t
в WinDbg. Я ожидал получить такой результат:
0:000> !heap -t
Index Address Allocated by
1: 005c0000 MyDll.dll
2: 006b0000 AnotherDll.dll
Таким образом, я могу определить, какая куча была создана какой DLL, а затем, например, определить источник утечки памяти.
Является ли это неправильным толкованием термина "пометка кучи DLL" или мне нужно еще что-то команды, чтобы получить желаемый результат?
Мои исследования до сих пор:
- я погуглил учебник по этой теме, но не смог найти подробного описания
- я читал Windbg'S
.hh !heap
, но там это тоже не объясняется подробно. Тег используется только в!heap -b
1 ответ:
Опять очень поздний ответ
Чтобы извлечь выгоду из HeapTagging
you need to create a tag
сначала в вашем коде.
насколько я знаю (то есть до xp-sp3) былиno Documented APIS to Create a tag
(С тех пор я не сталкивался с кучей, поэтому я не знаю о последних API в os > vista перезаписи были сделаны в менеджере кучи, поэтому, вероятно, многие из
^^^features^^^
, которые я публикую ниже, возможно, были исправлены или улучшены или удалены ошибки)В XP-SP3, но вы можете использовать недокументированные
RtlCreateTagHeap
, чтобы создать новый тег либоProcess 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 кб
HeapAlloc goes through ZwAllocateVirtualMemory
в случае выделения > 512 кб в 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(); }
Скомпилированный exe-файл для запуска с windbg, как показано ниже
Исполнение и проверка по умолчанию
**будет видно только 50 тегов, все они > 512 кб выделенияCdb-c "g;!куча * - 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 на выходе inspect heaps with tags cdb-c " eb 7c94b8a1+3 00; g;!куча * - 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