In Windows, a handle is an opaque value representing a reference to a specific object (file, process, thread, etc.). All handles are managed in a structure called a handle table. Handle values are efficiently recycled.
The handle table is three-tiered:
32 entries512 entries255 entriesOnly the subhandle table is allocated initially. Higher tiers are created as needed.
source: Windows Internals 7, part 2
_HANDLE_TABLE_ENTRYDescribes a handle in memory. The TableCode field in
_HANDLE_TABLE points to the table of these entries.
// 0x10 bytes (sizeof)
union _HANDLE_TABLE_ENTRY {
volatile LONGLONG VolatileLowValue;
LONGLONG LowValue;
struct {
struct _HANDLE_TABLE_ENTRY_INFO* volatile InfoTable;
LONGLONG HighValue;
union _HANDLE_TABLE_ENTRY* NextFreeHandleEntry;
struct _EXHANDLE LeafHandleValue;
};
LONGLONG RefCountField;
ULONGLONG Unlocked:1;
ULONGLONG RefCnt:16;
ULONGLONG Attributes:3;
struct {
ULONGLONG ObjectPointerBits:44;
ULONG GrantedAccessBits:25;
ULONG NoRightsUpgrade:1;
ULONG Spare1:6;
};
ULONG Spare2;
};
_HANDLE_TABLETracks and manages all handles in a process. It is referenced in the
ObjectTable field of EPROCESS.
// 0x80 bytes (sizeof)
struct _HANDLE_TABLE {
ULONG NextHandleNeedingPool;
LONG ExtraInfoPages;
volatile ULONGLONG TableCode;
struct _EPROCESS* QuotaProcess;
struct _LIST_ENTRY HandleTableList;
ULONG UniqueProcessId;
union {
ULONG Flags;
struct {
UCHAR StrictFIFO:1;
UCHAR EnableHandleExceptions:1;
UCHAR Rundown:1;
UCHAR Duplicated:1;
UCHAR RaiseUMExceptionOnInvalidHandleClose:1;
};
};
struct _EX_PUSH_LOCK HandleContentionEvent;
struct _EX_PUSH_LOCK HandleTableLock;
union {
struct _HANDLE_TABLE_FREE_LIST FreeLists[1];
struct {
UCHAR ActualEntry[32];
struct _HANDLE_TRACE_DEBUG_INFO* DebugInfo;
};
};
};
_OBJECT_HEADERThis structure precedes every kernel object, providing metadata like reference count and object type.
//0x38 bytes (sizeof), src: Vergilius Project
struct _OBJECT_HEADER
{
LONGLONG PointerCount; //0x0
union
{
LONGLONG HandleCount; //0x8
VOID* NextToFree; //0x8
};
struct _EX_PUSH_LOCK Lock; //0x10
UCHAR TypeIndex; //0x18
union
{
UCHAR TraceFlags; //0x19
struct
{
UCHAR DbgRefTrace:1; //0x19
UCHAR DbgTracePermanent:1; //0x19
};
};
UCHAR InfoMask; //0x1a
union
{
UCHAR Flags; //0x1b
struct
{
UCHAR NewObject:1; //0x1b
UCHAR KernelObject:1; //0x1b
UCHAR KernelOnlyAccess:1; //0x1b
UCHAR ExclusiveObject:1; //0x1b
UCHAR PermanentObject:1; //0x1b
UCHAR DefaultSecurityQuota:1; //0x1b
UCHAR SingleHandleEntry:1; //0x1b
UCHAR DeletedInline:1; //0x1b
};
};
ULONG Reserved; //0x1c
union
{
struct _OBJECT_CREATE_INFORMATION* ObjectCreateInfo; //0x20
VOID* QuotaBlockCharged; //0x20
};
VOID* SecurityDescriptor; //0x28
struct _QUAD Body; //0x30
};