(x64)内存虚拟化

内存虚拟化


内存虚拟化+无痕HOOK。
BOOLEAN SetupEptPaingStructure()
{
	DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_ERROR_LEVEL, "[+] ept init...\n");
	/*
		1. 分配内存
	*/
	PVOID64 ept = (__int64)ExAllocatePoolWithTag(NonPagedPool, (2 + HardWarePhysicsAddressRange + HardWarePhysicsAddressRange * 512) * PAGE_SIZE, 'ept');
	if (!ept)
	{
		DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_ERROR_LEVEL, "[-] ept paing structure 内存分配失败!\n");
		return FALSE;
	}
	else
	{
		DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_ERROR_LEVEL, "[+] ept base: %p\n", ept);
		memset(ept, 0, (2 + HardWarePhysicsAddressRange + HardWarePhysicsAddressRange * 512) * PAGE_SIZE);
		g_vmx_config.EPT.ept_address = ept;
	}


	/*
		2. 配置eptp属性
	*/
	EptPointer eptp = { 0 };
	BOOLEAN bRet = SetupExtendedPageTablePointerRights(&eptp);
	if (!bRet)
	{
		DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_ERROR_LEVEL, "[+] ept开启失败!\n");
		return FALSE;
	}

	/*
		3. 分配内存
		空间分布状态: PT, PDT, PPE(1GB), PXE
	*/
	PVOID64 pa = 0;		// 物理地址
	PEptPtEntry pt = (PEptPtEntry)ept;
	PEptPdEntry pdt = (PEptPdEntry)((__int64)ept + (HardWarePhysicsAddressRange << (30 - 12 + 3)));
	PEptPdptEntry pdpt = (PEptPdptEntry)((__int64)pdt + (HardWarePhysicsAddressRange << (30 - 12 - 9 + 3)));
	PEptPml4Entry pml4t = (PEptPml4Entry)((__int64)pdpt + PAGE_SIZE);

	// eptp属性
	eptp.Bits.physial_address = MmGetPhysicalAddress((PVOID64)pml4t).QuadPart >> 12;
	g_vmx_config.EPT.eptp = eptp.all;
	DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_ERROR_LEVEL, "[+] eptp pa: %p\n", MmGetPhysicalAddress((PVOID64)pml4t).QuadPart);

	// pml4t属性
	pml4t->Bits.physial_address = MmGetPhysicalAddress((PVOID64)pdpt).QuadPart >> 12;
	//DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_ERROR_LEVEL, "[+] pml4t pa: %p\n", pml4t->Bits.physial_address);
	pml4t->Bits.execute_access = TRUE;
	pml4t->Bits.read_access = TRUE;
	pml4t->Bits.write_access = TRUE;

	for (__int64 pdpt_index = 0; pdpt_index < HardWarePhysicsAddressRange; pdpt_index++, pdpt++)
	{
		//pdpt属性配置
		pdpt->Bits.physial_address = MmGetPhysicalAddress((PVOID64)pdt).QuadPart >> 12;
		//DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_ERROR_LEVEL, "[+] pdpt pa: %p\n", pdpt->Bits.physial_address);
		pdpt->Bits.execute_access = TRUE;
		pdpt->Bits.read_access = TRUE;
		pdpt->Bits.write_access = TRUE;

		for (__int64 pdt_index = 0; pdt_index < 512; pdt_index++, pdt++)
		{
			// pde属性设置
			pdt->Bits.physial_address = MmGetPhysicalAddress((PVOID64)pt).QuadPart >> 12;
			pdt->Bits.execute_access = TRUE;
			pdt->Bits.read_access = TRUE;
			pdt->Bits.write_access = TRUE;

			for (__int64 pt_index = 0; pt_index < 512; pt_index++, pt++)
			{
				// pte属性设置
				pt->Bits.physial_address = (__int64)pa;
				pt->Bits.execute_access = TRUE;
				pt->Bits.read_access = TRUE;
				pt->Bits.write_access = TRUE;
				pt->Bits.memory_type = 6;	//writeback

				pa = (PVOID64)((__int64)pa + 1);
			}
		}
	}

	DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_ERROR_LEVEL, "[ok] ept初始化成功!\n");

	return FALSE;
}


