首页
社区
课程
招聘
[原创]win10 1909逆向(绕过PG,实现内核HOOK)
发表于: 2021-4-1 11:55 27704

[原创]win10 1909逆向(绕过PG,实现内核HOOK)

2021-4-1 11:55
27704
收藏
免费 14
支持
分享
最新回复 (34)
雪    币: 6078
活跃值: (5485)
能力值: ( LV5,RANK:65 )
在线值:
发帖
回帖
粉丝
26
不懂,MARK一下!
2021-4-8 17:49
0
雪    币: 219
活跃值: (778)
能力值: (RANK:290 )
在线值:
发帖
回帖
粉丝
27
#ifndef PTE_SHIFT
#define PTE_SHIFT 3
#endif
#ifndef PTI_SHIFT
#define PTI_SHIFT 12
#endif
#ifndef PDI_SHIFT
#define PDI_SHIFT 21
#endif
#ifndef PPI_SHIFT
#define PPI_SHIFT 30
#endif
#ifndef PXI_SHIFT
#define PXI_SHIFT 39
#endif
#define VIRTUAL_ADDRESS_BITS 48
#define VIRTUAL_ADDRESS_MASK ((((ULONG_PTR)1) << VIRTUAL_ADDRESS_BITS) - 1)

#define PXE_PER_PAGE 512
#define PXI_MASK (PXE_PER_PAGE - 1)
#define MiGetPxeOffset(va) \
	((ULONG)(((ULONG_PTR)(va) >> PXI_SHIFT) & PXI_MASK))
#define MiGetPxeAddress(va)   \
	((PMMPTE)PXE_BASE + MiGetPxeOffset(va))
#define MiGetPpeAddress(va)   \
	((PMMPTE)(((((ULONG_PTR)(va) & VIRTUAL_ADDRESS_MASK) >> PPI_SHIFT) << PTE_SHIFT) + PPE_BASE))
#define MiGetPdeAddress(va) \
	((PMMPTE)(((((ULONG_PTR)(va) & VIRTUAL_ADDRESS_MASK) >> PDI_SHIFT) << PTE_SHIFT) + PDE_BASE))
#define MiGetPteAddress(va) \
	((PMMPTE)(((((ULONG_PTR)(va) & VIRTUAL_ADDRESS_MASK) >> PTI_SHIFT) << PTE_SHIFT) + PTE_BASE))


namespace PETMAP
{
	typedef struct _PXXPHYSICAL_
	{
		ULONG64 Pte_PhyAddress;
		ULONG64 Pde_PhyAddress;
		ULONG64 Ppe_PhyAddress;
		ULONG64 Pxe_PhyAddress;
		PULONG64 Pte_Address;
		PULONG64 Pde_Address;
		PULONG64 Ppe_Address;
		PULONG64 Pxe_Address;
	}*PPXXPHYSICAL,PXXPHYSICAL;
	typedef struct _PXXINDX_
	{
		ULONG64 Pte_Index;
		ULONG64 Pde_Index;
		ULONG64 Ppe_Index;
		ULONG64 Pxe_Index;
	}*PPXXINDXL,PXXINDX;

	static PXXINDX		pxxindex_info	=	{0};
	static PXXPHYSICAL pxxphysical_base_info	=	{0};
	static PVOID Pte_Base = NULL;
	static PVOID Pde_Base = NULL;
	static PVOID Ppe_Base = NULL;
	static PVOID Pxe_Base = NULL;
	LONGLONG QuadPart;

	
	PVOID MiGetAddress(ULONG64 VirtualAddress){
		return (PVOID)(((uintptr_t)VirtualAddress & 0xfff) + reinterpret_cast<ULONG64>(Pte_Base));
	}

