原理上很简单的东西,但我想很多新手都苦于找不到完整的示例 代码,下面就是一份完整的代码
inline hook原理大概如下:
修改被HOOK函数A的头5个字节,使其跳转到我们自定义的函数B,函数B的类型与函数A要相同。因为我们是使用JMP直接跳转到函数B,
而不是使用正常的CALL指令。在函数B内,我们可以检查函数参数,然后可以直接返回。也可以再调用函数A的一个副本。这个副本在HOOK动作发生的同时,就保存下来了。
代码非常简单,工程打包供大家学习。高手飘过
/*
* krembo.c, Demonstration of inline hooking (aka. Detouring) within driver/kernel.
* - izik@tty64.org
*/
#include <ntddk.h>
// Assembly JMP opcode value
#ifndef X86_JMP
#define X86_JMP 0xE9
#endif
// Number of bytes to overwrite
#ifndef JMP_LENGTH
#define JMP_LENGTH sizeof(X86_JMP) + sizeof(int)
#endif
// Size of a page (4k)
#ifndef PAGE_SIZE
#define PAGE_SIZE 0x1000
#endif
// Pointers macros
#define PAGE_MASK(ptr) (ptr & 0xFFFFF000)
#define OFFSET_IN_PAGE(ptr) (ptr - (ptr & 0xFFFFF000))
// RtlRandom pointer prototype
typedef unsigned long (*RTLRANDOM)(
unsigned long *seed
);
// Pointers to duplicated (original) and current versions of RtlRandom
RTLRANDOM pDupRtlRandom;
RTLRANDOM pCurRtlRandom;
/*
* DetourFunction, Detour a function (Install Detour)
* * pFcnAddr, Pointer to the soon-to-be-detoured function
* * iHookAddr, Address of the hook function
* * iPoolType, Pool type of allocated memory
*/
void *DetourFunction(char *pFcnAddr, int iHookAddr, int iPoolType) {
void *pOrigPage;
// Allocate a `PAGE_SIZE` for the original function (duplicate)
pOrigPage = ExAllocatePoolWithTag(iPoolType, PAGE_SIZE, 0xdeadbeef);//分配一页内存,该函数在WIN 2000下可能不存在,XP下没问题
// Is there enough resources?
if (pOrigPage == NULL) {
return NULL;
}
// Duplicate the entire page
RtlCopyMemory(pOrigPage, (char *)PAGE_MASK((int)pFcnAddr), PAGE_SIZE);//拷贝函数内容,把函数所在的一整页都拷贝下来。如果函数不仅仅占据一页呢?
// Calculate the relocation to `iHookAddr`
iHookAddr -= ((int)pFcnAddr + 5);//iHookAddr = iHookAddr - (pFcnAddr +5) iHookAddr是跳转的相对地址
_asm
{
CLI // disable interrupt
MOV EAX, CR0 // move CR0 register into EAX
AND EAX, NOT 10000H // disable WP bit
MOV CR0, EAX // write register back
}
// Overwrite the first `JMP_LENGTH` bytes of pFcnAddr (Detour it)
*(pFcnAddr) = X86_JMP;
*(pFcnAddr+1) = (iHookAddr & 0xFF);
*(pFcnAddr+2) = (iHookAddr >> 8) & 0xFF;
*(pFcnAddr+3) = (iHookAddr >> 16) & 0xFF;
*(pFcnAddr+4) = (iHookAddr >> 24) & 0xFF;
_asm
{
MOV EAX, CR0 // move CR0 register into EAX
OR EAX, 10000H // enable WP bit
MOV CR0, EAX // write register back
STI // enable interrupt
}
// Return pointer to the duplicate function (within the duplicate page)
return (void *)((int)pOrigPage + OFFSET_IN_PAGE((int)pFcnAddr));//返回我们保存的函数副本地址(原件)
}
/*
* MyRtlRandom, RtlRandom hook
* * seed, given seed
*/
unsigned long MyRtlRandom(unsigned long *seed) {//HOOK发生时,原始函数跳转到该函数位置,★该函数的类型与原始函数相同
unsigned long retval;
DbgPrint(("MyRtlRandom invoked "));
retval = pDupRtlRandom(seed); //retval 是被HOOK函数的原件的地址,见DriverEntry(),在该函数内部又调用原始函数的原件(副本)
//DbgPrint(("Returning value = %d, from OldRtlRandom(%d)\n"));
return retval;
}
/*
* RestoreDetouredFunction, Restore a detoured function (Remove detour)
* * pDupFcn, Pointer to the duplicated function
* * pOrigFcn, Pointer to the original function
*/
void RestoreDetouredFunction(char *pOrigFcn, char *pDupFcn) { //移除HOOK
int offset;
_asm
{
CLI // disable interrupt
MOV EAX, CR0 // move CR0 register into EAX
AND EAX, NOT 10000H // disable WP bit
MOV CR0, EAX // write register back
}
// Uninstall the detour, Restore `JMP_LENGHT` bytes from the duplicate function.
for (offset = 0; offset < JMP_LENGTH; offset++) {
pOrigFcn[offset] = pDupFcn[offset];
}
_asm
{
MOV EAX, CR0 // move CR0 register into EAX
OR EAX, 10000H // enable WP bit
MOV CR0, EAX // write register back
STI // enable interrupt
}
// Deallocate the duplicate page
ExFreePoolWithTag((void *)((int)pDupFcn - OFFSET_IN_PAGE((int)pOrigFcn)), 0xdeadbeef);
return ;
}
/*
* DriverUnload, Driver unload point
* * DriverObject, self (Driver)
*/
void DriverUnload(IN PDRIVER_OBJECT DriverObject) {
unsigned long seed;
if (pDupRtlRandom != NULL) { //pDupRtlRandom为我们保存的原始函数原件
DbgPrint(("Removeing detour from RtlRandom\n"));
// Remove detour
RestoreDetouredFunction((char *)pCurRtlRandom, (char *)pDupRtlRandom);
// Do another self-test
seed = 31337;
pCurRtlRandom(&seed);
// No bugcheck? ;-)
}
//DbgPrint(("Krembo unloaded!\n"));
return ;
}
/*
* DriverEntry, Driver Single Entry Point
* * DriverObject, self (Driver)
* * RegistryPath, given RegistryPath
*/
NTSTATUS DriverEntry(IN PDRIVER_OBJECT DriverObject, IN PUNICODE_STRING RegistryPath) {
UNICODE_STRING pFcnName;
unsigned long seed;
//DbgPrint(("Krembo loaded!\n"));
// Register unload routine
DriverObject->DriverUnload = DriverUnload;
// Lookup RtlRandom address
RtlInitUnicodeString(&pFcnName, L"RtlRandom");
pCurRtlRandom = MmGetSystemRoutineAddress(&pFcnName);
//DbgPrint(("Found RtlRandom @ 0x%08x\n", pCurRtlRandom));
// Detour RtlRandom
pDupRtlRandom = DetourFunction((char *)pCurRtlRandom, (int)MyRtlRandom, (int)NonPagedPool);
// Detour status?
if (pDupRtlRandom == NULL) {
// Unable to detour
DbgPrint(("Unable to detour RtlRandom! (Not enough resources?)\n"));
} else {
//DbgPrint(("Duplicate Function @ 0x%08x\n", pDupRtlRandom));
// Detour installed, do a self-test
DbgPrint(("Detour installed, going into a self-test ...\n"));
////DbgPrint(("Detour installed, going into a self-test ...\n"));
// Dummy seed for the self-test
seed = 31337;
pCurRtlRandom(&seed);
}
return STATUS_SUCCESS;
}
晕,不知道怎么添加附件。firefox 功能就是不如IE。不过代码都在这里了,COPY下然后编译就OK了
[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课