分享一个多核下的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
{
cli
push eax
mov eax,cr0
and eax,not 10000h
mov cr0,eax
pop eax
}
}
VOID OpenProtect()
{
__asm
{
push eax
mov eax,cr0
or eax,10000h
mov cr0,eax
pop eax
sti
}
}
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 0xC4
jmp [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;
}