	PVOID MiGetPXXAddress(ULONG64 VirtualAddress){
		return (PVOID)(((VirtualAddress >> 9) & 0x7FFFFFFFF8) + reinterpret_cast<ULONG64>(Pte_Base));
	}
	PVOID MmGetPteAddress(ULONG64 VirtualAddress){
		return ((PVOID)(((((ULONG_PTR)(VirtualAddress) & VIRTUAL_ADDRESS_MASK) >> PTI_SHIFT) << PTE_SHIFT) + reinterpret_cast<ULONG64>(Pte_Base)));
	}
	PVOID MmGetPdeAddress(ULONG64 VirtualAddress){
		return ((PVOID)(((((ULONG_PTR)(VirtualAddress) & VIRTUAL_ADDRESS_MASK) >> PDI_SHIFT) << PTE_SHIFT) + reinterpret_cast<ULONG64>(Pde_Base)));
	}
	PVOID MmGetPpeAddress(ULONG64 VirtualAddress){
		return ((PVOID)(((((ULONG_PTR)(VirtualAddress) & VIRTUAL_ADDRESS_MASK) >> PPI_SHIFT) << PTE_SHIFT) + reinterpret_cast<ULONG64>(Ppe_Base)));
	}
	PVOID MmGetPxeAddress(ULONG64 VirtualAddress){
		return ((PMMPTE)Pxe_Base + MiGetPxeOffset(VirtualAddress));
	}

	PVOID MiGetXXXAddress(ULONG64 VirtualAddress, PVOID PteBase)
	{

		return (PVOID)(((VirtualAddress >> 9) & 0x7FFFFFFFF8) + (ULONG64)PteBase);
	}
	NTSTATUS MmGetVirtualPxxPhyAddressEx(ULONG64 VirtualAddress,PPXXPHYSICAL VirtualInfor)
	{
		__faststorefence();
		PULONG64 Pte_PhyAddress	=	reinterpret_cast<PULONG64>(MmGetPteAddress(VirtualAddress));
		PULONG64 Pde_PhyAddress	=	reinterpret_cast<PULONG64>(MmGetPdeAddress(VirtualAddress));
		PULONG64 Ppe_PhyAddress	=	reinterpret_cast<PULONG64>(MmGetPpeAddress(VirtualAddress));
		PULONG64 Pxe_PhyAddress	=	reinterpret_cast<PULONG64>(MmGetPxeAddress(VirtualAddress));
		if (MmIsAddressValid(Pte_PhyAddress))
		{
			VirtualInfor->Pte_Address	=	Pte_PhyAddress;
			VirtualInfor->Pte_PhyAddress	=	*reinterpret_cast<PULONG64>(Pte_PhyAddress);
		}
		if (MmIsAddressValid(Pde_PhyAddress))
		{
			VirtualInfor->Pde_Address	=	Pde_PhyAddress;
			VirtualInfor->Pde_PhyAddress	=	*reinterpret_cast<PULONG64>(Pde_PhyAddress);
		}
		if (MmIsAddressValid(Ppe_PhyAddress))
		{
			VirtualInfor->Ppe_Address	=	Ppe_PhyAddress;
			VirtualInfor->Ppe_PhyAddress	=	*reinterpret_cast<PULONG64>(Ppe_PhyAddress);
		}
		if (MmIsAddressValid(Pxe_PhyAddress))
		{
			VirtualInfor->Pxe_Address	=	Pxe_PhyAddress;
			VirtualInfor->Pxe_PhyAddress	=	*reinterpret_cast<PULONG64>(Pxe_PhyAddress);
		}
		return STATUS_SUCCESS;
	}

