学技术打豆豆
雪 币: 1191
活跃值: (182)
能力值:
( LV3,RANK:20 )
在线值:
先通过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); } }
完。