win10 1909 逆向(CR3无法被MmMapioSpace映射原理和绕过代码)
2020-07-03 17:30:05 Author: bbs.pediy.com(查看原文) 阅读量:576 收藏

学技术打豆豆

雪    币: 1191

活跃值: 活跃值 (182)

能力值:

( LV3,RANK:20 )

在线值:

[原创]win10 1909 逆向(CR3无法被MmMapioSpace映射原理和绕过代码)

1天前 840

[原创]win10 1909 逆向(CR3无法被MmMapioSpace映射原理和绕过代码)

 先通过windbg 看几个图来认识一下CR3相同的地方:

1。先选择两个不同进程的CR3。

2。然后查看页帧数据库的CR3物理页的信息,得知不同进程的PteAddress是一样的【每个人数值可能不同,但这类数值比较特殊,后面会用来做比较】

3。一个进程的创建是通过MmCreateProcessAddressSpace这个函数,通过逆向后得知CR3的PteAddress的值是由MiInitializePfnForOtherProcess来给予。

4。好了,知道了他的由来,再来看看他是怎么屏蔽的,通过逆向MmMapioSpace得知,关链函数在MiFillSystemPtes。

上面我们得知PteAddress是一个比较特殊的地址:如图

PteAddress:0xffff89c4e2713898 转成虚拟地址 ffff89c4e2713000,发现没,他在Pte范围之内,这就是他的判定的原理,在这个范围之内,则判定失败。

----------------------------------------------------------------------------------------------------------------------------------------------------------------------------

好了,现在开始我们的绕过代码之行:

先上效果图(我们以WinObj.exe为例),因为懒,就没有去对齐,看着就行:

//代码写的简单

#include <ntddk.h>
#define PTE_BASE 0
#define MMPFNDATABASE 1
BOOLEAN ByPassCr3(IN PHYSICAL_ADDRESS PhysicalAddress);
PVOID FindBase(IN CHAR base);
PUINT64 OldPteAddress=0;
PVOID mm;

VOID Unload(PDRIVER_OBJECT pDriverObject)
{
	if (mm)
	{
		MmUnmapIoSpace(mm, 0x1000);
	}
	KdPrint(("end\n"));

}

NTSTATUS DriverEntry(PDRIVER_OBJECT pDriverObject, PUNICODE_STRING pRegPath)
{

	NTSTATUS status = STATUS_SUCCESS;
	pDriverObject->DriverUnload = Unload;
	KdPrint(("start\n"));
	PHYSICAL_ADDRESS Py;
	Py.QuadPart = 0x2faed002;
	if (!ByPassCr3(Py))
	{
		KdPrint(("ByPassCr3 Error\n"));
	}
	mm=MmMapIoSpace(Py, 0x1000, FALSE);
	KdPrint(("mm=%llx\n", mm));

	return status;
}
BOOLEAN ByPassCr3(
	IN PHYSICAL_ADDRESS PhysicalAddress
)
{  
	//第一步先申请0x1000非分页内存,得到PTE用来替换
	PVOID Mem=ExAllocatePoolWithTag(NonPagedPool, 0x1000, 'Mcr3');
	if (!Mem)
	{
		KdPrint(("Error\n"));
		return 0;
	}
	
	//第二步找到MMPTE基址
	PVOID PteBase=FindBase(PTE_BASE);
	PVOID PfnBase = FindBase(MMPFNDATABASE);
	PfnBase = (UINT64)PfnBase & 0xFFFFFFFFFFFFFFF0;
	if (!PteBase && !PfnBase)
	{
		KdPrint(("FindBase is error\n"));
		return 0;
	}
	//第三步找到CR3的MMPFN.PteAddress来替换
	UINT64 Index = PhysicalAddress.QuadPart >> 0xc;
	//保存旧的OldPteAddress,可以在映射后恢复,也可以不恢复,目前未发现不恢复会出现问题
	OldPteAddress = *(PUINT64)(Index * 0x30 + (UINT64)PfnBase + 8);
	//第4步得到开始申请的非分页内存的PTE,进行替换
	UINT64 MemPte = (((UINT64)Mem & 0xFFFFFFFFFFFF) >> 0xc) * 8 + (UINT64)PteBase;
	*(PUINT64)(Index * 0x30 + (UINT64)PfnBase + 8) = MemPte;
	return 1;
}
PVOID FindBase(char base)
{
	PUCHAR BaseAddr = MmGetVirtualForPhysical;
	
	if (base)
	{
		return *(PUINT64)(BaseAddr + 0x10);
	}
	else
	{
		return *(PUINT64)(BaseAddr + 0x22);
	}

}

完。


文章来源: https://bbs.pediy.com/thread-260443.htm
如有侵权请联系:admin#unsafe.sh