	NTSTATUS MmGetVirtualPxxPhyAddress(ULONG64 VirtualAddress){
		if (MmIsAddressValid(Pte_Base)&&MmIsAddressValid(Ppe_Base)&&MmIsAddressValid(Pxe_Base)&&MmIsAddressValid(Pde_Base)){

			PULONG64 Pte_PhyAddress	=	reinterpret_cast<PULONG64>(MmGetPteAddress(VirtualAddress));
			PULONG64 Pde_PhyAddress	=	reinterpret_cast<PULONG64>(MmGetPdeAddress(VirtualAddress));
			PULONG64 Ppe_PhyAddress	=	reinterpret_cast<PULONG64>(MmGetPpeAddress(VirtualAddress));
			PULONG64 Pxe_PhyAddress	=	reinterpret_cast<PULONG64>(MmGetPxeAddress(VirtualAddress));
			if (MmIsAddressValid(Pte_PhyAddress)){
				pxxphysical_base_info.Pte_Address		=	Pte_PhyAddress;
				pxxphysical_base_info.Pte_PhyAddress	=	*reinterpret_cast<PULONG64>(Pte_PhyAddress);
			}
			if (MmIsAddressValid(Pde_PhyAddress)){	

				pxxphysical_base_info.Pde_Address		=	Pde_PhyAddress;
				pxxphysical_base_info.Pde_PhyAddress	=	*reinterpret_cast<PULONG64>(Pde_PhyAddress);
			}
			if (MmIsAddressValid(Ppe_PhyAddress)){
				pxxphysical_base_info.Ppe_Address		=	Ppe_PhyAddress;
				pxxphysical_base_info.Ppe_PhyAddress	=	*reinterpret_cast<PULONG64>(Ppe_PhyAddress);
			}
			if (MmIsAddressValid(Pxe_PhyAddress)){	

				pxxphysical_base_info.Pxe_Address		=	Pxe_PhyAddress;
				pxxphysical_base_info.Pxe_PhyAddress	=	*reinterpret_cast<PULONG64>(Pxe_PhyAddress);
			}
			return STATUS_SUCCESS;
		}
		return STATUS_UNSUCCESSFUL;
	}
	VOID MmGetVirtualPxxIndex(ULONG64 VirtualAddress){
		pxxindex_info.Pxe_Index = (VirtualAddress >> 0x27) & 0x1FF;
		pxxindex_info.Ppe_Index = (VirtualAddress >> 0x1E) & 0x1FF;
		pxxindex_info.Pde_Index = (VirtualAddress >> 0x15) & 0x1FF;
		pxxindex_info.Pte_Index = (VirtualAddress >> 0xC) & 0x1FF;	
		
	}
	LONG MmSetPhyAddressPointer(PVOID volatile *Target,_In_opt_ LONG64 Value){

		PVOID OldValue =  InterlockedExchangePointer (Target,(PVOID)Value);
		return reinterpret_cast<LONG>(OldValue);
	}
	ULONG64 MmSetPhyAddress64(PVOID volatile Target,_In_opt_ ULONG64 Value){

		PULONG64 m_Target = reinterpret_cast<PULONG64>(Target);
		ULONG64 value;
		if (MmIsAddressValid(Target)){
			value = *m_Target;
			*m_Target = Value;
		}
		return value;
	}

	NTSTATUS MmCreateNewTable(PVOID Address,int Index,ULONG64 ShadowPhyAddress,ULONG64 PhyAddress)
	{
		ULONG64 flags = PhyAddress & 0xFF00000000000FFF;
		ULONG64 new_pteflags =	ShadowPhyAddress&~0xFF00000000000FFF|flags; //保持原本属性
		NTSTATUS Status	=	STATUS_SUCCESS;
		if (MmIsAddressValid(Address)){
			*(PULONG64)((ULONG64)Address + Index * 8) = new_pteflags;
		}
		else
			Status	=	STATUS_UNSUCCESSFUL;
		return Status;
	}

}
KIRQL wpoff()
{
	KIRQL irql = KeRaiseIrqlToDpcLevel();
	ULONG_PTR cr0 = __readcr0();

	cr0 &= 0xfffffffffffeffff;
	_disable();
	__writecr0(cr0);

	return irql;
}

VOID wpon(KIRQL irql)
{

	ULONG_PTR cr0 = __readcr0();
	cr0 |= 0x10000;
	__writecr0(cr0);
	_enable();

	KeLowerIrql(irql);

}

VOID Hook(UINT64 Address, UINT64 ProxAddress)
{
	
	UCHAR code[]= "\xFF\x25\x00\x00\x00\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF";
	KIRQL irql = wpoff();
	KIRQL dpc_irql = KeRaiseIrqlToDpcLevel();
	memcpy(code + 6, &ProxAddress, 8);
	memcpy((PVOID)Address, &code, 14);
	KeLowerIrql(dpc_irql);
	wpon(irql);
	
}

NTSTATUS RtlMapCopyMemroy(PVOID BaseAddress,PVOID TartAddress,SIZE_T Size)
{

	PMDL pMDL = IoAllocateMdl(BaseAddress,Size,FALSE,FALSE,NULL);
	NTSTATUS Status	=	STATUS_UNSUCCESSFUL;
	if (!pMDL)	return Status;

	MmBuildMdlForNonPagedPool(pMDL);
	__try{
		MmProbeAndLockPages(pMDL,KernelMode,IoWriteAccess);
	}
	__except(EXCEPTION_EXECUTE_HANDLER){
		DBG("MmProbeAndLockPages erro\n");
	}

	__try{
		PVOID pMapedAddr = MmMapLockedPagesSpecifyCache(pMDL,KernelMode,MmCached,NULL,FALSE,NormalPagePriority);
		memcpy(BaseAddress,pMapedAddr,Size);		Status = STATUS_SUCCESS;
	}
	__except(EXCEPTION_EXECUTE_HANDLER){
		DBG(("erro\n"));
	}
	return Status;
}