/* 检查eptp属性并进行设置 */
BOOLEAN SetupExtendedPageTablePointerRights(PEptPointer eptp)
{
	CPUID cpuid = { 0 };		// 用于存储rdmsr的返回值
	asm_rdmsr(IA32_VMX_EPT_VPID_CAP, &cpuid);

	if (cpuid.eax & 0x100)		// uncacheable, bit 8
		DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_ERROR_LEVEL, "[+] CPU支持UC(uncacheable)!\n");
	else
		DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_ERROR_LEVEL, "[+] CPU不支持UC(uncacheable)!\n");


	if (cpuid.eax & 0x4000)		// writeback, bit 14, 支持则优先设置
	{
		DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_ERROR_LEVEL, "[+] CPU支持WB(writeback)!\n");
		eptp->Bits.memory_type = 6;
	}
	else
		DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_ERROR_LEVEL, "[+] CPU不支持WB(writeback)!\n");


	if (cpuid.eax & 0x40)		// page walk length, bit 6
	{
		DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_ERROR_LEVEL, "[+] CPU支持4级分页!\n");
		eptp->Bits.page_walk_length = 3;
	}
	else
	{
		DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_ERROR_LEVEL, "[+] CPU支持4级分页!\n[-] CPU无法开启ept!\n");
		return FALSE;
	}


	if (cpuid.eax & 0x200000)	// dirty&accessed, bit 21
	{
		DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_ERROR_LEVEL, "[+] CPU支持dirty、accessed!\n");
		eptp->Bits.enable_accessed_and_dirty_flags = TRUE;
	}
	else
		DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_ERROR_LEVEL, "[+] CPU不支持dirty、accessed!\n");


}


/* 开启内存虚拟化 */
void StartVirtualizeMemory()
{
	SetupEptPaingStructure();
	HookEptPage(0xfffff80578a01800);		// 0x0e page-fault
}


void InsertEptHookList(PEptHookItem pEptHookItem)
{
	PEptHookItem hook_item = &g_vmx_config.EPT.ept_hook_list_header;

	if (!hook_item->next)
	{
		hook_item->next = pEptHookItem;
	}
	else 
	{
		pEptHookItem->next = hook_item->next;
		hook_item->next = pEptHookItem;
	}
	
}

BOOLEAN HookEptPage(PVOID64 pTargetLinerAddress)
{
	/* guest线性地址转为ept.pte(线性地址)*/
	PEptPtEntry pte = (PEptPtEntry)GetEptPtEntryLinerAddress(pTargetLinerAddress);

	/* 设置hook-item属性 */
	PEptHookItem hook_item = kmalloc(sizeof(EptHookItem));
	hook_item->next = NULL;
	hook_item->target_liner_address = pTargetLinerAddress;
	hook_item->target_physical_address = MmGetPhysicalAddress(pTargetLinerAddress).QuadPart;
	hook_item->pte_liner_address = (__int64*)pte;
	hook_item->fake_page_liner_address = AllocateFakePage(pTargetLinerAddress);

	/* 将被hook的物理页线性地址挂入ept-hook链 */
	InsertEptHookList(hook_item);

	/* 设置物理页新的属性位 */
	pte->Bits.read_access = FALSE;
	pte->Bits.write_access = FALSE;
	pte->Bits.execute_access = TRUE;

	return TRUE;
}

__int64* GetEptPtEntryLinerAddress(__int64* pTargetLinerAddress)
{
	PVOID64 gpa = MmGetPhysicalAddress(pTargetLinerAddress).QuadPart;
	return (__int64)g_vmx_config.EPT.ept_address + (((__int64)gpa >> 12) << 3);
}

