RtlQueryProcessDebugInformation as Anti-Dbg Trick

The Essay

The following paper will uncover some interesting undocumented

functions relative to Windows Heap Enumeration.

RtlCreateQueryDebugBuffer
RtlQueryProcessDebugInformation
RtlDestroyQueryDebugBuffer

Here the prototypes for each function:

PDEBUG_BUFFER
NTAPI
RtlCreateQueryDebugBuffer(
IN ULONG  Size,
IN BOOLEAN  EventPair);


NTSTATUS
NTAPI
RtlQueryProcessDebugInformation(
IN ULONG  ProcessId,
IN ULONG  DebugInfoClassMask,
IN OUT PDEBUG_BUFFER  DebugBuffer);


NTSTATUS
NTAPI
RtlDestroyQueryDebugBuffer(
IN PDEBUG_BUFFER  DebugBuffer);

RtlCreateQueryDebugBuffer allocates buffer for storing heap data in case of success, it returns pointer to allocated debug buffer. Here the declaration of debug buffer:

typedef struct _DEBUG_BUFFER {
HANDLE  SectionHandle;
PVOID  SectionBase;
PVOID  RemoteSectionBase;
ULONG  SectionBaseDelta;
HANDLE  EventPairHandle;
ULONG  Unknown[2];
HANDLE  RemoteThreadHandle;
ULONG  InfoClassMask;
ULONG  SizeOfInfo;
ULONG  AllocatedSize;
ULONG  SectionSize;
PVOID  ModuleInformation;
PVOID  BackTraceInformation;
PVOID  HeapInformation;
PVOID  LockInformation;
PVOID  Reserved[8];
} DEBUG_BUFFER, *PDEBUG_BUFFER;

After the buffer allocation we can call the Heap Process Debug Information, we can call RtlQueryProcessDebugInformation to load all heap blocks of the process. This function loads entire heap nodes and corresponding heap blocks of the process. Debug Buffer contains the pointer to heap information structure at offset 0×38. First parameter of this heap structure is node count and after that it contains array of DEBUG_HEAP_INFORMATION structure which represent each heap node.

typedef struct _DEBUG_HEAP_INFORMATION
{
ULONG Base; // 0×00
ULONG Flags; // 0×04
USHORT Granularity; // 0×08
USHORT Unknown; // 0x0A
ULONG Allocated; // 0x0C
ULONG Committed; // 0×10
ULONG TagCount; // 0×14
ULONG BlockCount; // 0×18
ULONG Reserved[7]; // 0x1C
PVOID Tags; // 0×38
PVOID Blocks; // 0x3C Heap block pointer for this node.
} DEBUG_HEAP_INFORMATION, *PDEBUG_HEAP_INFORMATION;

As you should know a debugged process presents different flags respect a not debugged one, here the sample anti-dbg code:

#define WIN32_LEAN_AND_MEAN
#include <stdio.h>
#include <stdlib.h>
#include <windows.h>
#include <Psapi.h>
#include “defs.h”

#pragma comment(lib,”ntdll.lib”)
#pragma comment(lib,”psapi.lib”)

void QueryDbgBufferMethod(void)
{
PDEBUG_BUFFER buffer;
NTSTATUS ntStatus;

buffer = RtlCreateQueryDebugBuffer(0,FALSE);

ntStatus = RtlQueryProcessDebugInformation(GetCurrentProcessId(),
PDI_HEAPS|PDI_HEAP_BLOCKS,
buffer);

PDEBUG_HEAP_INFORMATION heapInfo = PDEBUG_HEAP_INFORMATION(PULONG(buffer->HeapInformation) + 1);

if (heapInfo->Flags == 0×50000062)
MessageBoxA(NULL,”Debugged”,”Warning”,MB_OK);
else
MessageBoxA(NULL,”Not Debugged”,”Warning”,MB_OK);

RtlDestroyQueryDebugBuffer(buffer);
}

and here ‘defs.h

typedef LONG NTSTATUS;
#define STATUS_SUCCESS ((NTSTATUS)0x00000000L)

typedef struct _DEBUG_BUFFER {
HANDLE SectionHandle;
PVOID  SectionBase;
PVOID  RemoteSectionBase;
ULONG  SectionBaseDelta;
HANDLE  EventPairHandle;
ULONG  Unknown[2];
HANDLE  RemoteThreadHandle;
ULONG  InfoClassMask;
ULONG  SizeOfInfo;
ULONG  AllocatedSize;
ULONG  SectionSize;
PVOID  ModuleInformation;
PVOID  BackTraceInformation;
PVOID  HeapInformation;
PVOID  LockInformation;
PVOID  Reserved[8];
} DEBUG_BUFFER, *PDEBUG_BUFFER;

typedef struct _DEBUG_HEAP_INFORMATION
{
ULONG Base; // 0×00
ULONG Flags; // 0×04
USHORT Granularity; // 0×08
USHORT Unknown; // 0x0A
ULONG Allocated; // 0x0C
ULONG Committed; // 0×10
ULONG TagCount; // 0×14
ULONG BlockCount; // 0×18
ULONG Reserved[7]; // 0x1C
PVOID Tags; // 0×38
PVOID Blocks; // 0x3C
} DEBUG_HEAP_INFORMATION, *PDEBUG_HEAP_INFORMATION;

// RtlQueryProcessDebugInformation.DebugInfoClassMask constants
#define PDI_MODULES                       0×01
#define PDI_BACKTRACE                     0×02
#define PDI_HEAPS                         0×04
#define PDI_HEAP_TAGS                     0×08
#define PDI_HEAP_BLOCKS                   0×10
#define PDI_LOCKS                         0×20

extern “C”
__declspec(dllimport)
NTSTATUS
__stdcall
RtlQueryProcessDebugInformation(
IN ULONG  ProcessId,
IN ULONG  DebugInfoClassMask,
IN OUT PDEBUG_BUFFER  DebugBuffer);

extern “C”
__declspec(dllimport)
PDEBUG_BUFFER
__stdcall
RtlCreateQueryDebugBuffer(
IN ULONG  Size,
IN BOOLEAN  EventPair);
extern “C”
__declspec(dllimport)
NTSTATUS
__stdcall
RtlDestroyQueryDebugBuffer(
IN PDEBUG_BUFFER  DebugBuffer);

See you to the next post.. :)

About these ads

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Connecting to %s

Follow

Get every new post delivered to your Inbox.

%d bloggers like this: