枚举内核句柄表(Windows内核学习笔记)
日期: 2020-04-14 分类: 个人收藏 512次阅读
前面我写过有关内核句柄表的一些知识,今天来在这里跟大家分享一下我自己写的内核枚举进程句柄方法。
#include"EnumProcessHandleTable.h"
#ifdef _WIN64
#define _HANDLE_TABLE_ 0x200 //硬偏移Win7x64下的HANDLE_TABLE字段在EPROCESS下的偏移
#define _OFFSET_ 0x10 //TableCode中的第一项是用作审计,需要越过他到达HandleTableEntry
#define _OBJECT_BODY_ 0x30 //64位下,越过ObjectHeader到Body的偏移
typedef struct _HANDLE_TABLE
{
ULONGLONG TableCode; //0x0
PVOID QuotaProcess; //0x8
VOID* UniqueProcessId; //0x10
ULONG64 HandleLock; //0x18
struct _LIST_ENTRY HandleTableList; //0x20
ULONG64 HandleContentionEvent; //0x30
PVOID DebugInfo; //0x38
LONG ExtraInfoPages; //0x40
union
{
ULONG Flags; //0x44
UCHAR StrictFIFO : 1; //0x44
};
ULONG FirstFreeHandle; //0x48
struct _HANDLE_TABLE_ENTRY* LastFreeHandleEntry; //0x50
ULONG HandleCount; //0x58
ULONG NextHandleNeedingPool; //0x5c
ULONG HandleCountHighWatermark; //0x60
}HANDLE_TABLE, *PHANDLE_TABLE;
typedef struct _HANDLE_TABLE_ENTRY
{
union
{
VOID* Object; //0x0
ULONG ObAttributes; //0x0
struct _HANDLE_TABLE_ENTRY_INFO* InfoTable; //0x0
ULONGLONG Value; //0x0
};
union
{
ULONG GrantedAccess; //0x8
struct
{
USHORT GrantedAccessIndex; //0x8
USHORT CreatorBackTraceIndex; //0xa
};
ULONG NextFreeTableEntry; //0x8
};
}HANDLE_TABLE_ENTRY, *PHANDLE_TABLE_ENTRY;
#else
#define _HANDLE_TABLE_ 0x0f4 //硬偏移Win7x86下的HANDLE_TABLE字段在EPROCESS下的偏移
#define _OFFSET_ 0x8 //TableCode中的第一项是用作审计,需要越过他到达HandleTableEntry
#define _OBJECT_BODY_ 0x18 //32位下,越过ObjectHeader到Body的偏移
typedef struct _HANDLE_TABLE
{
ULONG TableCode; //0x0
PVOID QuotaProcess; //0x4
VOID* UniqueProcessId; //0x8
ULONG HandleLock; //0xc
struct _LIST_ENTRY HandleTableList; //0x10
ULONG HandleContentionEvent; //0x18
PVOID DebugInfo; //0x1c
LONG ExtraInfoPages; //0x20
union
{
ULONG Flags; //0x24
UCHAR StrictFIFO : 1; //0x24
};
ULONG FirstFreeHandle; //0x28
PVOID LastFreeHandleEntry; //0x2c
ULONG HandleCount; //0x30
ULONG NextHandleNeedingPool; //0x34
ULONG HandleCountHighWatermark; //0x38
}HANDLE_TABLE, *PHANDLE_TABLE;
//0x8 结构体大小8字节
typedef struct _HANDLE_TABLE_ENTRY
{
union
{
VOID* Object; //0x0
ULONG ObAttributes; //0x0
struct _HANDLE_TABLE_ENTRY_INFO* InfoTable; //0x0
ULONG Value; //0x0
};
union
{
ULONG GrantedAccess; //0x4
struct
{
USHORT GrantedAccessIndex; //0x4
USHORT CreatorBackTraceIndex; //0x6
};
ULONG NextFreeTableEntry; //0x4
};
}HANDLE_TABLE_ENTRY, *PHANDLE_TABLE_ENTRY;
#endif
NTSTATUS DriverEntry(PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegisterPath)
{
UNREFERENCED_PARAMETER(RegisterPath);
HANDLE ProcessID = 0x0FDC; //Taskmgr进程ID,此处给定一个值,为了在虚拟机调试驱动代码
NTSTATUS Status = STATUS_SUCCESS;
DbgPrint("Beginning!\r\n");
DriverObject->DriverUnload = DriverUnload;//驱动卸载例程
//枚举进程句柄表
//这个函数必须在卸载函数的后面,否则可能导致驱动无法卸载
EnumProcessHandleTable(ProcessID);
return Status;
}
VOID DriverUnload(PDRIVER_OBJECT DriverObject)
{
UNREFERENCED_PARAMETER(DriverObject);
DbgPrint("DriverUnload()\r\n");
}
NTSTATUS EnumProcessHandleTable(HANDLE ProcessID)
{
PEPROCESS EProcess = NULL; //进程体指针
PHANDLE_TABLE HandleTable = NULL;
NTSTATUS Status = STATUS_SUCCESS;
ULONG_PTR TableCode = NULL;
ULONG Flag = NULL;
__try
{
//the driver must call ObDereferenceObject to dereference the Process parameter received
//from the PsLookupProcessByProcessID routine.
//必须调用ObReferenceObject解除引用
Status = PsLookupProcessByProcessId(ProcessID,&EProcess);//通过进程ID获得进程体指针
/*
NTSTATUS NTAPI PsLookupProcessByProcessId(IN HANDLE ProcessId,OUT PEPROCESS *Process)
{
PHANDLE_TABLE_ENTRY CidEntry;
PEPROCESS FoundProcess;
NTSTATUS Status = STATUS_INVALID_PARAMETER;
PAGED_CODE();
PSTRACE(PS_PROCESS_DEBUG, "ProcessId: %p\n", ProcessId);
KeEnterCriticalRegion();
CidEntry = ExMapHandleToPointer(PspCidTable, ProcessId);
if (CidEntry)
{
FoundProcess = CidEntry->Object;
if (FoundProcess->Pcb.Header.Type == ProcessObject)
{
if (ObReferenceObjectSafe(FoundProcess))
{
*Process = FoundProcess;
Status = STATUS_SUCCESS;
}
}
ExUnlockHandleTableEntry(PspCidTable, CidEntry);
}
KeLeaveCriticalRegion();
return Status;
}
*/
//MmIsAddressValid判断地址是否有效,内部实现是通过虚拟地址转换物理地址的方法
if (NT_SUCCESS(Status) && MmIsAddressValid(EProcess))
{
/*
kd> dt _Eprocess 894d13c0
nt!_EPROCESS
+0x000 Pcb : _KPROCESS
+0x098 ProcessLock : _EX_PUSH_LOCK
+0x0a0 CreateTime : _LARGE_INTEGER 0x1d4e118`8f81a1dd
+0x0a8 ExitTime : _LARGE_INTEGER 0x0
+0x0b0 RundownProtect : _EX_RUNDOWN_REF
+0x0b4 UniqueProcessId : 0x00000e9c Void
+0x0b8 ActiveProcessLinks : _LIST_ENTRY [ 0x8495aba8 - 0x89756bd8 ]
+0x0c0 ProcessQuotaUsage : [2] 0x1888
+0x0c8 ProcessQuotaPeak : [2] 0x18c4
+0x0d0 CommitCharge : 0x278
+0x0d4 QuotaBlock : 0x8927f640 _EPROCESS_QUOTA_BLOCK
+0x0d8 CpuQuotaBlock : (null)
+0x0dc PeakVirtualSize : 0x5589000
+0x0e0 VirtualSize : 0x4cf5000
+0x0e4 SessionProcessLinks : _LIST_ENTRY [ 0x8eb89010 - 0x895d4e24 ]
+0x0ec DebugPort : (null)
+0x0f0 ExceptionPortData : 0x891f8858 Void
+0x0f0 ExceptionPortValue : 0x891f8858
+0x0f0 ExceptionPortState : 0y000
+0x0f4 ObjectTable : 0xa4b32f58 _HANDLE_TABLE
0: kd> dd 0xa4b32f58
a4b32f58 a5b29000 894d13c0 00000e9c 00000000
a4b32f68 849544e8 a4b0d398 00000000 00000000
a4b32f78 00000000 00000000 000001f4 a5b29ff8
a4b32f88 00000074 00000800 00000080 0043005c
a4b32f98 060d0209 73634946 00000000 87d4c930
a4b32fa8 896fa2c0 a4b32fac 00000000 00000000
a4b32fb8 896fa2ec 8854e478 00000000 00010001
a4b32fc8 00000001 00000000 a4b65118 a4b39fd0
0: kd> dt _Handle_Table 0xa4b32f58
nt!_HANDLE_TABLE
+0x000 TableCode : 0xa5b29000
+0x004 QuotaProcess : 0x894d13c0 _EPROCESS
+0x008 UniqueProcessId : 0x00000e9c Void
+0x00c HandleLock : _EX_PUSH_LOCK
+0x010 HandleTableList : _LIST_ENTRY [ 0x849544e8 - 0xa4b0d398 ]
+0x018 HandleContentionEvent : _EX_PUSH_LOCK
+0x01c DebugInfo : (null)
+0x020 ExtraInfoPages : 0n0
+0x024 Flags : 0
+0x024 StrictFIFO : 0y0
+0x028 FirstFreeHandle : 0x1f4
+0x02c LastFreeHandleEntry : 0xa5b29ff8 _HANDLE_TABLE_ENTRY
+0x030 HandleCount : 0x74
+0x034 NextHandleNeedingPool : 0x800
+0x038 HandleCountHighWatermark : 0x80
0: kd> dd 0xa5b29000
a5b29000 00000000 fffffffe 8e6771e9 00000003
a5b29010 894edde1 00100020 891d0f69 00100020
a5b29020 a4b31cb9 00020019 896233c1 001f0001
a5b29030 894c3d61 001f0001 98dd0819 000f003f
a5b29040 8946a7e9 001f0003 9ceb4f59 00000001
a5b29050 885e7bd9 00000804 88ad40e1 021f0003
a5b29060 89234f91 000f037f 892776f1 000f01ff
a5b29070 89234f91 000f037f 885ce351 00000804
0: kd> !object 8e6771e8+ 0x18 //所有对象的Head 在32位下大小为0x18 64位下为0x30 越过头的偏移
Object: 8e677200 Type: (871446a0) Directory
ObjectHeader: 8e6771e8 (new version)
HandleCount: 37 PointerCount: 83
Directory Object: 8c005ed0 Name: KnownDlls
Hash Address Type Name
---- ------- ---- ----
00 8e67f650 Section gdi32.dll
8e6430e8 Section kernelbase.dll
8c12dfd8 Section IMAGEHLP.dll
02 8c107450 Section NORMALIZ.dll
03 920b2a50 Section ole32.dll
9459cc58 Section URLMON.dll
04 969a8ee0 Section USP10.dll
05 976b4900 Section DEVOBJ.dll
976fa378 Section api-ms-win-downlevel-user32-l1-1-0.dll
06 977cf9c8 Section CFGMGR32.dll
8c122920 Section SHELL32.dll
8e648a60 Section WLDAP32.dll
07 977cf410 Section api-ms-win-downlevel-version-l1-1-0.dll
08 8e63e660 Section api-ms-win-downlevel-ole32-l1-1-0.dll
09 8c10f940 Section user32.dll
977cfa30 Section profapi.dll
14 980f0438 Section MSASN1.dll
16 8c1abf88 SymbolicLink KnownDllPath
977ed590 Section COMCTL32.dll
17 8c1cc330 Section PSAPI.DLL
969a8d80 Section CRYPT32.dll
18 8c122fd8 Section OLEAUT32.dll
8e678880 Section advapi32.dll
8e63e700 Section api-ms-win-downlevel-normaliz-l1-1-0.dll
19 8c1b2598 Section SHLWAPI.dll
8c1f4580 Section IERTUTIL.dll
969a8a98 Section ntdll.dll
20 8c114dd8 Section WS2_32.dll
21 8c191cb8 Section LPK.dll
980f0768 Section USERENV.dll
22 976d6ad8 Section api-ms-win-downlevel-shlwapi-l1-1-0.dll
8e7ff2e0 Section sechost.dll
23 8c12deb8 Section COMDLG32.dll
24 8e673948 Section difxapi.dll
25 8e68b990 Section Setupapi.dll
26 8e63bd70 Section MSCTF.dll
8c064da0 Section WININET.dll
27 8c1a1ea8 Section IMM32.dll
976fa850 Section WINTRUST.dll
28 8c11b238 Section MSVCRT.dll
31 8e648608 Section rpcrt4.dll
8c1f9fd8 Section clbcatq.dll
32 8e6628a8 Section kernel32.dll
34 969e5600 Section api-ms-win-downlevel-advapi32-l1-1-0.dll
35 8e689238 Section NSI.dll
*/
HandleTable = (PHANDLE_TABLE)(*((ULONG_PTR*)((ULONG_PTR)EProcess + _HANDLE_TABLE_)));//0x0f4偏移
if (MmIsAddressValid(HandleTable))
{
TableCode = (ULONG_PTR)(HandleTable->TableCode) & 0xFFFFFFFFFFFFFFFC;
//当TableCode与FFFFFFC按位与的时候,C为 1100 所以会使TableCode的低两位全部变成00;
//即通过按位与操作之后,会使TableCode变为真正的地址
Flag = (ULONG)(HandleTable->TableCode) & 0x03;//得层数
//当TableCode与0x03按位与的时候,3 为 0011 所以会使TableCode的低两位全部变成 00 01 10 11四种可能结果,
//但是句柄表最多只有3层
switch (Flag)
{
case 0: //00
{
//单层表
//511项
Operation0(TableCode);
break;
}
case 1: //01
{
//双层表
//1023项-》511+511
Operation1(TableCode);
break;
}
case 2: //10
{
//三层表
//1024-》1024-》511
Operation2(TableCode);
break;
}
default: //11
{
break;
}
}
}
else
{
Status = STATUS_UNSUCCESSFUL;
}
Status = STATUS_SUCCESS;
}
else
{
return STATUS_UNSUCCESSFUL;
}
}
__except ((EXCEPTION_EXECUTE_HANDLER))
{
}
if (NT_SUCCESS(Status))
{
ObReferenceObject(EProcess);
EProcess = NULL;
}
}
NTSTATUS Operation0(ULONG_PTR TableCode)
{
PHANDLE_TABLE_ENTRY HandleTableEntry = NULL;
ULONG Index = 0;
HandleTableEntry = (PHANDLE_TABLE_ENTRY)((ULONG_PTR*)(TableCode + _OFFSET_));
ULONG_PTR ObjectCount = 0;
for (Index = 0; Index<(PAGE_SIZE / sizeof(HANDLE_TABLE_ENTRY)); Index++)
{
if (MmIsAddressValid((PVOID)HandleTableEntry))
{
PVOID ObjectHeader = (PVOID)(*(ULONG_PTR*)HandleTableEntry & 0xFFFFFFFFFFFFFFF8);
//ObjectHeader 0x1000 大于8的值 全部变为8;小于8的全为0
if (MmIsAddressValid(ObjectHeader))
{
PVOID ObjectBody = (PVOID)((ULONG_PTR)ObjectHeader + _OBJECT_BODY_);
if (MmIsAddressValid(ObjectBody)) //这里应当判断对象是否合法
{
//打印数量以及ObjectBody的地址
ObjectCount++;
DbgPrint("ObjectCount:%d ObjectBody:%p\r\n", ObjectCount,ObjectBody);
}
}
}
HandleTableEntry++; //结构体指针++ 越过当前这个结构体
}
return STATUS_SUCCESS;
}
NTSTATUS Operation1(ULONG_PTR TableCode)
{
do
{
//枚举每一层的句柄表项
Operation0(*(ULONG_PTR*)TableCode);
TableCode += sizeof(ULONG_PTR);
} while (*(PULONG_PTR)TableCode != 0 && MmIsAddressValid((PVOID)*(PULONG_PTR)TableCode));
return STATUS_SUCCESS;
}
NTSTATUS Operation2(ULONG_PTR TableCode)
{
do
{
Operation1(*(ULONG_PTR*)TableCode);
TableCode += sizeof(ULONG_PTR);
} while (*(PULONG_PTR)TableCode != 0);
return STATUS_SUCCESS;
}
“If you can take it,you can make it.”
除特别声明,本站所有文章均为原创,如需转载请以超级链接形式注明出处:SmartCat's Blog
精华推荐