Win10 X64 HOOK KiUserExceptionDispatcher

Win10 X64 HOOK KiUserExceptionDispatcher

HOOK.ASM

extrn NewKiUserExceptionDispatcher : proc 
extrn OrgKiUserExceptionDispatcher : proc  
extrn OldKiUserExceptionDispatcher : proc 
.data
.code


;hook 
public MyKiUserExceptionDispatcher

MyKiUserExceptionDispatcher PROC  
    mov   rcx, rsp 
    add  rcx,4F0h
    mov   rdx,rsp  
    call  NewKiUserExceptionDispatcher ;先经过我们自己的异常处理

    ;mov rax,[OldKiUserExceptionDispatcher]  ;这样跳转回去会异常 原因未知
    ;jmp rax 

    ;
    mov   rax, [OrgKiUserExceptionDispatcher] ;直接用原函数+偏移 跳到RtlDispatchException 这样可以
    mov   rax,[rax]
    add   rax ,1ch
    jmp   rax; RtlDispatchException
    ret
MyKiUserExceptionDispatcher ENDP

END

HOOKFUC.H

#pragma once
#include <windows.h>

typedef VOID(WINAPI* PtrKiUserExceptionDispatcher)();
namespace HookEmu {
	//extern "C" C形式导出
	extern "C" PtrKiUserExceptionDispatcher OrgKiUserExceptionDispatcher;
	extern "C" PtrKiUserExceptionDispatcher OldKiUserExceptionDispatcher;
	extern HMODULE hNtDll ;
	
}
 

namespace HookFunction {
	 extern VOID HookKi();

}

namespace KiuserExc
{
	extern "C" void MyKiUserExceptionDispatcher();//汇编导出
	extern "C" void   NewKiUserExceptionDispatcher(PEXCEPTION_RECORD ExceptionRecord, PCONTEXT  Context);
}
namespace VEH_Tess
{
	extern LONG __stdcall VEHandler(
		EXCEPTION_POINTERS* ExceptionInfo
	);
	extern void InitVeh();
}


namespace HelpFuc {

	static VOID StackTrace64(PCONTEXT  Context);
}

HOOKFUC.CPP

#include "hookFun.h"
#include "MinHook.h"
#include <stdio.h>
namespace HookEmu {
	PtrKiUserExceptionDispatcher OrgKiUserExceptionDispatcher = 0;
	HMODULE hNtDll = NULL;
	PtrKiUserExceptionDispatcher OldKiUserExceptionDispatcher = nullptr;
}
namespace HookFunction {

	  VOID HookKi()
	{
		printf("ADDRESS:%llx", &KiuserExc::MyKiUserExceptionDispatcher);
		HookEmu::hNtDll = GetModuleHandleA("Ntdll.dll");
		HookEmu::OrgKiUserExceptionDispatcher = (PtrKiUserExceptionDispatcher)GetProcAddress(HookEmu::hNtDll, "KiUserExceptionDispatcher");


		if (MH_Initialize() == MH_OK)
		{
			if (MH_OK == MH_CreateHook(HookEmu::OrgKiUserExceptionDispatcher, (DWORD64*)&KiuserExc::MyKiUserExceptionDispatcher, reinterpret_cast<void**>(&HookEmu::OldKiUserExceptionDispatcher)))
			{
				if (MH_OK == MH_EnableHook(HookEmu::OrgKiUserExceptionDispatcher))
				{
					printf("钩子安装成功!\n");
				}
			}
		}
		return;
	}
}

namespace KiuserExc {

	void   NewKiUserExceptionDispatcher(PEXCEPTION_RECORD ExceptionRecord, PCONTEXT  Context)
	{
		printf(":HK\n");
		if (Context)
		{
			//HelpFuc::StackTrace64(Context);
			if (Context->ContextFlags & CONTEXT_DEBUG_REGISTERS)
			{
				printf(":HK\n");

				// Now each Thread handle should have its own CONTEXT.
				/*BeckupHardwareBP[CurrOffset].Dr0 = Context->Dr0;
				BeckupHardwareBP[CurrOffset].Dr1 = Context->Dr1;
				BeckupHardwareBP[CurrOffset].Dr2 = Context->Dr2;
				BeckupHardwareBP[CurrOffset].Dr3 = Context->Dr3;
				BeckupHardwareBP[CurrOffset].Dr6 = Context->Dr6;
				BeckupHardwareBP[CurrOffset].Dr7 = Context->Dr7;
	*/

				Context->Dr0 = 0;
				Context->Dr1 = 0;
				Context->Dr2 = 0;
				Context->Dr3 = 0;
				Context->Dr6 = 0;
				Context->Dr7 = 0;
				//Context->Rip += 1;
			}
		}
	}
}
namespace  VEH_Tess
{
	LONG __stdcall VEHandler(
		EXCEPTION_POINTERS* ExceptionInfo
	)
	{
		ExceptionInfo->ContextRecord->Rip += 1;
		printf("VEH 异常将被忽略 发生地址:%p RAX:0x%016I64x RCX:0x%016I64x RDX:0x%016I64x R8:0x%016I64x  R9:0x%016I64x\n", ExceptionInfo->ContextRecord->Rip, ExceptionInfo->ContextRecord->Rax, ExceptionInfo->ContextRecord->Rcx, ExceptionInfo->ContextRecord->Rdx, ExceptionInfo->ContextRecord->R8, ExceptionInfo->ContextRecord->R9);

		return EXCEPTION_CONTINUE_EXECUTION;//忽略异常=什么都没发生 try块当然也无法捕获到
	}


