02 全局句柄表

文章详细介绍了Windows内核中进程和线程的表示方式,包括PID和CID在全局句柄表中的使用,以及如何通过特定函数如PsLookupProcessThreadByCid()来查询进程和线程。同时,展示了调试工具KD的使用,用于查看和解析_EPROCESS结构和_HANDLE_TABLE的内容。
摘要由CSDN通过智能技术生成

1.所有的进程和线程无论是否打开,都在这个表中

2.每个进程和线程都有一个唯一的编码 : PID和CID 这两个值其实就是全局句柄表中的索引

进程和线程的查询 : 主要是以下三个函数,按照给定的PID或CID从PspCidTable从中查找相应的进程和线程对象

PsLookupProcessThreadByCid()
PsLookupProcessByProcessId()
PsLookupThreadByThreadId()

kd> dd PspCidTable
80562460  e10008b0 00000002 00000000 00000000
80562470  00000000 00000000 00000000 00000000
80562480  00000000 00000000 00000000 00000000
80562490  00000000 00000000 00000000 00000000
805624a0  00000000 00000000 00000000 00000000
805624b0  00000000 00000000 00000000 00000000
805624c0  00000000 00000000 00000000 00000000
805624d0  00000000 00000000 00000000 00000000

kd> dt _HANDLE_TABLE e10008b0
ntdll!_HANDLE_TABLE
   +0x000 TableCode        : 0xe1003000
   +0x004 QuotaProcess     : (null) 
   +0x008 UniqueProcessId  : (null) 
   +0x00c HandleTableLock  : [4] _EX_PUSH_LOCK
   +0x01c HandleTableList  : _LIST_ENTRY [ 0xe10008cc - 0xe10008cc ]
   +0x024 HandleContentionEvent : _EX_PUSH_LOCK
   +0x028 DebugInfo        : (null) 
   +0x02c ExtraInfoPages   : 0n0
   +0x030 FirstFree        : 0x688
   +0x034 LastFree         : 0x56c
   +0x038 NextHandleNeedingPool : 0x800
   +0x03c HandleCount      : 0n343
   +0x040 Flags            : 1
   +0x040 StrictFIFO       : 0y1

全局句柄表的TableCode 的元素指的就是EPROCESS 或者 ETHREAD 的头了,不再是 _OBJECT_HANDLE
如果还想获取_OBJECT_HEADER可以使用该地址减去 0x18

kd> dq 0xe1003000
e1003000  fffffffe`00000000 00000000`89bf19c9
e1003010  00000000`89bf1751 00000000`89bf1309
e1003020  00000000`89bee021 00000000`89beeda9
e1003030  00000000`89beeb31 00000000`89bee8b9
e1003040  00000000`89bee641 00000000`89bee3c9
e1003050  00000000`89bed021 00000000`89bedda9


kd> dt _EPROCESS 89bf19c8
ntdll!_EPROCESS
   +0x000 Pcb              : _KPROCESS
   +0x06c ProcessLock      : _EX_PUSH_LOCK
   +0x070 CreateTime       : _LARGE_INTEGER 0x0
   +0x078 ExitTime         : _LARGE_INTEGER 0x0
   +0x080 RundownProtect   : _EX_RUNDOWN_REF
   +0x084 UniqueProcessId  : 0x00000004 Void
   +0x088 ActiveProcessLinks : _LIST_ENTRY [ 0x89974e28 - 0x80562358 ]
   +0x090 QuotaUsage       : [3] 0
   +0x09c QuotaPeak        : [3] 0
   +0x0a8 CommitCharge     : 7
   +0x0ac PeakVirtualSize  : 0x28b000
   +0x0b0 VirtualSize      : 0x1c7000
   +0x0b4 SessionProcessLinks : _LIST_ENTRY [ 0x0 - 0x0 ]
   +0x0bc DebugPort        : (null) 
   +0x0c0 ExceptionPort    : (null) 
   +0x0c4 ObjectTable      : 0xe1000d10 _HANDLE_TABLE
   +0x0c8 Token            : _EX_FAST_REF
   +0x0cc WorkingSetLock   : _FAST_MUTEX
   +0x0ec WorkingSetPage   : 0
   +0x0f0 AddressCreationLock : _FAST_MUTEX
   +0x110 HyperSpaceLock   : 0
   +0x114 ForkInProgress   : (null) 
   +0x118 HardwareTrigger  : 0
   +0x11c VadRoot          : 0x89c25078 Void
   +0x120 VadHint          : 0x89c25078 Void
   +0x124 CloneRoot        : (null) 
   +0x128 NumberOfPrivatePages : 3
   +0x12c NumberOfLockedPages : 0
   +0x130 Win32Process     : (null) 
   +0x134 Job              : (null) 
   +0x138 SectionObject    : (null) 
   +0x13c SectionBaseAddress : (null) 
   +0x140 QuotaBlock       : 0x80562400 _EPROCESS_QUOTA_BLOCK
   +0x144 WorkingSetWatch  : (null) 
   +0x148 Win32WindowStation : (null) 
   +0x14c InheritedFromUniqueProcessId : (null) 
   +0x150 LdtInformation   : (null) 
   +0x154 VadFreeHint      : (null) 
   +0x158 VdmObjects       : (null) 
   +0x15c DeviceMap        : 0xe10087c0 Void
   +0x160 PhysicalVadList  : _LIST_ENTRY [ 0x89bf1b28 - 0x89bf1b28 ]
   +0x168 PageDirectoryPte : _HARDWARE_PTE_X86
   +0x168 Filler           : 0
   +0x170 Session          : (null) 
   +0x174 ImageFileName    : [16]  "System"
   +0x184 JobLinks         : _LIST_ENTRY [ 0x0 - 0x0 ]
   +0x18c LockedPagesList  : (null) 



