pg3 bypass源码阅读 —— 学习x64内核hook跳板技术

如之前描述的 pg3复杂了许多


先来看看都要hook哪些点


1、hook dpc和定时器分发器,防止seh路线触发pg

KiTimerListExpire,KiRetireDpcList


看一下hook点




hook的就是call的位置。


这里有两种方案:一种是直接jmp + 64bit addr,显然有同步问题,需要暂停所有cpu然后把irql提升到HIGH_LEVEL去操作。


另一种是 call 32bit 跳板 addr,如下图,操作8byte符合原子操作



e8 xxxxxxxx是32位转移,我们需要一个nt范围内的跳板,作者是这样处理的。把KiCustomAccessRoutine4跳转到KiCustomAccessRoutine0,那么KiCustomAccessRoutine4后面的代码就可以随便改了,不需要原子操作,这是一个技巧。



void VistaAll_DpcInterceptor(
		PKDPC InDpc,
		PVOID InDeferredContext,
		PVOID InSystemArgument1,
		PVOID InSystemArgument2)
{
	ULONGLONG		Routine = (ULONGLONG)InDpc->DeferredRoutine;

	__try
	{
		if((Routine >= 0xFFFFFA8000000000) && (Routine <= 0xFFFFFAA000000000))
		{
		}
		else
		if(KeContainsSymbol((void*)Routine))
		{
			if(!PgIsPatchGuardContext(InDeferredContext))
				InDpc->DeferredRoutine(InDpc, InDeferredContext, InSystemArgument1, InSystemArgument2);
		}
		else
			InDpc->DeferredRoutine(InDpc, InDeferredContext, InSystemArgument1, InSystemArgument2);
	}
	__except(EXCEPTION_EXECUTE_HANDLER)
	{
	}
}

fake dpc的处理非常简单,判断dpc context即可


2.hook ExpWorkerThread 工作线程也有可能触发pg,hook方法同上,fake函数如下

VOID VistaAll_ExpWorkerThreadInterceptor(PWORKER_THREAD_ROUTINE InRoutine, VOID* InContext, VOID* InRSP)
{
	ULONGLONG		Val = (ULONGLONG)InRoutine;

	if((Val >= 0xfffffa8000000000) && (Val <= 0xfffffaa000000000))
		return;

	__try
	{
		InRoutine(InContext);
	}
	__except(EXCEPTION_EXECUTE_HANDLER)
	{
	}
}

过滤了所有内核的work thread,工作线程是non-seh mode,无法过滤非传统地址,所以过滤了所有的nt工作线程。。总是系统跑起来之后也不会再排新的工作线程就是了。


3.这样还不够,hook KeBugcheckEx作为补充,KeBugcheckEx是被PG循环恢复的,但是分析代码KeBugcheckEx一开始就调用到RtlCaptureContext,所以转去hook RtlCaptureContext,还是用跳板函数,用到了栈回溯

RtlCaptureContext_Hook PROC

	; call high level handler without messing up the context structure...
	push		rcx
	push		rdx
	push		r8
	push		r9
	push		r10
	push		r11
	mov			rcx, qword ptr[rsp + 128]
	mov			rdx, qword ptr[rsp + 7 * 8]
	sub			rsp, 32
	call		KeBugCheck_Hook
	mov			qword ptr [rsp], rax
	add			rsp, 32
	pop			r11
	pop			r10
	pop			r9
	pop			r8
	pop			rdx
	pop			rcx
	pop			rax
	
	; recover destroyed bytes of RtlCaptureContext
	pushfq
	mov			word ptr [rcx+38h],cs
	mov			word ptr [rcx+3Ah],ds
	mov			word ptr [rcx+3Ch],es
	mov			word ptr [rcx+42h],ss
	
	; jump behind destroyed bytes... (RetVal of RtlCaptureContext_HookEx)
	jmp			qword ptr[rsp - 32 - 8 * 7 + 8]

RtlCaptureContext_Hook ENDP

fake函数将pg进入死循环

ULONGLONG KeBugCheck_Hook(ULONGLONG InBugCode, ULONGLONG InCaller)
{
	FAST_MUTEX WaitAlways;

	//判断调用者
	if((InCaller >= KeBugCheckEx_Sym) && (InCaller <= KeBugCheckEx_Sym + 100))
	{
		if(InBugCode == CRITICAL_STRUCTURE_CORRUPTION)
		{
			// KeBugCheckEx disables interrupts before calling RtlCaptureContext()
			EnableInterrupts();

			//进入死循环
			ExInitializeFastMutex(&WaitAlways);
			ExAcquireFastMutex(&WaitAlways);
			ExAcquireFastMutex(&WaitAlways);
		}
	}

	//返回跳转地址
	return RtlCaptureContext_Sym + 14;
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值