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;
}