NTSTATUS RtlMapCopyMemroy(PVOID BaseAddress,PVOID TartAddress,SIZE_T Size)
{

	PMDL pMDL = IoAllocateMdl(BaseAddress,Size,FALSE,FALSE,NULL);
	NTSTATUS Status	=	STATUS_UNSUCCESSFUL;
	if (!pMDL)	return Status;

	MmBuildMdlForNonPagedPool(pMDL);
	__try{
		MmProbeAndLockPages(pMDL,KernelMode,IoWriteAccess);
	}
	__except(EXCEPTION_EXECUTE_HANDLER){
		DBG("MmProbeAndLockPages erro\n");
	}

	__try{
		PVOID pMapedAddr = MmMapLockedPagesSpecifyCache(pMDL,KernelMode,MmCached,NULL,FALSE,NormalPagePriority);
		memcpy(BaseAddress,pMapedAddr,Size);		Status = STATUS_SUCCESS;
	}
	__except(EXCEPTION_EXECUTE_HANDLER){
		DBG(("erro\n"));
	}
	return Status;
}
NTSTATUS PTE_Hook(ULONG64 VirtualAddress)
{
	NTSTATUS status;
	PETMAP::Pte_Base	=	(PVOID)PTE_BASE;
	PETMAP::Pxe_Base	=	(PVOID)PXE_BASE;
	PETMAP::Ppe_Base	=	(PVOID)PPE_BASE;
	PETMAP::Pde_Base	=	(PVOID)PDE_BASE;
	PETMAP::MmGetVirtualPxxIndex(VirtualAddress);
	DBG("VirtualAddress Pte_Index 0x%x\n",PETMAP::pxxindex_info.Pte_Index);
	DBG("VirtualAddress Pde_Index 0x%x\n",PETMAP::pxxindex_info.Pde_Index);
	DBG("VirtualAddress Ppe_Index 0x%x\n",PETMAP::pxxindex_info.Ppe_Index);
	DBG("VirtualAddress Pxe_Index 0x%x\n",PETMAP::pxxindex_info.Pxe_Index);
	PETMAP::MmGetVirtualPxxPhyAddress(VirtualAddress);
	DBG("VirtualAddress Pte_PhyAddress 0x%p\n",PETMAP::pxxphysical_base_info.Pte_PhyAddress);
	DBG("VirtualAddress Pde_PhyAddress 0x%p\n",PETMAP::pxxphysical_base_info.Pde_PhyAddress);
	DBG("VirtualAddress Ppe_PhyAddress 0x%p\n",PETMAP::pxxphysical_base_info.Ppe_PhyAddress);
	DBG("VirtualAddress Pxe_PhyAddress 0x%p\n",PETMAP::pxxphysical_base_info.Pxe_PhyAddress);
	DBG("VirtualAddress Pte_Address 0x%p\n",PETMAP::pxxphysical_base_info.Pte_Address);
	DBG("VirtualAddress Pde_Address 0x%p\n",PETMAP::pxxphysical_base_info.Pde_Address);
	DBG("VirtualAddress Ppe_Address 0x%p\n",PETMAP::pxxphysical_base_info.Ppe_Address);
	DBG("VirtualAddress Pxe_Address 0x%p\n",PETMAP::pxxphysical_base_info.Pxe_Address);
	DBG("VirtualAddress 0x%p\n",VirtualAddress);

	FuncOffset = VirtualAddress & 0xFFF;
	DbgPrint("VirtualAddress Pxe_Address 0x%p\n",PETMAP::pxxphysical_base_info.Pxe_Address + FuncOffset);
	DbgPrint("VirtualAddress FuncOffset 0x%p\n",FuncOffset);
	LARGE_INTEGER High,Low;
  




   DWORD64 ImageBase	=	0;
   UNWIND_HISTORY_TABLE HistoryTable;
   ULONG SizeOfImage ;
   RtlLookupFunctionEntry(VirtualAddress,&ImageBase,&HistoryTable);
   DBG("VirtualAddress ImageBase 0x%p\n",ImageBase);
	if (MmIsAddressValid((PVOID)ImageBase))
		SizeOfImage =  RtlImageNtHeader((PVOID)ImageBase)->OptionalHeader.SizeOfImage;
	DBG("SizeOfImage 0x%p\n",SizeOfImage);
	High.QuadPart = ~0;
    PUCHAR m_new_pte_pageble = (PUCHAR)MmAllocateContiguousMemorySpecifyCache(SizeOfImage, Low, High, RtlConvertUlongToLargeInteger(0), MmCached);
   if (MmIsAddressValid(m_new_pte_pageble)){   
	  status =  RtlMapCopyMemroy(m_new_pte_pageble,(PVOID)ImageBase,SizeOfImage);
	  if (NT_SUCCESS(status))
	  {
		  PHYSICAL_ADDRESS new_funtion_pte_phy;
		  DWORD64 m_funtion_offset =   (PUCHAR)VirtualAddress - (PUCHAR)ImageBase;
		  PUCHAR m_funtion = m_new_pte_pageble + m_funtion_offset;
		  new_funtion_pte_phy	=	MmGetPhysicalAddress(m_funtion);
		  ULONG64 flags = PETMAP::pxxphysical_base_info.Pte_PhyAddress & 0xFF00000000000FFF;
		  ULONG64 new_pteflags = new_funtion_pte_phy.QuadPart&~0xFF00000000000FFF|flags;
		  PETMAP::MmSetPhyAddress64(PETMAP::pxxphysical_base_info.Pte_Address,new_pteflags);
		  Hook((UINT64)m_funtion,(UINT64)NewNtVmd);
	  }
   }
	__invlpg(&DirectoryTableBase);
	return STATUS_SUCCESS;
}
来Pte 也是ok 的 HOOK 几个页面

