Process Hacker源码中的用户态hook的做法
processhacker-code-5632\1.x\trunk\NProcessHacker\hook.h
typedef struct _PH_HOOK { PVOID Function; PVOID Target; BOOLEAN Hooked; CHAR Bytes[5]; } PH_HOOK, *PPH_HOOK;
这个结构体用来保存每个Hook的信息,Function是hook点的地址, Target是Trampoline的地址,Bytes用来备份Function点处原来的5个字节。
processhacker-code-5632\1.x\trunk\NProcessHacker\hook.c
VOID PHAPI PhInitializeHook( PPH_HOOK Hook, PVOID Function, PVOID Target ) { memset(Hook, 0, sizeof(PH_HOOK)); Hook->Function = Function; Hook->Target = Target; }
初始化Hook结构体,指定hook点与Trampoline的地址。
NTSTATUS PHAPI PhHook( PPH_HOOK Hook ) { NTSTATUS status = STATUS_SUCCESS; ULONG oldProtection; PCHAR function; /* Change the page protection of the target page so we can write to it. */ if (!VirtualProtect(Hook->Function, 5, PAGE_EXECUTE_READWRITE, &oldProtection)) return STATUS_ACCESS_VIOLATION; __try { function = (PCHAR)Hook->Function; /* Copy the original five bytes for unhooking. */ memcpy(Hook->Bytes, function, 5); /* Hook the function by writing a jump instruction. */ Hook->Hooked = TRUE; /* jmp Target */ *function = 0xe9; *(PULONG_PTR)(function + 1) = (ULONG_PTR)Hook->Target - (ULONG_PTR)Hook->Function - 5; } __except (EXCEPTION_EXECUTE_HANDLER) { status = GetExceptionCode(); } /* Restore the old page protection. */ VirtualProtect(Hook->Function, 5, oldProtection, NULL); return status; }
用于完成对Hook点的5个字节的替换,替换成e9 XXXXXXXX[Trampoline与Hook点之间的偏移距离]。
NTSTATUS PHAPI PhUnhook( PPH_HOOK Hook ) { NTSTATUS status = STATUS_SUCCESS; ULONG oldProtection; /* Change the page protection of the target page so we can write to it. */ if (!VirtualProtect(Hook->Function, 5, PAGE_EXECUTE_READWRITE, &oldProtection)) return STATUS_ACCESS_VIOLATION; __try { /* Unpatch the function by restoring the original first 5 bytes. */ memcpy(Hook->Function, Hook->Bytes, 5); Hook->Hooked = FALSE; } __except (EXCEPTION_EXECUTE_HANDLER) { status = GetExceptionCode(); } /* Restore the old page protection. */ VirtualProtect(Hook->Function, 5, oldProtection, NULL); return status; }
Unhook的过程恰好相反,用备份的5个字节恢复Hook点。