win10 x64驱动实现遍历全局句柄表

x64驱动实现遍历全局句柄表

驱动代码

#include "vad.h"
#include <ntifs.h>

//获取全部变量PspCidTable
//指向一张表,里面存储的是512个句柄表指针
VOID table_1(ULONG64 BaseAddr);

//遍历每个句柄表指针; 句柄表指针指向一个表,里面存储
//的是进程或线程对象地址;16个字节;1024/16 = 256个;
VOID table_2(ULONG64 BaseAddr, INT index1);


VOID UnDriver(PDRIVER_OBJECT driver)
{
	DbgPrint("卸载成功 \n");
}

NTSTATUS DriverEntry(IN PDRIVER_OBJECT Driver, PUNICODE_STRING RegistryPath)
{
	DbgPrint("进入l \n");
	UNICODE_STRING uc_funcName;
	RtlInitUnicodeString(&uc_funcName, L"PsLookupProcessByProcessId");
	LONGLONG* ul_funcAddr = MmGetSystemRoutineAddress(&uc_funcName);
	if (ul_funcAddr == NULL)
	{
		return FALSE;
	}
	DbgPrint("PsLookupProcessByProcessId addr = %p \n", ul_funcAddr);
	LONG64 CidTable_entry = 0;
	for (int i = 0; i < 120; i++)
	{
		//找E8 call
		if ((*((PUCHAR)ul_funcAddr + i)) == 0xe8)
		{
			CidTable_entry = (LONG64)((PUCHAR)ul_funcAddr + i);
			break;
		}
	}

	PLONG64 pPspCidTable = NULL;
	if (CidTable_entry != 0)
	{
		//求出JMP 地址:ul_entry + 5 + 偏移地址
		int dwOffset = *(INT*)(CidTable_entry + 1);
		ULONG64 CidTableEntry_callJmp = CidTable_entry + dwOffset + 5;
		DbgPrint("CidTableEntry_callJmp addr = %p \n", CidTableEntry_callJmp);



		for (INT i = 0; i < 200; i++)
		{
			// fffff802`0841d1a5 48 8b 0d 84 73 f5 ff  mov     rcx,qword ptr [nt!PspCidTable (fffff802`08374530)]
			if (*(PUCHAR)(CidTableEntry_callJmp + i) == 0x48 && *(PUCHAR)(CidTableEntry_callJmp + i + 1) == 0x8b && *(PUCHAR)(CidTableEntry_callJmp + i + 2) == 0x05)
			{
				// 解析 mov 地址
				INT movCode = *(INT*)(CidTableEntry_callJmp + i + 3);
				DbgPrint("movCode = %p \n", movCode);
				ULONG64 movJmp = CidTableEntry_callJmp + i + movCode + 7;
				DbgPrint("movJmp = %p \n", movJmp);

				// 得到 PspCidTable
				pPspCidTable = (PLONG64)movJmp;
				DbgPrint("pPspCidTable addr = %p \n", pPspCidTable);
	
			}
		}
	
	}
	if (pPspCidTable == NULL)
	{
		return STATUS_SUCCESS;
	}
	//判断是几级表
	LONG64 Table_code = *((PLONG64)((*pPspCidTable) + 8));
	INT Grade = Table_code & 3;
	DbgPrint("Table_code = %p \n", Table_code);
	DbgPrint("Grade = %X \n", Grade);
	if (Grade == 0)
	{
	
	}
	else if (Grade == 1)
	{

		table_1(Table_code & (~3));
	}


	Driver->DriverUnload = UnDriver;
	return STATUS_SUCCESS;
}

VOID table_2(ULONG64 BaseAddr, INT index1)
{
// 遍历一级表(每个表项大小 16 ),表大小 4k,所以遍历 4096/16 = 256 次
	PEPROCESS p_eprocess = NULL;
	PETHREAD p_ethread = NULL;
	INT p_id = 0;
	for (INT i = 0; i < 256; i++)
	{
		if (!MmIsAddressValid((PVOID64)(BaseAddr + i * 16)))
		{
			DbgPrint("非法地址= %p \n", BaseAddr + i * 16);
			continue;
		}

		ULONG64 Table1_code = *(PULONG64)(BaseAddr + i * 16);

		// 换算 先右移16位 在与上0xfffffffffffffff0
		ULONG64 Table1_decode = (LONG64)Table1_code >> 0x10;
		Table1_decode &= 0xfffffffffffffff0;

		//计算方式说明:i*4->windows规定。
		//1024*index1-> 因为一个表有256个对象地址,那么256*4 = 1024;
		//1024*  index1代表第几个句柄指针索引
		p_id = i * 4 + 1024 * index1;

		// 判断是进程还是线程
		if (PsLookupProcessByProcessId((HANDLE)p_id, &p_eprocess) == STATUS_SUCCESS)
		{
			DbgPrint("进程PID: %d | ID: %d | 对象: %p \n", p_id, i, Table1_decode);
		}
		else if (PsLookupThreadByThreadId((HANDLE)p_id, &p_ethread) == STATUS_SUCCESS)
		{
			DbgPrint("线程TID: %d | ID: %d | 对象: %p \n", p_id, i , Table1_decode);
		}
	}
}



VOID table_1(ULONG64 BaseAddr)
{
	// 遍历二级表(每个表项大小 8),表大小 4k,所以遍历 4096/8 = 512 次
	ULONG64 ul_baseAddr_1 = 0;
	for (INT i = 0; i < 512; i++)
	{
		if (!MmIsAddressValid((PVOID64)(BaseAddr + i * 8)))
		{
			DbgPrint("非法二级表指针(1):%p \n", BaseAddr + i * 8);
			continue;
		}
		if (!MmIsAddressValid((PVOID64) * (PULONG64)(BaseAddr + i * 8)))
		{
			DbgPrint("非法二级表指针(2):%p \n", BaseAddr + i * 8);
			continue;
		}
		ul_baseAddr_1 = *(PULONG64)(BaseAddr + i * 8);
		table_2(ul_baseAddr_1, i);
	}
}



总结

不懂可以私信我!!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值