欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

x64 内核 InlineHook

程序员文章站 2022-06-17 14:44:39
...

需要使用LDE反汇编引擎

#include<ntddk.h>
#include"LDE.h"
#define kmalloc(_s) ExAllocatePoolWithTag(NonPagedPool, _s, 'SYSW')
#define kfree(_p) ExFreePool(_p)

KIRQL WPOFFx64()
{
	KIRQL irql = KeRaiseIrqlToDpcLevel();
	UINT64 cr0 = __readcr0();
	cr0 &= 0xfffffffffffeffff;
	__writecr0(cr0);
	_disable();
	return irql;

}

void WPONx64(KIRQL irql)
{
	UINT64 cr0 = __readcr0();
	cr0 |= 0x10000;
	_enable();
	__writecr0(cr0);
	KeLowerIrql(irql);
}

void *GetFunctionAddr(PCWSTR FunctionName)
{
	UNICODE_STRING UniCodeFunctionName;
	RtlInitUnicodeString(&UniCodeFunctionName, FunctionName);
	return MmGetSystemRoutineAddress(&UniCodeFunctionName);
}

ULONG GetPatchSize(PUCHAR Address)
{
	ULONG LenCount = 0, Len = 0;
	while (LenCount < 14)	//至少需要14字节
	{
		Len = LDE(Address, 64);
		Address = Address + Len;
		LenCount = LenCount + Len;
	}
	return LenCount;
}

//传入:待HOOK函数地址,代理函数地址,接收原始函数地址的指针,接收补丁长度的指针;返回:原来头N字节的数据
PVOID HookKernelApi(IN PVOID ApiAddress, IN PVOID Proxy_ApiAddress, OUT PVOID *Original_ApiAddress, OUT ULONG *PatchSize)
{

	KIRQL irql;
	UINT64 tmpv;
	PVOID head_n_byte, ori_func;
	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";

	//计算需要多少完整字节数
	*PatchSize = GetPatchSize((PUCHAR)ApiAddress);

	//读取原函数头部被覆盖的值
	head_n_byte = kmalloc(*PatchSize);
	irql = WPOFFx64();
	memcpy(head_n_byte, ApiAddress, *PatchSize);
	WPONx64(irql);

	//step 2: Create ori function
	ori_func = kmalloc(*PatchSize + 14);	//原始机器码+跳转机器码
	RtlFillMemory(ori_func, *PatchSize + 14, 0x90);

	tmpv = (ULONG64)ApiAddress + *PatchSize;	//跳转到没被打补丁的那个字节
	memcpy(jmp_code_orifunc + 6, &tmpv, 8);
	memcpy((PUCHAR)ori_func, head_n_byte, *PatchSize);
	memcpy((PUCHAR)ori_func + *PatchSize, jmp_code_orifunc, 14);
	*Original_ApiAddress = ori_func;

	//step 3: fill jmp code
	tmpv = (UINT64)Proxy_ApiAddress;
	memcpy(jmp_code + 6, &tmpv, 8);

	//step 4: Fill NOP and hook
	irql = WPOFFx64();
	RtlFillMemory(ApiAddress, *PatchSize, 0x90);
	memcpy(ApiAddress, jmp_code, 14);

	WPONx64(irql);
	return head_n_byte;
}

//传入:被HOOK函数地址,原始数据,补丁长度
VOID UnhookKernelApi(IN PVOID ApiAddress, IN PVOID OriCode, IN ULONG PatchSize)
{
	KIRQL irql;
	irql = WPOFFx64();
	memcpy(ApiAddress, OriCode, PatchSize);
	WPONx64(irql);

	//后续还要释放申请的内存
}


typedef NTSTATUS(__fastcall *PSLOOKUPPROCESSBYPROCESSID)(HANDLE ProcessId, PEPROCESS *Process);
ULONG64 my_eprocess = 0;	//待保护进程的eprocess
ULONG pslp_patch_size = 0;	//PsLookupProcessByProcessId被修改了N字节
PUCHAR pslp_head_n_byte = NULL;	//PsLookupProcessByProcessId的前N字节数组
PVOID ori_pslp = NULL;	//PsLookupProcessByProcessId的原函数


NTSTATUS Proxy_PsLookupProcessByProcessId(HANDLE ProcessId, PEPROCESS *Process)
{
	NTSTATUS st;
	st = ((PSLOOKUPPROCESSBYPROCESSID)ori_pslp)(ProcessId, Process);
	DbgPrint("进入代理函数\n");
	return st;
}

VOID HookPsLookupProcessByProcessId()
{
	pslp_head_n_byte = HookKernelApi(GetFunctionAddr(L"PsLookupProcessByProcessId"),
		(PVOID)Proxy_PsLookupProcessByProcessId,
		&ori_pslp,
		&pslp_patch_size);
}

VOID UnhookPsLookupProcessByProcessId()
{
	UnhookKernelApi(GetFunctionAddr(L"PsLookupProcessByProcessId"),
		pslp_head_n_byte,
		pslp_patch_size);
}

VOID DriverUnload(PDRIVER_OBJECT pDriver)
{
	UnhookPsLookupProcessByProcessId();
}

NTSTATUS DriverEntry(PDRIVER_OBJECT pDriver,PUNICODE_STRING pRegPath)
{
	LDE_init();
	pDriver->DriverUnload = DriverUnload;

	HookPsLookupProcessByProcessId();

	return 0;
}