这块算是基本搞明白了
...常用命令
查看所有进程基本信息:
!process 0 0
查看进程eprocess:
dt _eprocess fffffa801aaae060 含有_handle_table
typedef struct _HANDLE_TABLE // 15 elements, 0x68 bytes (sizeof)
{
/*0x000*/ UINT64 TableCode; //关键一项
/*0x008*/ struct _EPROCESS* QuotaProcess;
/*0x010*/ VOID* UniqueProcessId;
/*0x018*/ UINT64 HandleLock; // 7 elements, 0x8 bytes (sizeof)
/*0x020*/ struct _LIST_ENTRY HandleTableList; // 2 elements, 0x10 bytes (sizeof)
/*0x030*/ UINT64 HandleContentionEvent; // 7 elements, 0x8 bytes (sizeof)
/*0x038*/ PVOID DebugInfo;
/*0x040*/ LONG32 ExtraInfoPages;
union // 2 elements, 0x4 bytes (sizeof)
{
/*0x044*/ ULONG32 Flags;
/*0x044*/ UINT8 StrictFIFO : 1; // 0 BitPosition
};
/*0x048*/ ULONG32 FirstFreeHandle;
/*0x04C*/ UINT8 _PADDING0_[0x4];
/*0x050*/ struct _HANDLE_TABLE_ENTRY* LastFreeHandleEntry;
/*0x058*/ ULONG32 HandleCount;
/*0x05C*/ ULONG32 NextHandleNeedingPool;
/*0x060*/ ULONG32 HandleCountHighWatermark;
/*0x064*/ UINT8 _PADDING1_[0x4];
}HANDLE_TABLE, *PHANDLE_TABLE;
假如只有一项,TableCode指向的内容是HANDLE_TABLE_ENTRY数组,低3位表示是否是2,3级表:
typedef struct _HANDLE_TABLE_ENTRY // 8 elements, 0x10 bytes (sizeof)
{
union // 4 elements, 0x8 bytes (sizeof)
{
/*0x000*/ VOID* Object;//这里去掉最低3位指向_object_header
/*0x000*/ ULONG32 ObAttributes;
/*0x000*/ PVOID* InfoTable;
/*0x000*/ UINT64 Value;
};
union // 3 elements, 0x8 bytes (sizeof)
{
/*0x008*/ ULONG32 GrantedAccess;
struct // 2 elements, 0x8 bytes (sizeof)
{
/*0x008*/ UINT16 GrantedAccessIndex;
/*0x00A*/ UINT16 CreatorBackTraceIndex;
/*0x00C*/ UINT8 _PADDING0_[0x4];
};
/*0x008*/ ULONG32 NextFreeTableEntry;
};
}HANDLE_TABLE_ENTRY, *PHANDLE_TABLE_ENTRY;
一个进程的句柄值handle/4=index, handle_table[index].object=目标对象的对象头
对象头:
typedef struct _OBJECT_HEADER // 12 elements, 0x38 bytes (sizeof)
{
/*0x000*/ INT64 PointerCount;
union // 2 elements, 0x8 bytes (sizeof)
{
/*0x008*/ INT64 HandleCount;
/*0x008*/ VOID* NextToFree;
};
/*0x010*/ struct _EX_PUSH_LOCK Lock; // 7 elements, 0x8 bytes (sizeof)
/*0x018*/ UINT8 TypeIndex; //类型对象索引 在ObTypeIndexTable中的索引
/*0x019*/ UINT8 TraceFlags;
/*0x01A*/ UINT8 InfoMask;
/*0x01B*/ UINT8 Flags;
/*0x01C*/ UINT8 _PADDING0_[0x4];
union // 2 elements, 0x8 bytes (sizeof)
{
/*0x020*/ struct _OBJECT_CREATE_INFORMATION* ObjectCreateInfo;
/*0x020*/ VOID* QuotaBlockCharged;
};
/*0x028*/ VOID* SecurityDescriptor;
/*0x030*/ struct _QUAD Body; // 2 elements, 0x8 bytes (sizeof) 对象体
}OBJECT_HEADER, *POBJECT_HEADER;
类型对象
typedef struct _OBJECT_TYPE // 12 elements, 0xD0 bytes (sizeof)
{
/*0x000*/ struct _LIST_ENTRY TypeList; // 2 elements, 0x10 bytes (sizeof)
/*0x010*/ struct _UNICODE_STRING Name; // 3 elements, 0x10 bytes (sizeof) 类型名字
/*0x020*/ VOID* DefaultObject;
/*0x028*/ UINT8 Index; //在ObTypeIndexTable中的索引
/*0x029*/ UINT8 _PADDING0_[0x3];
/*0x02C*/ ULONG32 TotalNumberOfObjects;
/*0x030*/ ULONG32 TotalNumberOfHandles;
/*0x034*/ ULONG32 HighWaterNumberOfObjects;
/*0x038*/ ULONG32 HighWaterNumberOfHandles;
/*0x03C*/ UINT8 _PADDING1_[0x4];
/*0x040*/ struct _OBJECT_TYPE_INITIALIZER TypeInfo; // 25 elements, 0x70 bytes (sizeof)
/*0x0B0*/ struct _EX_PUSH_LOCK TypeLock; // 7 elements, 0x8 bytes (sizeof)
/*0x0B8*/ ULONG32 Key;
/*0x0BC*/ UINT8 _PADDING2_[0x4];
/*0x0C0*/ struct _LIST_ENTRY CallbackList; // 2 elements, 0x10 bytes (sizeof) 该类型对象的回调函数链表
}OBJECT_TYPE, *POBJECT_TYPE;
每个类型对象存在一个全局变量指针POBJECT_TYPE
而且所有类型对象处于一个全局数组中:dq ObTypeIndexTable
Windows内核原理与实现的书讲到dq obpobjecttypes东西,这个和ObTypeIndexTable[2:]内容相同
windbg !object命令查看OBJECT_TYPE.
类型信息
typedef struct _OBJECT_TYPE_INITIALIZER // 25 elements, 0x70 bytes (sizeof)
{
/*0x000*/ UINT16 Length;
union // 2 elements, 0x1 bytes (sizeof)
{
/*0x002*/ UINT8 ObjectTypeFlags;
struct // 7 elements, 0x1 bytes (sizeof)
{
/*0x002*/ UINT8 CaseInsensitive : 1; // 0 BitPosition
/*0x002*/ UINT8 UnnamedObjectsOnly : 1; // 1 BitPosition
/*0x002*/ UINT8 UseDefaultObject : 1; // 2 BitPosition
/*0x002*/ UINT8 SecurityRequired : 1; // 3 BitPosition
/*0x002*/ UINT8 MaintainHandleCount : 1; // 4 BitPosition
/*0x002*/ UINT8 MaintainTypeList : 1; // 5 BitPosition
/*0x002*/ UINT8 SupportsObjectCallbacks : 1; // 6 BitPosition
};
};
/*0x004*/ ULONG32 ObjectTypeCode;
/*0x008*/ ULONG32 InvalidAttributes;
/*0x00C*/ struct _GENERIC_MAPPING GenericMapping; // 4 elements, 0x10 bytes (sizeof)
/*0x01C*/ ULONG32 ValidAccessMask; //访问掩码
/*0x020*/ ULONG32 RetainAccess;
/*0x024*/ enum _POOL_TYPE PoolType;
/*0x028*/ ULONG32 DefaultPagedPoolCharge;
/*0x02C*/ ULONG32 DefaultNonPagedPoolCharge;
/*0x030*/ FUNCT_00A3_0FB4_DumpProcedure* DumpProcedure;
/*0x038*/ FUNCT_005B_0FBC_OpenProcedure* OpenProcedure;
/*0x040*/ FUNCT_00A3_0FCA_CloseProcedure* CloseProcedure;
/*0x048*/ FUNCT_00A3_072C_Free_IdleHandler_InterfaceReference_InterfaceDereference_DeleteProcedure_WorkerRoutine_Callback_ReleaseFromLazyWrite_ReleaseFromReadAhead* DeleteProcedure;
/*0x050*/ FUNCT_005B_0FD0_ParseProcedure* ParseProcedure;
/*0x058*/ FUNCT_005B_0FDC_SecurityProcedure* SecurityProcedure;
/*0x060*/ FUNCT_005B_0FED_QueryNameProcedure* QueryNameProcedure;
/*0x068*/ FUNCT_0065_0FF5_OkayToCloseProcedure* OkayToCloseProcedure;
}OBJECT_TYPE_INITIALIZER, *POBJECT_TYPE_INITIALIZER;
全局内核句柄表, 进程pid,线程tid的本质
全局变量:PspCidTable,这个表是系统上所有进程和线程对象所在的表,而且只含有进程和线程
所有pid和tid是它的索引,所有pid和tid的集合没有重复,就是说不会有一个pid和tid的值相同,即便跨进程
kd> dq PspCidTable
fffff800`04072bc8 fffff8a0`00004880 00000000`00000000
fffff800`04072bd8 ffffffff`80000020 00000000`00000101
fffff800`04072be8 ffffffff`800002dc ffffffff`80000024
fffff8a0`00004880为handle_table
kd> dt _handle_table fffff8a0`00004880
nt!_HANDLE_TABLE
+0x000 TableCode : 0xfffff8a0`01201001 说明是二级表
+0x008 QuotaProcess : (null)
+0x010 UniqueProcessId : (null)
+0x018 HandleLock : _EX_PUSH_LOCK
+0x020 HandleTableList : _LIST_ENTRY [ 0xfffff8a0`000048a0 - 0xfffff8a0`000048a0 ]
+0x030 HandleContentionEvent : _EX_PUSH_LOCK
+0x038 DebugInfo : (null)
+0x040 ExtraInfoPages : 0n0
+0x044 Flags : 1
+0x044 StrictFIFO : 0y1
+0x048 FirstFreeHandle : 0x3b0
+0x050 LastFreeHandleEntry : 0xfffff8a0`01202e70 _HANDLE_TABLE_ENTRY
+0x058 HandleCount : 0x228
+0x05c NextHandleNeedingPool : 0xc00
kd> dq 0xfffff8a0`01201000
fffff8a0`01201000 fffff8a0`00005000 fffff8a0`01202000
fffff8a0`01201010 fffff8a0`01831000 00000000`00000000
fffff8a0`01201020 00000000`00000000 00000000`00000000
kd> dt _handle_table_entry fffff8a0`00005010
nt!_HANDLE_TABLE_ENTRY
+0x000 Object : 0xfffffa80`18dc5741 Void system进程的eprocess
+0x000 ObAttributes : 0x18dc5741
+0x000 InfoTable : 0xfffffa80`18dc5741 _HANDLE_TABLE_ENTRY_INFO
+0x000 Value : 0xfffffa80`18dc5741
+0x008 GrantedAccess : 0
+0x008 GrantedAccessIndex : 0
+0x00a CreatorBackTraceIndex : 0
+0x008 NextFreeTableEntry : 0
kd> !process 0 0 system
PROCESS fffffa8018dc5740
SessionId: none Cid: 0004 Peb: 00000000 ParentCid: 0000
DirBase: 00187000 ObjectTable: fffff8a000001780 HandleCount: 507.
Image: System
对象体作为ObGetObjectType的参数,返回对象类型.
一级表遍历方法: pid=0x110
kd> db poi(fffff8a0`00005000+0x10*(110/4))-1+0x2e0
fffffa80`1ad37e10 73 76 63 68 6f 73 74 2e-65 78 65 00 00 00 00 02 svchost.exe.....
fffffa80`1ad37e20 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
fffffa80`1ad37e30 00 00 00 00 00 00 00 00-c0 9d d3 1a 80 fa ff ff ................
fffffa80`1ad37e40 80 6f da 1a 80 fa ff ff-00 00 00 00 00 00 00 00 .o..............
fffffa80`1ad37e50 00 00 00 00 00 00 00 00-0e 00 00 00 c5 ef db f5 ................
fffffa80`1ad37e60 00 00 00 00 00 00 00 00-00 e0 fd ff ff 07 00 00 ................
fffffa80`1ad37e70 00 00 00 00 00 00 00 00-3c 08 00 00 00 00 00 00 ........<.......
fffffa80`1ad37e80 06 00 00 00 00 00 00 00-c1 2f 00 00 00 00 00 00 ........./......
二级表遍历方法:pid=0x460
kd> db poi(poi(fffff8a0`01201000+8)+0x10*((460-0x400)/4))-1+0x2e0
fffffa80`1ad48340 73 70 6f 6f 6c 73 76 2e-65 78 65 00 00 00 00 02 spoolsv.exe.....
fffffa80`1ad48350 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
fffffa80`1ad48360 00 00 00 00 00 00 00 00-80 24 d4 1a 80 fa ff ff .........$......
fffffa80`1ad48370 70 1d 15 1b 80 fa ff ff-00 00 00 00 00 00 00 00 p...............
fffffa80`1ad48380 00 00 00 00 00 00 00 00-0c 00 00 00 39 ff d0 e4 ............9...
fffffa80`1ad48390 00 00 00 00 00 00 00 00-00 40 fd ff ff 07 00 00 .........@......
fffffa80`1ad483a0 00 00 00 00 00 00 00 00-00 00 00 00 00 00 00 00 ................
fffffa80`1ad483b0 00 00 00 00 00 00 00 00-c4 02 00 00 00 00 00 00 ................
每个表最大的句柄值为0x400,超过的为(pid-0x400)/4
一些操作:
//根据调试对象类型名字,获取调试对象类型指针, L"name"
PVOID MyGetObjectType(PWCHAR ObjectTypeName)
{
//
//需要声明下函数 ->NTKERNELAPI PVOID ObGetObjectType(HANDLE ObjectAdd);
//
UNICODE_STRING name;
BOOLEAN i = 2;
PVOID pObjectType;
if (ObjectTypeName == NULL)
{
return 0;
}
RtlInitUnicodeString(&name, ObjectTypeName); //初始化
while (ObGetObjectType((PVOID)(&i + 0x18))) //遍历循环对象类型数组
{
pObjectType = ObGetObjectType(&i + 0x18); //获取对象类型结构的指针
i++;
//返回真表示,字符串相等,则找到了对应的名字的对象类型了
if (RtlEqualUnicodeString((PVOID)((ULONG_PTR)pObjectType + 0x10), &name, TRUE))
{
return pObjectType;//返回对象类型地址
}
}
return 0; //否则没有找到则返回0;
}
//调用方法
PVOID gDebugObjectType = 0;
gDebugObjectType = MyGetObjectType(L"DebugObject");
进程句柄表遍历:
#ifndef F_HANDLE
#define F_HANDLE
#include
#define HANDLE_TABLE_OFFSET7 0x200
#define IMAGE_FILE_NAME_OFFSET7 0x2E0
typedef struct _HANDLE_TABLE_ENTRY // 8 elements, 0x10 bytes (sizeof)
{
union // 4 elements, 0x8 bytes (sizeof)
{
/*0x000*/ VOID* Object;
/*0x000*/ ULONG32 ObAttributes;
/*0x000*/ PVOID* InfoTable;
/*0x000*/ UINT64 Value;
};
union // 3 elements, 0x8 bytes (sizeof)
{
/*0x008*/ ULONG32 GrantedAccess;
struct // 2 elements, 0x8 bytes (sizeof)
{
/*0x008*/ UINT16 GrantedAccessIndex;
/*0x00A*/ UINT16 CreatorBackTraceIndex;
/*0x00C*/ UINT8 _PADDING0_[0x4];
};
/*0x008*/ ULONG32 NextFreeTableEntry;
};
}HANDLE_TABLE_ENTRY, *PHANDLE_TABLE_ENTRY;
typedef struct _HANDLE_TABLE // 15 elements, 0x68 bytes (sizeof)
{
/*0x000*/ UINT64 TableCode;
/*0x008*/ struct _EPROCESS* QuotaProcess;
/*0x010*/ VOID* UniqueProcessId;
/*0x018*/ UINT64 HandleLock; // 7 elements, 0x8 bytes (sizeof)
/*0x020*/ struct _LIST_ENTRY HandleTableList; // 2 elements, 0x10 bytes (sizeof)
/*0x030*/ UINT64 HandleContentionEvent; // 7 elements, 0x8 bytes (sizeof)
/*0x038*/ PVOID DebugInfo;
/*0x040*/ LONG32 ExtraInfoPages;
union // 2 elements, 0x4 bytes (sizeof)
{
/*0x044*/ ULONG32 Flags;
/*0x044*/ UINT8 StrictFIFO : 1; // 0 BitPosition
};
/*0x048*/ ULONG32 FirstFreeHandle;
/*0x04C*/ UINT8 _PADDING0_[0x4];
/*0x050*/ struct _HANDLE_TABLE_ENTRY* LastFreeHandleEntry;
/*0x058*/ ULONG32 HandleCount;
/*0x05C*/ ULONG32 NextHandleNeedingPool;
/*0x060*/ ULONG32 HandleCountHighWatermark;
/*0x064*/ UINT8 _PADDING1_[0x4];
}HANDLE_TABLE, *PHANDLE_TABLE;
typedef struct _OBJECT_HEADER // 12 elements, 0x38 bytes (sizeof)
{
/*0x000*/ INT64 PointerCount;
union // 2 elements, 0x8 bytes (sizeof)
{
/*0x008*/ INT64 HandleCount;
/*0x008*/ VOID* NextToFree;
};
/*0x010*/ INT64 Lock; // 7 elements, 0x8 bytes (sizeof)
/*0x018*/ UINT8 TypeIndex;
/*0x019*/ UINT8 TraceFlags;
/*0x01A*/ UINT8 InfoMask;
/*0x01B*/ UINT8 Flags;
/*0x01C*/ UINT8 _PADDING0_[0x4];
union // 2 elements, 0x8 bytes (sizeof)
{
/*0x020*/ PVOID ObjectCreateInfo;
/*0x020*/ VOID* QuotaBlockCharged;
};
/*0x028*/ VOID* SecurityDescriptor;
/*0x030*/ struct _QUAD Body; // 2 elements, 0x8 bytes (sizeof)
}OBJECT_HEADER, *POBJECT_HEADER;
typedef struct _OBJECT_TYPE_INITIALIZER // 25 elements, 0x70 bytes (sizeof)
{
/*0x000*/ UINT16 Length;
union // 2 elements, 0x1 bytes (sizeof)
{
/*0x002*/ UINT8 ObjectTypeFlags;
struct // 7 elements, 0x1 bytes (sizeof)
{
/*0x002*/ UINT8 CaseInsensitive : 1; // 0 BitPosition
/*0x002*/ UINT8 UnnamedObjectsOnly : 1; // 1 BitPosition
/*0x002*/ UINT8 UseDefaultObject : 1; // 2 BitPosition
/*0x002*/ UINT8 SecurityRequired : 1; // 3 BitPosition
/*0x002*/ UINT8 MaintainHandleCount : 1; // 4 BitPosition
/*0x002*/ UINT8 MaintainTypeList : 1; // 5 BitPosition
/*0x002*/ UINT8 SupportsObjectCallbacks : 1; // 6 BitPosition
};
};
/*0x004*/ ULONG32 ObjectTypeCode;
/*0x008*/ ULONG32 InvalidAttributes;
/*0x00C*/ struct _GENERIC_MAPPING GenericMapping; // 4 elements, 0x10 bytes (sizeof)
/*0x01C*/ ULONG32 ValidAccessMask;
/*0x020*/ ULONG32 RetainAccess;
/*0x024*/ enum _POOL_TYPE PoolType;
/*0x028*/ ULONG32 DefaultPagedPoolCharge;
/*0x02C*/ ULONG32 DefaultNonPagedPoolCharge;
/*0x030*/ PVOID DumpProcedure;
/*0x038*/ VOID* OpenProcedure;
/*0x040*/ VOID* CloseProcedure;
/*0x048*/ VOID* DeleteProcedure;
/*0x050*/ VOID* ParseProcedure;
/*0x058*/ VOID* SecurityProcedure;
/*0x060*/ VOID* QueryNameProcedure;
/*0x068*/ VOID* OkayToCloseProcedure;
}OBJECT_TYPE_INITIALIZER, *POBJECT_TYPE_INITIALIZER;
typedef struct _OBJECT_TYPE7 // 12 elements, 0xD0 bytes (sizeof)
{
/*0x000*/ struct _LIST_ENTRY TypeList; // 2 elements, 0x10 bytes (sizeof)
/*0x010*/ struct _UNICODE_STRING Name; // 3 elements, 0x10 bytes (sizeof) 类型名字
/*0x020*/ VOID* DefaultObject;
/*0x028*/ UINT8 Index; //在ObTypeIndexTable中的索引
/*0x029*/ UINT8 _PADDING0_[0x3];
/*0x02C*/ ULONG32 TotalNumberOfObjects;
/*0x030*/ ULONG32 TotalNumberOfHandles;
/*0x034*/ ULONG32 HighWaterNumberOfObjects;
/*0x038*/ ULONG32 HighWaterNumberOfHandles;
/*0x03C*/ UINT8 _PADDING1_[0x4];
/*0x040*/ struct _OBJECT_TYPE_INITIALIZER TypeInfo; // 25 elements, 0x70 bytes (sizeof)
/*0x0B0*/ ULONG64 TypeLock; // 7 elements, 0x8 bytes (sizeof)
/*0x0B8*/ ULONG32 Key;
/*0x0BC*/ UINT8 _PADDING2_[0x4];
/*0x0C0*/ struct _LIST_ENTRY CallbackList; // 2 elements, 0x10 bytes (sizeof) 该类型对象的回调函数链表
}OBJECT_TYPE7, *POBJECT_TYPE7;
NTKERNELAPI NTSTATUS PsLookupProcessByProcessId(HANDLE Id, PEPROCESS *Process);
NTKERNELAPI POBJECT_TYPE ObGetObjectType(PVOID Object);
NTSTATUS EnumProcessHandles(ULONG pid)
{
PEPROCESS eproc;
NTSTATUS ret;
ret = PsLookupProcessByProcessId(pid, &eproc);
if (!NT_SUCCESS(ret))
{
return ret;
}
ObDereferenceObject(eproc);
PHANDLE_TABLE ht = *(PULONG64)((ULONG64)eproc + HANDLE_TABLE_OFFSET7);
ULONG64 tablecode = ht->TableCode;
UINT8 level = tablecode & (0x3);
PHANDLE_TABLE_ENTRY pTable;
ULONG64* pTable2;
ULONG64* pTable3;
PHANDLE_TABLE_ENTRY pEntry;
ULONG64* pEntry2;
ULONG64* pEntry3;
POBJECT_HEADER pObjh;
POBJECT_TYPE7 obt;
ULONG32 handle_value=0;
ULONG count = 0;
if (level == 0)//1级表
{
pTable = tablecode & (0xfffffffffffffffc);
pEntry = pTable;
while (pEntry&&count<(PAGE_SIZE/sizeof(HANDLE_TABLE_ENTRY)))
{
pObjh = (ULONG64)(pEntry->Object)&(0xfffffffffffffff8);
if (pObjh)
{
obt = (POBJECT_TYPE7)ObGetObjectType(&pObjh->Body);
if (obt)
{
DbgPrint("handle_value:%d, handle_type:%wZ, handle_type_index:%x, object_body:%p\n", handle_value, &obt->Name, obt->Index, &pObjh->Body);
}
}
handle_value += 4;
pEntry++;
count++;
}
}
else if (level == 1)//2级表
{
pTable2 = (ULONG64*)(tablecode & (0xfffffffffffffffc));
pEntry2 = pTable2;
while (*pEntry2)
{
pEntry = *pEntry2;
while (pEntry&&count < (PAGE_SIZE / sizeof(HANDLE_TABLE_ENTRY)))
{
pObjh = (ULONG64)(pEntry->Object) & 0xfffffffffffffff8;
if (pObjh)
{
obt = (POBJECT_TYPE7)ObGetObjectType(&pObjh->Body);
if (obt)
{
DbgPrint("handle_value:%d, handle_type:%wZ, handle_type_index:%x, object_body:%p\n", handle_value, &obt->Name, obt->Index, &pObjh->Body);
}
}
handle_value += 4;
pEntry++;
count++;
}
count = 0;
pEntry2++;
}
}
else if (level == 2)//3级表
{
pTable3 = (ULONG64*)(tablecode & (0xfffffffffffffffc));
pEntry3 = pTable3;
while (*pEntry3)
{
DbgBreakPoint();
pEntry2 = *pEntry3;
while (*pEntry2)
{
pEntry = *pEntry2;
while (pEntry&&count < (PAGE_SIZE / sizeof(HANDLE_TABLE_ENTRY)))
{
pObjh = (ULONG64)(pEntry->Object) & 0xfffffffffffffff8;
if (pObjh)
{
obt = (POBJECT_TYPE7)ObGetObjectType(&pObjh->Body);
if (obt)
{
DbgPrint("handle_value:%d, handle_type:%wZ, handle_type_index:%x, object_body:%p\n", handle_value, &obt->Name, obt->Index, &pObjh->Body);
}
}
handle_value += 4;
pEntry++;
count++;
}
count = 0;
pEntry2++;
}
pEntry3++;
}
}
return ret;
}
根据进程id查找目标句柄属性:
NTSTATUS GetProcessHandle(ULONG pid, ULONG tarpid, PHANDLE_TABLE_ENTRY* buffer)
{
PEPROCESS eproc;
NTSTATUS ret;
ret = PsLookupProcessByProcessId(pid, &eproc);
if (!NT_SUCCESS(ret))
{
return ret;
}
ObDereferenceObject(eproc);
PHANDLE_TABLE ht = *(PULONG64)((ULONG64)eproc + HANDLE_TABLE_OFFSET7);
ULONG64 tablecode = ht->TableCode;
UINT8 level = tablecode & (0x3);
PHANDLE_TABLE_ENTRY pTable;
ULONG64* pTable2;
ULONG64* pTable3;
PHANDLE_TABLE_ENTRY pEntry;
ULONG64* pEntry2;
ULONG64* pEntry3;
POBJECT_HEADER pObjh;
POBJECT_TYPE7 obt;
ULONG32 handle_value = 0;
ULONG count = 0;
ULONG64 PID;
if (level == 0)//1级表
{
pTable = tablecode & (0xfffffffffffffffc);
pEntry = pTable;
while (pEntry&&count < (PAGE_SIZE / sizeof(HANDLE_TABLE_ENTRY)))
{
pObjh = (ULONG64)(pEntry->Object)&(0xfffffffffffffff8);
if (pObjh)
{
obt = (POBJECT_TYPE7)ObGetObjectType(&pObjh->Body);
if (obt)
{
//DbgPrint("handle_value:%d, handle_type:%wZ, handle_type_index:%x, object_body:%p\n", handle_value, &obt->Name, obt->Index, &pObjh->Body);
if (obt->Index == 0x7)
{
PID = *(ULONG64*)(UniqueProcessId_OFFSET7 + (ULONG64)(&pObjh->Body));
if (PID == tarpid)
{
*buffer = pEntry;
DbgPrint("handle:%d\n", handle_value);
return ret;
}
}
}
}
handle_value += 4;
pEntry++;
count++;
}
}
else if (level == 1)//2级表
{
pTable2 = (ULONG64*)(tablecode & (0xfffffffffffffffc));
pEntry2 = pTable2;
while (*pEntry2)
{
pEntry = *pEntry2;
while (pEntry&&count < (PAGE_SIZE / sizeof(HANDLE_TABLE_ENTRY)))
{
pObjh = (ULONG64)(pEntry->Object) & 0xfffffffffffffff8;
if (pObjh)
{
obt = (POBJECT_TYPE7)ObGetObjectType(&pObjh->Body);
if (obt)
{
//DbgPrint("handle_value:%d, handle_type:%wZ, handle_type_index:%x, object_body:%p\n", handle_value, &obt->Name, obt->Index, &pObjh->Body);
if (obt->Index == 0x7)
{
PID = *(ULONG64*)(UniqueProcessId_OFFSET7 + (ULONG64)(&pObjh->Body));
if (PID == tarpid)
{
*buffer = pEntry;
return ret;
}
}
}
}
handle_value += 4;
pEntry++;
count++;
}
count = 0;
pEntry2++;
}
}
else if (level == 2)//3级表
{
pTable3 = (ULONG64*)(tablecode & (0xfffffffffffffffc));
pEntry3 = pTable3;
while (*pEntry3)
{
DbgBreakPoint();
pEntry2 = *pEntry3;
while (*pEntry2)
{
pEntry = *pEntry2;
while (pEntry&&count < (PAGE_SIZE / sizeof(HANDLE_TABLE_ENTRY)))
{
pObjh = (ULONG64)(pEntry->Object) & 0xfffffffffffffff8;
if (pObjh)
{
obt = (POBJECT_TYPE7)ObGetObjectType(&pObjh->Body);
if (obt)
{
//DbgPrint("handle_value:%d, handle_type:%wZ, handle_type_index:%x, object_body:%p\n", handle_value, &obt->Name, obt->Index, &pObjh->Body);
if (obt->Index == 0x7)
{
PID = *(ULONG64*)(UniqueProcessId_OFFSET7 + (ULONG64)(&pObjh->Body));
if (PID == tarpid)
{
*buffer = pEntry;
return ret;
}
}
}
}
handle_value += 4;
pEntry++;
count++;
}
count = 0;
pEntry2++;
}
pEntry3++;
}
}
return ret;
}
系统句柄表遍历
void EnumSystemHandles(ULONG64* PspCidTable)
{
PEPROCESS eproc;
NTSTATUS ret;
PHANDLE_TABLE ht = *PspCidTable;
ULONG64 tablecode = ht->TableCode;
UINT8 level = tablecode & (0x3);
PHANDLE_TABLE_ENTRY pTable;
ULONG64* pTable2;
ULONG64* pTable3;
PHANDLE_TABLE_ENTRY pEntry;
ULONG64* pEntry2;
ULONG64* pEntry3;
POBJECT_HEADER pObjh;
POBJECT_TYPE7 obt;
ULONG32 handle_value = 0;
ULONG count = 0;
//在系统句柄表中,pObjh直接就是对象体,而不是对象头
if (level == 0)//1级表
{
pTable = tablecode & (0xfffffffffffffffc);
pEntry = pTable;
while (pEntry&&count < (PAGE_SIZE / sizeof(HANDLE_TABLE_ENTRY)))
{
pObjh = (ULONG64)(pEntry->Object)&(0xfffffffffffffff8);
if (pObjh)
{
obt = (POBJECT_TYPE7)ObGetObjectType(pObjh);
if (obt)
{
DbgPrint("handle_value:%d, handle_type:%wZ, handle_type_index:%x, object_body:%p\n", handle_value, &obt->Name, obt->Index, pObjh);
}
}
handle_value += 4;
pEntry++;
count++;
}
}
else if (level == 1)//2级表
{
pTable2 = (ULONG64*)(tablecode & (0xfffffffffffffffc));
pEntry2 = pTable2;
while (*pEntry2)
{
pEntry = *pEntry2;
while (pEntry&&count < (PAGE_SIZE / sizeof(HANDLE_TABLE_ENTRY)))
{
pObjh = (ULONG64)(pEntry->Object) & 0xfffffffffffffff8;
if (pObjh)
{
obt = (POBJECT_TYPE7)ObGetObjectType(pObjh);
if (obt)
{
DbgPrint("handle_value:%d, handle_type:%wZ, handle_type_index:%x, object_body:%p\n", handle_value, &obt->Name, obt->Index, pObjh);
}
}
handle_value += 4;
pEntry++;
count++;
}
count = 0;
pEntry2++;
}
}
else if (level == 2)//3级表
{
pTable3 = (ULONG64*)(tablecode & (0xfffffffffffffffc));
pEntry3 = pTable3;
while (*pEntry3)
{
DbgBreakPoint();
pEntry2 = *pEntry3;
while (*pEntry2)
{
pEntry = *pEntry2;
while (pEntry&&count < (PAGE_SIZE / sizeof(HANDLE_TABLE_ENTRY)))
{
pObjh = (ULONG64)(pEntry->Object) & 0xfffffffffffffff8;
if (pObjh)
{
obt = (POBJECT_TYPE7)ObGetObjectType(pObjh);
if (obt)
{
DbgPrint("handle_value:%d, handle_type:%wZ, handle_type_index:%x, object_body:%p\n", handle_value, &obt->Name, obt->Index, pObjh);
}
}
handle_value += 4;
pEntry++;
count++;
}
count = 0;
pEntry2++;
}
pEntry3++;
}
}
}