通过PspCidTable枚举进程

如果当前进程为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);
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值