kd> dt _OBJECT_HEADER 0x89bee640-0x18 
nt!_OBJECT_HEADER
   +0x000 PointerCount     : 0n1
   +0x004 HandleCount      : 0n0
   +0x004 NextToFree       : (null) 
   +0x008 Type             : 0x89bf1e70 _OBJECT_TYPE
   +0x00c NameInfoOffset   : 0 ''
   +0x00d HandleInfoOffset : 0 ''
   +0x00e QuotaInfoOffset  : 0 ''
   +0x00f Flags            : 0x22 '"'
   +0x010 ObjectCreateInfo : 0x00000001 _OBJECT_CREATE_INFORMATION
   +0x010 QuotaBlockCharged : 0x00000001 Void
   +0x014 SecurityDescriptor : 0xe10003ae Void
   +0x018 Body             : _QUAD


kd> dt _OBJECT_TYPE 0x89bf1e70 
ntdll!_OBJECT_TYPE
   +0x000 Mutex            : _ERESOURCE
   +0x038 TypeList         : _LIST_ENTRY [ 0x89bf1ea8 - 0x89bf1ea8 ]
   +0x040 Name             : _UNICODE_STRING "Thread"
   +0x048 DefaultObject    : (null) 
   +0x04c Index            : 6
   +0x050 TotalNumberOfObjects : 0x13c
   +0x054 TotalNumberOfHandles : 0x216
   +0x058 HighWaterNumberOfObjects : 0x167
   +0x05c HighWaterNumberOfHandles : 0x26d
   +0x060 TypeInfo         : _OBJECT_TYPE_INITIALIZER
   +0x0ac Key              : 0x65726854
   +0x0b0 ObjectLocks      : [4] _ERESOURCE


遍历全局句柄表

#include <ntddk.h>  

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;
    int* DebugInfo;
    LONG ExtraInfoPages;
    ULONG FirstFree;
    ULONG LastFree;
    ULONG NextHandleNeedingPool;
    LONG HandleCount;
    union {
        ULONG Flags;
        BOOLEAN StrictFIFO : 1;
    };

} HANDLE_TABLE, * PHANDLE_TABLE;

unsigned int* __stdcall ExpLookupHandleTableEntry(struct _HANDLE_TABLE* pspcidtable, int cid)
{
    unsigned int index;
    int pageCount; 
    int tablebase; 
    int base; 
    unsigned int processindex; 

    processindex = cid & 0xFFFFFFFC;这个代码就是去掉余数,保证这个就是4的倍数
    index = processindex >> 2;
    if (processindex >= pspcidtable->NextHandleNeedingPool)
        return 0;
    pageCount = pspcidtable->TableCode & 3;
    tablebase = (pspcidtable->TableCode & 0xFFFFFFFC);
    if (!pageCount)
        return *(int*)(tablebase + 8 * index);
    if (pageCount == 1)
    {
        base = *(int*)(tablebase + (processindex >> 11));
    }
    else
    {
        index = (processindex >> 2) - (processindex >> 21 << 19);
        base = *((char*)*(int*)(tablebase + (processindex >> 21)) + 4 * (index >> 9));
    }
    return *(int*)(base + 8 * (index & 0x1FF));
}

VOID UnloadDriver(PDRIVER_OBJECT DriverObject)
{
    DbgPrint("Unloaded Successfully!");
}

UNICODE_STRING process, thread;

void ShowInfo(int* TableCode, int cid)
{
    int* addr = ((int)ExpLookupHandleTableEntry(TableCode, cid) & ~3);
    if (addr && MmIsAddressValid(addr))
    {
        int* type = addr[-4];

        if (!type)
        {
            return;
        }

        PUNICODE_STRING str = &type[16];16 * 4 = 0x40

        if (!RtlCompareUnicodeString(str, &process, FALSE))
        {
            UCHAR* imgname = &addr[93];
            DbgPrint("PID : %d , Type : %wZ , Name : %s\n", cid, str, imgname);
            return;
        }

        if (!RtlCompareUnicodeString(str, &thread, FALSE))
        {
            DbgPrint("TID : %d , Type : %wZ\n", cid, str);
            return;
        }
    }
}


NTSTATUS DriverEntry(PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath)
{
    DriverObject->DriverUnload = UnloadDriver;
    DbgPrint("Loaded Successfully!");

    RtlInitUnicodeString(&process, L"Process");
    RtlInitUnicodeString(&thread, L"Thread");

    UNICODE_STRING PsLookupProcessThreadByCid;
    RtlInitUnicodeString(&PsLookupProcessThreadByCid, L"PsLookupProcessThreadByCid");
    UCHAR* f = MmGetSystemRoutineAddress(&PsLookupProcessThreadByCid);

    DWORD32* PspCidTable = *(DWORD32*)(f + 32);

    UINT32 TableCode = *PspCidTable;

    switch (TableCode & 3)
    {
        case 0:
            for (int i = 0; i < 512; i++)
            {
                ShowInfo(TableCode, 4 * i);
            }
            break;

        case 1:
            for (int i = 0; i < 512 * 1024; i++)
            {
                ShowInfo(TableCode, 4 * i);
            }
            break;
        case 2:
            for (int i = 0; i < 512 * 1024 * 1024; i++)
            {
                ShowInfo(TableCode, 4 * i);
            }
            break;
    }

    return STATUS_SUCCESS;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值