1 Windows程序中的句柄表
句柄是一個對象引用,同一個對象在不同的環境下可能有不同的引用(句柄)值。句柄僅在一個程序範圍内有效。
HANDLE_TABLE 結構的定義:
typedef struct _HANDLE_TABLE {
ULONG_PTR TableCode;//指向句柄表的存儲結構
struct _EPROCESS *QuotaProcess;//句柄表的記憶體資源記錄在此程序中
HANDLE UniqueProcessId;//建立程序的ID,用于回調函數
#define HANDLE_TABLE_LOCKS 4
EX_PUSH_LOCK HandleTableLock[HANDLE_TABLE_LOCKS];//句柄表鎖,僅在句柄表擴充時使用
LIST_ENTRY HandleTableList;//所有的句柄表形成一個連結清單
EX_PUSH_LOCK HandleContentionEvent;//連結清單投為全局變量HandleTableListHead
PHANDLE_TRACE_DEBUG_INFO DebugInfo;//調試資訊,僅當調試句柄時才有意義
LONG ExtraInfoPages;//審計資訊所占用的頁面數量
ULONG FirstFree;//空閑連結清單表頭的句柄索引
ULONG LastFree;//最近被釋放的句柄索引,用于FIFO類型空閑連結清單
ULONG NextHandleNeedingPool;//下一次句柄表擴充的起始句柄索引
LONG HandleCount;//正在使用的句柄表項的數量
union {
ULONG Flags;//标志域/
// For optimization we reuse handle values quickly. This can be a problem for
// some usages of handles and makes debugging a little harder. If this
// bit is set then we always use FIFO handle allocation.
BOOLEAN StrictFIFO : 1;//是否使用FIFO風格的重用,即先釋放先重用
};
} HANDLE_TABLE, *PHANDLE_TABLE;
TableCode : 指向句柄表的最高層表項頁面,低2位的值表示目前句柄表的層數。
如果最低2位為0,說明句柄表隻有1層,最多能容納512個句柄。
如果最低2位為1,說明句柄表有2層,最多能容納512*1024個句柄。
如果最低2位為2,說明句柄表有3層,最多能容納512*1024*1024個句柄。
Windows 程序的句柄表結構

執行體在建立程序時,首先為新程序配置設定一個單層句柄表。由ExCreateHandleTable 函數來完成,該函數調用ExpAllocateHandleTable 來構造初始的句柄表。由函數
ExpAllocateHandleTableEntryShow 來擴充句柄表。代碼見base\ntos\ex\handle.c.
FirstFree : 記錄了目前句柄表中的空閑句柄鍊。通過句柄索引值來連結。
HANDLE_TABLE_ENTRY 結構定義如下:
typedef struct _HANDLE_TABLE_ENTRY {
union {
PVOID Object;
ULONG ObAttributes;
PHANDLE_TABLE_ENTRY_INFO InfoTable;
ULONG_PTR Value;
};
union {
union {
ACCESS_MASK GrantedAccess;
struct {
USHORT GrantedAccessIndex;
USHORT CreatorBackTraceIndex;
};
};
LONG NextFreeTableEntry;
};
} HANDLE_TABLE_ENTRY, *PHANDLE_TABLE_ENTRY;
Object : 指向句柄所代表的核心對象,最低3位含義:第0 位OBJ_PROTECT_CLOSE,表示調用者是否允許關閉該句柄;第1位OBJ_INHERIT,訓示該程序所建立的子程序是否可以繼承該句柄,即是否将該句柄項拷貝到它們的句柄表中;第2位OBJ_AUDIT_OBJECT_CLOSE,訓示關閉該對象時是否産生一個審計事件
第二個union中,如果句柄表項指向一個有效的對象,則GrantedAccess 記錄了該句柄的通路掩碼;如果這是一個空閑的句柄表項,則NextFreeTableEntry 将加入到句柄表的空閑單連結清單中。
一個有效的句柄有4中可能:-1,表示目前程序;-2表示目前線程;負值,其絕對值為核心句柄表中的索引;不超過226的正值,目前程序的句柄表中的索引。
核心句柄表即系統的全局句柄表,wrk 中即變量ObpKernelHandleTable,也是System 程序的句柄表。解析句柄函數ObReferenceObjectByHandle,見base\ntos\ob\obref.c 。
将一個對象插入到句柄表中的函數是ObInsertObject,見base\ntos\ob\obinsert.c 。
對象的引用有兩種,一種在核心中之間通過對象位址來引用,通過ObReferenceObjectByPoint記錄一次新的引用,第二種,通過句柄來引用對象,通過ObpIncrementHandleCount檢查并記錄一次句柄引用。
在一個句柄上調用了ObReferenceObjectByHandle後,若該對象不在使用,必須調用ObDereferenceObject 函數。
程序唯一ID,即UniqueProcessId;線程有一個CLIENT_ID成員Cid,包含了所屬程序的唯一ID和線程的唯一ID。