最后于 2021-4-8 18:55 被viphack编辑 ,原因:
2021-4-8 18:32
0
雪    币: 2458
活跃值: (4571)
能力值: ( LV3,RANK:30 )
在线值:
发帖
回帖
粉丝
28
看了一下不知道理解的是否正确:
0.PG只会在SYSTEM进程的虚拟内存空间中校验内核代码
1.在一个进程运行前,通过改变页表,将原本所有进程共享的,有内核代码的,物理页单独为新进程准备一份。
2.我们HOOK自己准备的物理页,这样在SYSTEM中的PG,扫描不到我们HOOK的物理页。
几个问题:
0. 单独替换一个PTE不可以么?
1.为SYSTEM复制一份物理页,这样PG扫的永远是复制的,我们随便HOOK其他的,是否可行(被注释部分的代码是做这个的么)?
2021-9-22 19:47
0
雪    币: 248
活跃值: (3789)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
29
小白养的菜鸡 看了一下不知道理解的是否正确: 0.PG只会在SYSTEM进程的虚拟内存空间中校验内核代码 1.在一个进程运行前,通过改变页表,将原本所有进程共享的,有内核代码的,物理页单独为新进程准备一份。 ...
应该是这样
2021-9-22 20:06
0
雪    币: 2458
活跃值: (4571)
能力值: ( LV3,RANK:30 )
在线值:
发帖
回帖
粉丝
30
yy虫子yy 应该是这样
哈哈哈哈刚才还在看你的triple fault
2021-9-22 20:40
0
雪    币: 248
活跃值: (3789)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
31
小白养的菜鸡 哈哈哈哈刚才还在看你的triple fault
那个是CPU指令缺陷引起的,看我最后面的回复
https://bbs.pediy.com/thread-258766-2.htm
2021-9-22 21:35
0
雪    币:
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
32
只改NtOpenProcess的PTE好像也可以达到相同的目的吧
2021-10-2 18:41
0
雪    币:
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
33
小白养的菜鸡 看了一下不知道理解的是否正确: 0.PG只会在SYSTEM进程的虚拟内存空间中校验内核代码 1.在一个进程运行前,通过改变页表,将原本所有进程共享的,有内核代码的,物理页单独为新进程准备一份。 ...
被注销的代码应该是失败的代码,他本来应该是想给system一个假的物理页,让PG检测不到,但是运行中的进程无法修改页表,所以他想挂起进程,修改之后再恢复,但是我猜system进程挂起来之后电脑就死了,所以折中了一下
2021-10-2 20:54
0
雪    币: 36
活跃值: (588)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
34
只是推迟了触发PG,并没有完全避免PG的触发
2021-11-28 22:14
0
雪    币: 180
活跃值: (298)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
35
感谢亲亲,KeDelayExecutionThread这个函数帮助了我
2023-5-7 23:36
0
游客
登录 | 注册 方可回帖
返回
//