元始天尊 发表于 2015-6-24 23:51:36

探测句柄表结构一

每个进程都存在一个句柄表,是很重要的数据结构,系统分配资源创建内核对象,之后生成一个整数返还给用户,而自己管理对象的生命周期
学习句柄表结构最直接的方式无非是通过句柄表操作的api了,下面的句柄表操作函数和相关数据结构已经经过精简,可以说明句柄表的用法:
typedef struct _HANDLE_TABLE //每个进程都存在一个句柄表,所有句柄表都链接到一个全局链表中
{
        ULONG_PTR TableCode;//指向句柄表上层树节点
        struct _EPROCESS *QuotaProcess;
        HANDLE UniqueProcessId;
#define HANDLE_TABLE_LOCKS 4
        EX_PUSH_LOCK HandleTableLock;
        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;
            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;
            Entry = (PHANDLE_TABLE_ENTRY) &TableLevel1;
            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;
            TableLevel1 = (PUCHAR) *(PHANDLE_TABLE_ENTRY *) &TableLevel2;
            Entry = (PHANDLE_TABLE_ENTRY) &TableLevel1;
            break;
    }
    return Entry;
}

页: [1]
查看完整版本: 探测句柄表结构一