|
|
@@ -0,0 +1,228 @@ |
|
|
#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; |
|
|
} |