分享一個多核下的InlineHook與UnHook。XP SP3測試通過。如有朋友有問題,歡迎提出共同解決。
.h檔案
#ifndef _INLINEHOOK_H_#define _INLINEHOOK_H_#include <ntddk.h>#pragma pack(1)typedef struct _SERVICE_DESCRIPTOR_TABLE{unsigned int *ServiceTableBase;unsigned int *ServiceCounterTableBase; //僅適用於checked build版本unsigned int NumberOfServices;unsigned char *ParamTableBase;}SERVICE_DESCRIPTOR_TABLE,*PSERVICE_DESCRIPTOR_TABLE; #pragma pack()//變數及函數定義如下:extern PSERVICE_DESCRIPTOR_TABLE KeServiceDescriptorTable;UCHAR * PsGetProcessImageFileName(__in PEPROCESS Process);#define PsGetCurrentProcessImageFileName() PsGetProcessImageFileName(PsGetCurrentProcess())ULONG NumberOfRaisedCPU;ULONG AllCPURaised;PKDPC g_basePKDPC;VOID CloseProtect(){__asm{clipush eaxmov eax,cr0and eax,not 10000hmov cr0,eaxpop eax}}VOID OpenProtect(){__asm{push eaxmov eax,cr0or eax,10000hmov cr0,eaxpop eaxsti}}VOID RaiseCPUIrqlAndWait( IN PKDPC Dpc, IN PVOID DeferredContext, IN PVOID SystemArgument1, IN PVOID SystemArgument2 ){InterlockedIncrement(&NumberOfRaisedCPU);while (!InterlockedCompareExchange(&AllCPURaised, 1, 1)){__asm nop;}InterlockedDecrement(&NumberOfRaisedCPU);}void ReleaseExclusivity(){InterlockedIncrement(&AllCPURaised);while (InterlockedCompareExchange(&NumberOfRaisedCPU, 0, 0)){__asm nop;}if (NULL != g_basePKDPC){ExFreePool((PVOID)g_basePKDPC);g_basePKDPC = NULL;}return;}BOOLEAN GainExlusivity(VOID){NTSTATUS ntStatus;ULONG u_currentCPU;CCHAR i;PKDPC pKdpc, temp_pkdpc;if (DISPATCH_LEVEL != KeGetCurrentIrql()){return FALSE;}InterlockedAnd(&NumberOfRaisedCPU, 0);InterlockedAnd(&AllCPURaised, 0);temp_pkdpc = (PKDPC)ExAllocatePoolWithTag(NonPagedPool, KeNumberProcessors * sizeof(KDPC),'xian');if (NULL == temp_pkdpc){return FALSE;}g_basePKDPC = temp_pkdpc;u_currentCPU = KeGetCurrentProcessorNumber();for (i = 0; i < KeNumberProcessors; i++, *temp_pkdpc++){if (i != u_currentCPU){KeInitializeDpc(temp_pkdpc, RaiseCPUIrqlAndWait, NULL);KeSetTargetProcessorDpc(temp_pkdpc, i);KeInsertQueueDpc(temp_pkdpc, NULL, NULL);}}while (KeNumberProcessors - 1 != InterlockedCompareExchange(&NumberOfRaisedCPU, KeNumberProcessors - 1, KeNumberProcessors - 1)){__asm nop;}return TRUE;}void __stdcall SetWp(){CloseProtect();ReleaseExclusivity();}void __stdcall ClearWp(){GainExlusivity();OpenProtect();}/************************************************************************//*函數名:SK_UnInlineHook參數:IN ULONG OldFunction,原函數地址IN ULONG HookCodeLength,需要恢複的位元組長度IN PVOID pOldFunctionCode需要恢複的位元組內容*//************************************************************************/NTSTATUS SK_UnInlineHook(IN ULONG OldFunction,IN ULONG HookCodeLength,IN PVOID pOldFunctionCode){NTSTATUS status = STATUS_SUCCESS;KIRQL OldIrql;SetWp();__try{RtlCopyMemory((PULONG)OldFunction,pOldFunctionCode,HookCodeLength);}__except(1){status = STATUS_UNSUCCESSFUL;}ClearWp();return status;}/************************************************************************//*函數名:SK_InlineHook參數:IN ULONG OldFunction,需要hook的函數IN ULONG MyFunction,跳轉到我們自己的函數IN ULONG HookCodeLength,需要hook的長度OUT PULONG JmpBackAddress,跳回原函數的地址OUT PVOID pOldFunctionCode儲存原函數被hook的位元組*//************************************************************************/NTSTATUS SK_InlineHook(IN ULONG OldFunction,IN ULONG MyFunction,IN ULONG HookCodeLength,OUT PULONG JmpBackAddress,OUT PVOID pOldFunctionCode){NTSTATUS status = STATUS_SUCCESS;KIRQL OldIrql;UCHAR Jmp[0x10];SetWp();__try{memset(Jmp,0x90,0x10);RtlCopyMemory(pOldFunctionCode,(PULONG)OldFunction,HookCodeLength);*(PUCHAR)Jmp = 0xe9;*(PULONG)((PUCHAR)Jmp + 1) = (ULONG)MyFunction - (ULONG)OldFunction - HookCodeLength;*JmpBackAddress = (ULONG)OldFunction + HookCodeLength;RtlCopyMemory((PULONG)OldFunction,Jmp,HookCodeLength);}__except(1){status = STATUS_UNSUCCESSFUL;}ClearWp();return status;}#endif
.c 檔案
#include "InlineHookTest.h"UCHAR g_OldCode[5] = {0x90};ULONG g_JmpBackAddress = 0;__declspec(naked)VOID MyOpenProcess(){KdPrint(("%s 調用了NtOpenProcess!\n",PsGetCurrentProcessImageFileName()));__asm{push 0xC4jmp [g_JmpBackAddress]}}VOID UnloadDriver(PDRIVER_OBJECT pDriver){SK_UnInlineHook((ULONG)(KeServiceDescriptorTable->ServiceTableBase[122]),5,g_OldCode);}NTSTATUS DriverEntry(PDRIVER_OBJECT pDriver,PUNICODE_STRING pRegt){pDriver->DriverUnload = UnloadDriver;SK_InlineHook((ULONG)(KeServiceDescriptorTable->ServiceTableBase[122]),(ULONG)MyOpenProcess,5,&g_JmpBackAddress,g_OldCode);return STATUS_SUCCESS;}