void HandleOfEptViolation()
{
	ULONG64 ExitQualification;				// 详细的退出信息
	PHYSICAL_ADDRESS TargetAddress_pa;		// 目标物理地址

	DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_ERROR_LEVEL, "[+] HandleOfEptViolation.\n");

	asm_vmread(&ExitQualification, EXIT_QUALIFICATION);
	asm_vmread(&TargetAddress_pa, GUEST_PHYSICAL_ADDRESS);

	// 检测当前线性地址是否在目标页面范围内
	PEptHookItem hook_item = { 0 };
	BOOLEAN bRet = CheckCurrectEptViolationAddressIsTargetRange((__int64*)TargetAddress_pa.QuadPart, &hook_item);

	if (bRet)
	{
		//DbgBreakPoint();
		PEptPtEntry target_item = (PEptPtEntry)hook_item->pte_liner_address;
		DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_ERROR_LEVEL, "[+] 检测到当前线性地址处于目标页面范围内! 内存修复...\n");
		if (ExitQualification & 3)			// 页面读写出错
		{
			target_item->Bits.read_access = TRUE;
			target_item->Bits.write_access = TRUE;
			target_item->Bits.execute_access = FALSE;
			target_item->Bits.physial_address = MmGetPhysicalAddress(hook_item->fake_page_liner_address).QuadPart >> 12;
		}
		else		// 页面无法执行
		{
			target_item->Bits.read_access = FALSE;
			target_item->Bits.write_access = FALSE;
			target_item->Bits.execute_access = TRUE;
			target_item->Bits.physial_address = (__int64)hook_item->target_physical_address >> 12;
		}
		
	}
	else
	{
		DbgPrintEx(DPFLTR_IHVDRIVER_ID, DPFLTR_ERROR_LEVEL, "[error] noknwon ept error!\n");
	}
	
	// 刷新 TLB  ==> 作用没有体现出来???
	//DbgBreakPoint();
	//asm_invept(2, &g_vmx_config.EPT.eptp);
	
}

BOOLEAN CheckCurrectEptViolationAddressIsTargetRange(__int64* target_address_pa, __int64** hook_item_ret)
{
	PEptHookItem hook_item = &g_vmx_config.EPT.ept_hook_list_header;

	//__int64* pte_address_pa = GetEptPtEntryLinerAddress(target_address_pa);
	while (hook_item)
	{
		hook_item = hook_item->next;
		if (((__int64)hook_item->target_physical_address >> 12) == ((__int64)target_address_pa >> 12))
		{
			*hook_item_ret = hook_item;
			return TRUE;
		}
		else
			hook_item = hook_item->next;
	}

	return FALSE;
}

__int64* AllocateFakePage(__int64* real_page)
{
	/* 无痕hook, 需要将原页面的数据复制至fake-page */
	__int64* fake_page = kmalloc(PAGE_SIZE);
	memcpy(fake_page, real_page, PAGE_SIZE);

	return fake_page;
}

BOOLEAN UninstallEptPageHook(PVOID pTargetLinerAddress)
{
	PEptHookItem hook_item = &g_vmx_config.EPT.ept_hook_list_header;

	// 卸载指定 ept page hook
	if (pTargetLinerAddress)
	{
		PEptHookItem front = hook_item;
		hook_item = hook_item->next;
		while (hook_item->next)
		{
			if (pTargetLinerAddress == hook_item->target_liner_address)
			{
				front->next = hook_item->next;						// 删除hook_item节点
				*hook_item->pte_liner_address |= 0x07;				// 修复pte的权限属性
				MmFreeContiguousMemory(hook_item->fake_page_liner_address);		// 释放fake-page
				MmFreeContiguousMemory(hook_item);								// 释放hook_item
				return TRUE;
			}
		}
		return FALSE;
	}

	// 卸载所有 ept page hook
	else
	{
		__int64* next = hook_item->next;
		while (next)
		{
			hook_item = next;
			next = hook_item->next;
			MmFreeContiguousMemory(hook_item->fake_page_liner_address);
			MmFreeContiguousMemory(hook_item);
		}
		return TRUE;
	}
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值