Created
August 28, 2015 11:51
-
-
Save reinsteam/c0edd839f1d622ad3d20 to your computer and use it in GitHub Desktop.
Sample code of heap enumeration without using Tool Help functions <tlhelp32.h>
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#ifndef WIN32_LEAN_AND_MEAN | |
# define WIN32_LEAN_AND_MEAN | |
#endif | |
#pragma warning (push) | |
/* 4820: '<struct-name>' : 'n' bytes padding added after data member '<member-name>'*/ | |
# pragma warning (disable : 4820) | |
# include <windows.h> | |
# include <stdio.h> | |
# include <stdlib.h> | |
#pragma warning (pop) | |
typedef unsigned int u32; | |
/*--------------------------------------------------------------------------------------------------------------------*/ | |
#define DYNAMIC_IMPORTED_FUNC(rval, func, ...)\ | |
typedef rval (WINAPI *tpfn_##func)(__VA_ARGS__); \ | |
static tpfn_##func pfn_##func = 0; | |
#define DYNAMIC_SYSTEM_LOAD(lib, func)\ | |
( ( pfn_##func = (tpfn_##func)dynamic_system_func_load(lib, #func) ) != 0 ) | |
#define CALL(func, ...)\ | |
pfn_##func(__VA_ARGS__) | |
/*--------------------------------------------------------------------------------------------------------------------*/ | |
#ifdef __cplusplus | |
# define INLINE __forceinline | |
#else | |
# define INLINE __inline | |
#endif | |
/* To prevent MSVC warning 4820 when compiling for x64 */ | |
#ifdef _WIN64 | |
# define EXPLICIT_PADDING(n, size) BYTE padding_##n[size] | |
#else | |
# define EXPLICIT_PADDING(n, size) | |
#endif | |
/*--------------------------------------------------------------------------------------------------------------------*/ | |
static INLINE FARPROC dynamic_system_func_load(const char * module, const char * func) | |
{ | |
void * handle = GetModuleHandleA(module); | |
if (handle == 0) | |
{ | |
handle = LoadLibraryA(module); | |
} | |
if (handle != 0) | |
{ | |
return GetProcAddress(handle, func); | |
} | |
return 0; | |
} | |
/*---------------------------------------------------------------------------------------------------------------------- | |
/* Helper structures to query debug heap info | |
/*--------------------------------------------------------------------------------------------------------------------*/ | |
typedef struct _RTL_HEAP_TAG | |
{ | |
ULONG NumberOfAllocations; | |
ULONG NumberOfFrees; | |
SIZE_T BytesAllocated; | |
USHORT TagIndex; | |
USHORT CreatorBackTraceIndex; | |
WCHAR TagName[24]; | |
EXPLICIT_PADDING(0, 4); | |
} RTL_HEAP_TAG, *PRTL_HEAP_TAG; | |
typedef struct _RTL_HEAP_ENTRY | |
{ | |
SIZE_T Size; | |
USHORT Flags; | |
USHORT AllocatorBackTraceIndex; | |
EXPLICIT_PADDING(0, 4); | |
union | |
{ | |
struct | |
{ | |
SIZE_T Settable; | |
ULONG Tag; | |
EXPLICIT_PADDING(1, 4); | |
} s1; | |
struct | |
{ | |
SIZE_T CommitedSize; | |
PVOID FirstBlock; | |
} s2; | |
} u; | |
} RTL_HEAP_ENTRY, *PRTL_HEAP_ENTRY; | |
typedef struct _RTL_DEBUG_HEAP_INFORMATION | |
{ | |
PVOID BaseAddress; | |
ULONG Flags; | |
USHORT EntryOverhead; | |
USHORT CreatorBackTraceIndex; | |
SIZE_T BytesAllocated; | |
SIZE_T BytesCommited; | |
ULONG NumberOfTags; | |
ULONG NumberOfEntries; | |
ULONG NumberOfPseudoTags; | |
ULONG PseudoTagGranularity; | |
ULONG Reserved[5]; | |
EXPLICIT_PADDING(0, 4); | |
PRTL_HEAP_TAG Tags; | |
PRTL_HEAP_ENTRY Entries; | |
} RTL_DEBUG_HEAP_INFORMATION, *PRTL_DEBUG_HEAP_INFORMATION; | |
typedef struct _RTL_PROCESS_HEAPS | |
{ | |
ULONG NumberOfHeaps; | |
EXPLICIT_PADDING(0, 4); | |
RTL_DEBUG_HEAP_INFORMATION Heaps[1]; | |
} RTL_PROCESS_HEAPS, *PRTL_PROCESS_HEAPS; | |
typedef struct _RTL_DEBUG_INFORMATION | |
{ | |
HANDLE SectionHandleClient; | |
PVOID ViewBaseClient; | |
PVOID ViewBaseTarget; | |
ULONG_PTR ViewBaseDelta; | |
HANDLE EventPairClient; | |
HANDLE EventPairTarget; | |
HANDLE TargetProcessId; | |
HANDLE TargetThreadHandle; | |
ULONG Flags; | |
EXPLICIT_PADDING(0, 4); | |
SIZE_T OffsetFree; | |
SIZE_T CommitSize; | |
SIZE_T ViewSize; | |
union | |
{ | |
PVOID Modules; | |
PVOID ModulesEx; | |
}; | |
PVOID BackTraces; | |
struct _RTL_PROCESS_HEAPS *Heaps; | |
PVOID Locks; | |
PVOID SpecificHeap; | |
HANDLE TargetProcessHandle; | |
PVOID VerifierOptions; | |
PVOID ProcessHeap; | |
HANDLE CriticalSectionHandle; | |
HANDLE CriticalSectionOwnerThread; | |
PVOID Reserved[4]; | |
} RTL_DEBUG_INFORMATION, *PRTL_DEBUG_INFORMATION; | |
typedef struct _RTL_HEAP_USAGE_ENTRY | |
{ | |
struct _RTL_HEAP_USAGE_ENTRY * Next; | |
PVOID Address; | |
SIZE_T Size; | |
USHORT AllocatorBackTraceIndex; | |
USHORT TagIndex; | |
EXPLICIT_PADDING(0, 4); | |
} RTL_HEAP_USAGE_ENTRY, *PRTL_HEAP_USAGE_ENTRY; | |
typedef enum DebugInfoClassMask | |
{ | |
PDI_MODULES = 0x01, | |
PDI_BACKTRACE = 0x02, | |
PDI_HEAPS = 0x04, | |
PDI_HEAP_TAGS = 0x08, | |
PDI_HEAP_BLOCKS = 0x10, | |
PDI_LOCKS = 0x20 | |
} DebugInfoClassMask; | |
DYNAMIC_IMPORTED_FUNC(PRTL_DEBUG_INFORMATION, RtlCreateQueryDebugBuffer, u32, u32); | |
DYNAMIC_IMPORTED_FUNC(u32, RtlDestroyQueryDebugBuffer, PRTL_DEBUG_INFORMATION); | |
DYNAMIC_IMPORTED_FUNC(u32, RtlQueryProcessDebugInformation, u32, u32, PRTL_DEBUG_INFORMATION); | |
int main(int argc, char ** argv) | |
{ | |
u32 proc_id = 0; | |
if (argc > 1) | |
{ | |
proc_id = atoi(argv[1]); | |
} | |
u32 result = 1; | |
result = result && DYNAMIC_SYSTEM_LOAD("ntdll.dll", RtlCreateQueryDebugBuffer); | |
result = result && DYNAMIC_SYSTEM_LOAD("ntdll.dll", RtlDestroyQueryDebugBuffer); | |
result = result && DYNAMIC_SYSTEM_LOAD("ntdll.dll", RtlQueryProcessDebugInformation); | |
printf("---- Heap stats for PID : %u ---- \n", proc_id); | |
if (result) | |
{ | |
PRTL_DEBUG_INFORMATION buffer = CALL(RtlCreateQueryDebugBuffer, 0, 0); | |
if (buffer) | |
{ | |
u32 i; | |
CALL(RtlQueryProcessDebugInformation, proc_id, PDI_HEAPS, buffer); | |
PRTL_PROCESS_HEAPS prtl_heaps = buffer->Heaps; | |
if (prtl_heaps != 0) | |
{ | |
printf("---------------------------------------------------------------------------\n"); | |
printf("Heap # | Address | Commited | Allocated | Flags | \n"); | |
printf("---------------------------------------------------------------------------\n"); | |
for (i = 0; i < prtl_heaps->NumberOfHeaps; ++i) | |
{ | |
PRTL_DEBUG_HEAP_INFORMATION heap = prtl_heaps->Heaps + i; | |
printf("%6u | 0x%p | %9u bytes | %9u bytes | %#06x |\n", i, heap->BaseAddress, (u32)heap->BytesCommited, (u32)heap->BytesAllocated, heap->Flags); | |
} | |
} | |
CALL(RtlDestroyQueryDebugBuffer, buffer); | |
} | |
} | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment