UID 2
精华
积分 7736
威望 点
宅币 个
贡献 次
宅之契约 份
最后登录 1970-1-1
在线时间 小时
每个进程都存在一个句柄表,是很重要的数据结构,系统分配资源创建内核对象,之后生成一个整数返还给用户,而自己管理对象的生命周期
学习句柄表结构最直接的方式无非是通过句柄表操作的api了,下面的句柄表操作函数和相关数据结构已经经过精简,可以说明句柄表的用法:
typedef struct _HANDLE_TABLE //每个进程都存在一个句柄表,所有句柄表都链接到一个全局链表中
{
ULONG_PTR TableCode;//指向句柄表上层树节点
struct _EPROCESS *QuotaProcess;
HANDLE UniqueProcessId;
#define HANDLE_TABLE_LOCKS 4
EX_PUSH_LOCK HandleTableLock[HANDLE_TABLE_LOCKS];
LIST_ENTRY HandleTableList;//全局句柄表链表
EX_PUSH_LOCK HandleContentionEvent;
PHANDLE_TRACE_DEBUG_INFO DebugInfo;
LONG ExtraInfoPages;
ULONG FirstFree;
ULONG LastFree;
ULONG NextHandleNeedingPool;
LONG HandleCount;
union {
ULONG Flags;
BOOLEAN StrictFIFO : 1;
};
} HANDLE_TABLE, *PHANDLE_TABLE;
NTSTATUS ObReferenceObjectByHandle (HANDLE Handle,ACCESS_MASK DesiredAccess,POBJECT_TYPE ObjectType,KPROCESSOR_MODE AccessMode,
PVOID *Object,POBJECT_HANDLE_INFORMATION HandleInformation)
{
ACCESS_MASK GrantedAccess;
PHANDLE_TABLE HandleTable;
POBJECT_HEADER ObjectHeader;
PHANDLE_TABLE_ENTRY ObjectTableEntry;
PEPROCESS Process;
NTSTATUS Status;
PETHREAD Thread;
*Object = NULL;
if ((LONG)(ULONG_PTR) Handle < 0) // <0的情况可能是:内核句柄,-1,-2
{
if (Handle == NtCurrentProcess()) //NtCurrentProcess=-1
{//如果是当前进程
if ((ObjectType == PsProcessType) || (ObjectType == NULL))
{
Process = PsGetCurrentProcessByThread(Thread);
ObjectHeader = OBJECT_TO_OBJECT_HEADER(Process);
ObpIncrPointerCount(ObjectHeader);
*Object = Process;
return;
}
else if (Handle == NtCurrentThread()) //NtCurrentThread=-2
{
if ((ObjectType == PsThreadType) || (ObjectType == NULL))
{//如果是当前线程
ObjectHeader = OBJECT_TO_OBJECT_HEADER(Thread);
ObpIncrPointerCount(ObjectHeader);
*Object = Thread;
return;
}
else if (AccessMode == KernelMode)
{
Handle = DecodeKernelHandle( Handle );//去除最高位
HandleTable = ObpKernelHandleTable;
}
}
else
{
HandleTable = PsGetCurrentProcessByThread(Thread)->ObjectTable;
}
KeEnterCriticalRegionThread(&Thread->Tcb);//加锁
ObjectTableEntry = ExMapHandleToPointerEx ( HandleTable, Handle, AccessMode );//将句柄表句柄转换成句柄表入口
if (ObjectTableEntry != NULL)
{
ObjectHeader = (POBJECT_HEADER)(((ULONG_PTR)(ObjectTableEntry->Object)) & ~OBJ_HANDLE_ATTRIBUTES);
ReadForWriteAccess(ObjectHeader);
if ((ObjectHeader->Type == ObjectType) || (ObjectType == NULL))
{
ObpIncrPointerCount(ObjectHeader);
ExUnlockHandleTableEntry( HandleTable, ObjectTableEntry );
KeLeaveCriticalRegionThread(&Thread->Tcb);
*Object = &ObjectHeader->Body;
}
}
KeLeaveCriticalRegionThread(&Thread->Tcb);
return Status;
}
NTKERNELAPI PHANDLE_TABLE_ENTRY ExMapHandleToPointerEx ( PHANDLE_TABLE HandleTable, HANDLE Handle, KPROCESSOR_MODE PreviousMode)
{
EXHANDLE LocalHandle;
PHANDLE_TABLE_ENTRY HandleTableEntry = NULL;
PETHREAD CurrentThread;
LocalHandle.GenericHandleOverlay = Handle;
if (((LocalHandle.Index & (LOWLEVEL_COUNT - 1)) == 0) || ((HandleTableEntry = ExpLookupHandleTableEntry(HandleTable, LocalHandle)) == NULL) ||
!ExpLockHandleTableEntry( HandleTable, HandleTableEntry))
{
return NULL;
}
return HandleTableEntry;
}
typedef struct _EXHANDLE {
union {
struct {
ULONG TagBits : 2;
ULONG Index : 30;//句柄表入口索引
};
HANDLE GenericHandleOverlay;
#define HANDLE_VALUE_INC 4 // Amount to increment the Value to get to the next handle
ULONG_PTR Value;
};
} EXHANDLE, *PEXHANDLE;
PHANDLE_TABLE_ENTRY ExpLookupHandleTableEntry (PHANDLE_TABLE HandleTable,EXHANDLE tHandle)
{
ULONG_PTR i,j,k;
ULONG_PTR CapturedTable;
ULONG TableLevel;
PHANDLE_TABLE_ENTRY Entry = NULL;
EXHANDLE Handle;
PUCHAR TableLevel1;
PUCHAR TableLevel2;
PUCHAR TableLevel3;
ULONG_PTR MaxHandle;
Handle = tHandle;
Handle.TagBits = 0;
MaxHandle = *(volatile ULONG *) &HandleTable->NextHandleNeedingPool;
if (Handle.Value >= MaxHandle) {
return NULL;
}
CapturedTable = *(volatile ULONG_PTR *) &HandleTable->TableCode;
TableLevel = (ULONG)(CapturedTable & LEVEL_CODE_MASK);
CapturedTable = CapturedTable - TableLevel;
switch (TableLevel)
{
case 0://简单索引表,索引已经乘4
TableLevel1 = (PUCHAR) CapturedTable;
Entry = (PHANDLE_TABLE_ENTRY) &TableLevel1[Handle.Value * (sizeof (HANDLE_TABLE_ENTRY) / HANDLE_VALUE_INC)];
break;
case 1://2级索引表
TableLevel2 = (PUCHAR) CapturedTable;
i = Handle.Value % (LOWLEVEL_COUNT * HANDLE_VALUE_INC);
Handle.Value -= i;
j = Handle.Value / ((LOWLEVEL_COUNT * HANDLE_VALUE_INC) / sizeof (PHANDLE_TABLE_ENTRY));
TableLevel1 = (PUCHAR) *(PHANDLE_TABLE_ENTRY *) &TableLevel2[j];
Entry = (PHANDLE_TABLE_ENTRY) &TableLevel1[i * (sizeof (HANDLE_TABLE_ENTRY) / HANDLE_VALUE_INC)];
break;
case 2://3级索引表
TableLevel3 = (PUCHAR) CapturedTable;
i = Handle.Value % (LOWLEVEL_COUNT * HANDLE_VALUE_INC);
Handle.Value -= i;
k = Handle.Value / ((LOWLEVEL_COUNT * HANDLE_VALUE_INC) / sizeof (PHANDLE_TABLE_ENTRY));
j = k % (MIDLEVEL_COUNT * sizeof (PHANDLE_TABLE_ENTRY));
k -= j;
k /= MIDLEVEL_COUNT;
TableLevel2 = (PUCHAR) *(PHANDLE_TABLE_ENTRY *) &TableLevel3[k];
TableLevel1 = (PUCHAR) *(PHANDLE_TABLE_ENTRY *) &TableLevel2[j];
Entry = (PHANDLE_TABLE_ENTRY) &TableLevel1[i * (sizeof (HANDLE_TABLE_ENTRY) / HANDLE_VALUE_INC)];
break;
}
return Entry;
}