#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;
}
C++ Inline Hook 代码
最新推荐文章于 2022-11-10 17:27:31 发布