如果当前进程为System进程,就意味着此次打开的内核对象访问权限属于内核,那么就使用内核句柄表, 内
核句柄与用户句柄不同的地方就在于内核句柄需要或上一个0x80000000即最高位置为1作为标识,
但是实际在使用句柄的时候还是不需要这个最高位值的。进程的句柄表由EPROCESS中的
ObjectTable成员进行管理, 句柄表有3种内存结构分别为一级表,二级表以及三级表。表的结构
由进程中的句柄数决定,属于一个动态增长以及改变的过程,一级表能够存储句柄数为512, 二级为
1024*512,三级表为1024*1024*512。
// 获取PspCidTable地址
PULONG_PTR GetPspCidTable()
{
UNICODE_STRING uStrName;
ULONG_PTR pPsLookupProcessByProcessId;
PULONG_PTR PspCidTable;
RtlInitUnicodeString(&uStrName, L"PsLookupProcessByProcessId");
pPsLookupProcessByProcessId = (ULONG_PTR)MmGetSystemRoutineAddress(&uStrName);
if (!pPsLookupProcessByProcessId)
{
KdPrint(("PsLookupProcessByProcessId Can not Find Addresss"));
return 0;
}
KdPrint(("PsLookupProcessByProcessId:%p\n", pPsLookupProcessByProcessId));
// 488bd1 mov rdx, rcx
// 488b0d9149edff mov rcx, qword ptr[nt!PspCidTable(fffff800`0402ebc8)]
for (PUCHAR i = (PUCHAR)pPsLookupProcessByProcessId; i < pPsLookupProcessByProcessId + 0xff; i++)
{
// KdPrint(("PspCidTable:%x\n", *i));
if (*i == 0x48 && *(i + 1) == 0x8b && *(i + 2) == 0xd1)
{
PspCidTable = (LONG_PTR*)(*(LONG*)(i + 3 + 3) + 7 + 3 + i);
KdPrint(("PspCidTable:%p\n", PspCidTable));
return PspCidTable;
}
}
return 0;
}
//自己实现一个山寨的MyEnumHandleTable,接口和ExEnumHandleTable一样
BOOLEAN
MyEnumHandleTable(
PHANDLE_TABLE HandleTable,
MY_ENUMERATE_HANDLE_ROUTINE EnumHandleProcedure,
PVOID EnumParameter,
PHANDLE Handle
)
{
ULONG64 i, j, k;
ULONG_PTR CapturedTable;
ULONG64 TableLevel;
PHANDLE_TABLE_ENTRY TableLevel1, *TableLevel2, **TableLevel3;
BOOLEAN CallBackRetned = FALSE;
BOOLEAN ResultValue = FALSE;
ULONG64 MaxHandle;
//判断几个参数是否有效
if (!HandleTable
&& !EnumHandleProcedure
&& !MmIsAddressValid(Handle))
{
return ResultValue;
}
//取表基址和表的级数 , TableCode 的低两位用于表示当前句柄表的级数: 0、1、2 分别表示一级表、二级表和三级表。
CapturedTable = (HandleTable->TableCode)&~3;
TableLevel = (HandleTable->TableCode) & 3;
MaxHandle = HandleTable->NextHandleNeedingPool;
DbgPrint("句柄上限值为0x%X\n", MaxHandle);
//判断表的等级
switch (TableLevel)
{
case 0:
{
//一级表
TableLevel1 = (PHANDLE_TABLE_ENTRY)CapturedTable;
DbgPrint("解析一级表 0x%p...\n", TableLevel1);
for (i = 0; i < MAX_ENTRY_COUNT; i++)
{
*Handle = (HANDLE)(i * 4);
if (TableLevel1[i].Object && MmIsAddressValid(TableLevel1[i].Object))
{
//对象有效时,再调用回调函数
CallBackRetned = EnumHandleProcedure(&TableLevel1[i], *Handle, EnumParameter);
if (CallBackRetned) break;
}
}
ResultValue = TRUE;
}
break;
case 1:
{
//二级表
TableLevel2 = (PHANDLE_TABLE_ENTRY*)CapturedTable;
DbgPrint("解析二级表 0x%p...\n", TableLevel2);
DbgPrint("二级表的个 数:%d\n", MaxHandle / (MAX_ENTRY_COUNT * 4));
for (j = 0; j < MaxHandle / (MAX_ENTRY_COUNT * 4); j++)
{
TableLevel1 = TableLevel2[j];
if (!TableLevel1)
break; //为零则跳出
for (i = 0; i < MAX_ENTRY_COUNT; i++)
{
*Handle = (HANDLE)(j*MAX_ENTRY_COUNT * 4 + i * 4);
if (TableLevel1[i].Object && MmIsAddressValid(TableLevel1[i].Object))
{
//对象有效时,再调用回调函数
CallBackRetned = EnumHandleProcedure(&TableLevel1[i], *Handle, EnumParameter);
if (CallBackRetned) break;
}
}
}
ResultValue = TRUE;
}
break;
case 2:
{
//三级表
TableLevel3 = (PHANDLE_TABLE_ENTRY**)CapturedTable;
DbgPrint("解析三级表 0x%p...\n", TableLevel3);
DbgPrint("三级表的个 数:%d\n", MaxHandle / (MAX_ENTRY_COUNT * 4 * MAX_ADDR_COUNT));
for (k = 0; k < MaxHandle / (MAX_ENTRY_COUNT * 4 * MAX_ADDR_COUNT); k++)
{
TableLevel2 = TableLevel3[k];
if (!TableLevel2)
break; //为零则跳出
for (j = 0; j < MaxHandle / (MAX_ENTRY_COUNT * 4); j++)
{
TableLevel1 = TableLevel2[j];
if (!TableLevel1)
break; //为零则跳出
for (i = 0; i < MAX_ENTRY_COUNT; i++)
{
*Handle = (HANDLE)(k*MAX_ENTRY_COUNT*MAX_ADDR_COUNT + j*MAX_ENTRY_COUNT + i * 4);
if (TableLevel1[i].Object && MmIsAddressValid(TableLevel1[i].Object))
{
//对象有效时,再调用回调函数
CallBackRetned = EnumHandleProcedure(&TableLevel1[i], *Handle, EnumParameter);
if (CallBackRetned) break;
}
}
}
}
ResultValue = TRUE;
}
break;
default:
{
DbgPrint("BOOM!\n");
}
break;
}
DbgPrint("ProcessCount:0x%x", g_ProcessCount);
return ResultValue;
}
VOID StartEnum()
{
PULONG_PTR PspCidTable;
PHANDLE hLastHandle;
PspCidTable = GetPspCidTable();
ExEnumHandleTable((PHANDLE_TABLE)*PspCidTable, MyEnumerateHandleRoutine, NULL, &hLastHandle);
}