C++ Inline Hook 代码

#include <ntifs.h>
#include <ntddk.h>
#include <Ntstrsafe.h>
#include "ldasm.h"

#ifdef _WIN64
#define			HOOKLEN							15
#define			ProxyJmpCodeLength			15			
#else
#define			HOOKLEN							5
#define			ProxyJmpCodeLength			7			//sizeof(0xEA,0,0,0,0 0x08,0x00) = 7
#endif


PVOID JmpOldFunCodeAddr = NULL;
DWORD JmpCodeLength = 0;

//去掉页面保护
void  WPOFF(void)
{

#ifdef _WIN64

	_disable();
	DWORD64 cr0 = __readcr0();
	cr0 &= 0xfffffffffffeffff;
	__writecr0(cr0);
	//	_enable();

#else
	__asm
	{
		cli
		mov eax, cr0
		and eax, not 10000h
		mov cr0, eax
	}
#endif
}

//设置页面保护
void  WPON(void)
{
#ifdef _WIN64
	_disable();
	DWORD64 cr0 = __readcr0();
	cr0 |= 0x10000;
	__writecr0(cr0);
#else
	__asm
	{
		mov eax, cr0
		or eax, 10000h
		mov cr0, eax
		sti
	}
#endif
}

//HOOK
NTSTATUS FuncModify(PVOID FuncAddr, PVOID FuncNewAddr, PVOID *JmpCodeAddr, DWORD *JmpCodeLength)
{
	//定义变量
	NTSTATUS status = STATUS_UNSUCCESSFUL;
	ULONG BackupLength = 0;
	UCHAR *cPtr, *pOpcode;
	ULONG Length;
	PVOID pJmpCodeBuf;


	//参数效验
	if (FuncAddr == NULL || FuncNewAddr == NULL || JmpCodeAddr==NULL || JmpCodeLength==NULL)return status;

	//搜索hook点
	for (cPtr = (UCHAR *)FuncAddr; cPtr < (UCHAR *)FuncAddr + PAGE_SIZE; cPtr += Length)
	{
		ldasm_data ld = { 0 };
		Length = ldasm(cPtr, &ld, 0);
		BackupLength += Length;
		if (BackupLength >= HOOKLEN) break;
	}

	if (BackupLength<HOOKLEN)
	{
		return status;
	}

	pJmpCodeBuf = ExAllocatePool(NonPagedPool, BackupLength + ProxyJmpCodeLength);
	if (pJmpCodeBuf == NULL)
	{
		return status;
	}
	RtlZeroMemory(pJmpCodeBuf, BackupLength + ProxyJmpCodeLength);

	///
	*JmpCodeAddr = pJmpCodeBuf;
	*JmpCodeLength = BackupLength;


	// 保存原始API的头部
	RtlMoveMemory(pJmpCodeBuf, FuncAddr, BackupLength);


	WPOFF();
	KIRQL irql = KeRaiseIrqlToDpcLevel();
	//JMP回原始函数的地址
#ifdef _WIN64

	UINT64 tmpv;
	UCHAR jmp_code[] = "\xFF\x25\x00\x00\x00\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF";
	UCHAR jmp_code_orifunc[] = "\xFF\x25\x00\x00\x00\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF";

	//跳转到没被打补丁的那个字节
	tmpv = (ULONG64)FuncAddr + BackupLength;	
	memcpy(jmp_code_orifunc + 6, &tmpv, 8);
	memcpy((PUCHAR)pJmpCodeBuf + BackupLength, jmp_code_orifunc, 14);

	tmpv = (UINT64)FuncNewAddr;
	memcpy(jmp_code + 6, &tmpv, 8);
	RtlZeroMemory(FuncAddr, BackupLength);
	memcpy(FuncAddr, jmp_code, 14);


#else
	char jmp_code[ProxyJmpCodeLength] = { 0xEA, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00 };
	*((PULONG_PTR)(jmp_code + 1)) = (ULONG_PTR)FuncAddr + BackupLength;
	RtlMoveMemory((VOID *)((ULONGLONG)pJmpCodeBuf + BackupLength), jmp_code, ProxyJmpCodeLength);

	//HOOK操作
	char nJmpCode[HOOKLEN] = { 0xE9, 0x00, 0x00, 0x00, 0x00 };
	*(DWORD*)(nJmpCode + 1) = (DWORD)FuncNewAddr - ((DWORD)FuncAddr + HOOKLEN);
	RtlZeroMemory(FuncAddr, BackupLength);
	RtlMoveMemory(FuncAddr, nJmpCode, BackupLength);
#endif
	KeLowerIrql(irql);
	WPON();

	return STATUS_SUCCESS;
}

//恢复hook
NTSTATUS FuncRestore(PVOID FuncAddr, PVOID pOriginalCode, DWORD Length)
{

	//参数效验
	if (MmIsAddressValid(FuncAddr) == FALSE)return STATUS_UNSUCCESSFUL;
	if (MmIsAddressValid(pOriginalCode) == FALSE)return STATUS_UNSUCCESSFUL;
	if (Length <= 0)return STATUS_UNSUCCESSFUL;


	WPOFF();
	KIRQL irql = KeRaiseIrqlToDpcLevel();

	RtlMoveMemory(FuncAddr, pOriginalCode, Length);

	KeLowerIrql(irql);
	WPON();
	return STATUS_SUCCESS;
}



typedef NTSTATUS(__fastcall *FnNtOpenProcess)(HANDLE ProcessId, PEPROCESS *Process);

NTSTATUS NewNtOpenProcess(PHANDLE    ProcessHandle, ACCESS_MASK   DesiredAccess, POBJECT_ATTRIBUTES ObjectAttributes, PCLIENT_ID   ClientId)
{
	if (ClientId->UniqueProcess==2216)
	{
		return STATUS_ACCESS_DENIED;
	}
	return  ((FnNtOpenProcess)JmpOldFunCodeAddr)(ProcessHandle, DesiredAccess, ObjectAttributes, ClientId);

}



VOID DriverUnload(IN PDRIVER_OBJECT DriverObject)
{

	return;
}



NTSTATUS DriverEntry(IN PDRIVER_OBJECT DriverObject, IN PUNICODE_STRING RegistryPath)
{
	NTSTATUS status;
	DriverObject->DriverUnload = DriverUnload;


	DbgBreakPoint();
	FuncModify(NtOpenProcess, NewNtOpenProcess, &JmpOldFunCodeAddr, &JmpCodeLength);
	FuncRestore(NtOpenProcess, JmpOldFunCodeAddr, JmpCodeLength);
	return STATUS_SUCCESS;
}




  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值