	void InitVeh()
	{
		AddVectoredExceptionHandler(1, VEHandler);//正常的监视全局异常
	}
}


namespace HelpFuc
{
	static VOID StackTrace64(PCONTEXT  Context)
	{

		KNONVOLATILE_CONTEXT_POINTERS NvContext;
		UNWIND_HISTORY_TABLE          UnwindHistoryTable;
		PRUNTIME_FUNCTION             RuntimeFunction;
		PVOID                         HandlerData;
		ULONG64                       EstablisherFrame;
		ULONG64                       ImageBase;

		RtlZeroMemory(
			&UnwindHistoryTable,
			sizeof(UNWIND_HISTORY_TABLE));

		RuntimeFunction = RtlLookupFunctionEntry(
			Context->Rip,
			&ImageBase,
			&UnwindHistoryTable
		);

		RtlZeroMemory(
			&NvContext,
			sizeof(KNONVOLATILE_CONTEXT_POINTERS));

		if (!RuntimeFunction)
		{
			printf("Rip:%llx\n", Context->Rip);
			Context->Rip = (ULONG64)(*(PULONG64)Context->Rsp);
			printf("new Rip:%llx\n", Context->Rip);
			Context->Rsp += 8;
			printf("RSP+=8\n");
		}
		else
		{
			RtlVirtualUnwind(
				UNW_FLAG_EHANDLER,
				ImageBase,
				Context->Rip,
				RuntimeFunction,
				Context,
				&HandlerData,
				&EstablisherFrame,
				&NvContext);
		}

		printf("ret Rip:%llx\n", Context->Rip);
		return;
	}
}

MAIN.CPP


#include <iostream>
#include "hookFun.h"
#include "MinHook.h"
 



void func(int cc) {

    __debugbreak();
	printf("func ok\n");
}

int main()
{ 
    VEH_Tess::InitVeh();
    HookFunction::HookKi();
    while(1){
        func(11);
        getchar();
    }
	printf("********************\n");
    getchar();

     
}
 
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
x64 Inline Hook(内联钩子)是一种在x64架构下实现的钩子技术,用于在程序运行时对函数进行修改或者监控。钩子技术可以用于实现一些高级功能,如函数拦截、行为修改和调试等。 Inline Hook的主要原理是通过修改函数的机器码,将目标函数的执行流程改变到一个特定的钩子函数,从而实现我们所需的功能。这个钩子函数可以进行一系列的操作,如记录参数、修改参数、替换返回值等。 x64 Inline Hook实现相对复杂,因为x64架构下的指令集更加复杂,并且x64架构引入了新的寄存器和指令,如RAX、R10、R11,还有新的调用惯例等。因此,在实现x64 Inline Hook前,我们需要对x64汇编指令和调用惯例有深入的了解。 具体实现Inline Hook主要包括以下几个步骤: 1. 定位到目标函数的地址。可以通过符号表、导入表或者动态调试等方式获取目标函数的地址。 2. 备份目标函数的原始字节码。为了在后续操作中恢复目标函数的完整执行流程,我们需要保留原始字节码。 3. 修改目标函数的字节码。通过修改目标函数的机器码,将执行流程转移到我们的钩子函数。 4. 编写钩子函数。钩子函数的参数和返回值需要与目标函数保持一致,并实现所需的功能。 5. 恢复目标函数的原始字节码。在钩子函数执行完毕后,需要将目标函数的字节码恢复到原始状态,以确保程序正常运行。 6. 跳回目标函数。在钩子函数执行完成后,我们需要将执行流程跳转回原始的目标函数。 需要注意的是,Inline Hook的实现需要考虑到多线程的情况,并且要保证对内存的修改是线程安全的,以及在恢复原始字节码时要避免潜在的问题。 总的来说,x64 Inline Hook是一种强大的技术,可以用于实现程序的函数修改和监控等高级功能。但它的实现相对复杂,需要对x64架构和汇编指令有深入的理解。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值