使用陷阱式Hook, 原理是把要Hook的API所在位置改成jmp newfunc, 这里的newfunc是用来代替此API的函数. 在newfunc中只要恢复被改的内存再调用原API就成了
使用方法:
建立DLL,使用系统级空Hook用于进入其它进程,
WINBASEAPI HANDLE WINAPI NewCreateFileA(
LPCSTR lpFileName,
DWORD dwDesiredAccess,
DWORD dwShareMode,
LPSECURITY_ATTRIBUTES lpSecurityAttributes,
DWORD dwCreationDisposition,
DWORD dwFlagsAndAttributes,
HANDLE hTemplateFile
)
{
hook->Lock(); // 因为陷阱式Hook是不可重入的,so用临界区来防止重入
hook->HookOff(); //恢复原CreateFileA地址的头五字节
HANDLE Result=CreateFileA(lpFileName,dwDesiredAccess,dwShareMode,
lpSecurityAttributes,dwCreationDisposition,dwFlagsAndAttributes,
hTemplateFile);
SendMessage(hwnd,WM_USER,HOOK_CREATEFILEA,0); //Hook到了,想做什么呢?
hook->HookOn(); //干完还得继续Hook地
hook->Unlock(); // 退出临界区
return Result;
}
在DllEntryPoint里建立Hook:
int WINAPI DllEntryPoint(HINSTANCE hinst, unsigned long reason, void* lpReserved)
{
if(reason==DLL_PROCESS_ATTACH)
{
h_inst=hinst;
hook=new CHookClass("kernel32.dll","CreateFileA",NewCreateFileA);
hook->HookOn();
}
else if(reason==DLL_PROCESS_DETACH)
{
delete hook;
}
return 1;
}
//系统级空Hook,这里用了WH_GETMESSAGE,用其它的也行:
LRESULT CALLBACK GetMsgProc(int code,WPARAM wPar,LPARAM lPar)
{
return CallNextHookEx(MessageHook, code, wPar, lPar); //什么也不做,只是为了进入其它进程
}
extern "C" void __declspec(dllexport) __stdcall StartHook(HWND hWnd)
{
if(MessageHook==0)
{
hwnd=hWnd;
MessageHook=SetWindowsHookEx(WH_GETMESSAGE, (HOOKPROC)GetMsgProc, h_inst, 0);
}
}
extern "C" void __declspec(dllexport) __stdcall StopHook()
{
if(MessageHook!=0)
{
UnhookWindowsHookEx(MessageHook);
MessageHook=0;
}
}
注意这里面的hwnd,MessageHook要使用共享段,怎么用不在此文章范围内,网上也是一找一大把的
//
#ifndef _HOOKCLASSH_
#define _HOOKCLASSH_
#include <windows.h>
//---------------------------------------------------------------
class CHookClass{
CHookClass(const CHookClass&);
CHookClass &operator=(const CHookClass&); //不准拷贝和赋值
#pragma pack(push,1)
struct TJmpCode{
char Jmp;
DWORD Ptr;
};
#pragma pack(pop)
public:
/* LibName: DLL 文件名 */
/* FuncName: 目标函数名 */
/* NewFuncPtr: 用于替换的函数指针 */
CHookClass(const char *LibName, const char *FuncName, void *NewFuncPtr);
~CHookClass();
void HookOn(); // 开启 API Hook
void HookOff(); // 关闭 API Hook
void Lock(); // 进入临界区
void Unlock(); // 退出临界区
bool IsHooked(){
// 取Hook状态
return _IsHooked;
}
private:
TJmpCode _OrgCode; // 原代码
TJmpCode _NewCode; // 新代码 jmp FuncPtr
void *_TagFuncPtr; // 目标函数指针
HANDLE _CurProcess; // 当前进程
bool _IsHooked; // 显示是否被Hook了
CRITICAL_SECTION _cs; // 临界区
};
//---------------------------------------------------------------
CHookClass::CHookClass(const char *LibName, const char *FuncName, void *NewFuncPtr)
:_TagFuncPtr(NULL),_IsHooked(false),_CurProcess(0)
{
HMODULE hModule=LoadLibrary(LibName);
_TagFuncPtr=GetProcAddress(hModule, FuncName);
if(_TagFuncPtr==NULL) throw(-1);
CopyMemory(&_OrgCode,_TagFuncPtr,5); // 保存原函数前五字节
_NewCode.Jmp=0xe9; //jmp
_NewCode.Ptr=DWORD(NewFuncPtr)-DWORD(_TagFuncPtr)-5; // 新的五字节为 jmp NewFuncPtr
_CurProcess=OpenProcess(PROCESS_ALL_ACCESS,FALSE, GetCurrentProcessId()); // 以特权方式打开当前进程
InitializeCriticalSection(&_cs);
}
CHookClass::~CHookClass()
{
if(_IsHooked) HookOff();
DeleteCriticalSection(&_cs);
}
void CHookClass::HookOn()
{
// !开启 API Hook
if(!_IsHooked)
{
DWORD dwOldProtect;
VirtualProtectEx(_CurProcess, _TagFuncPtr, 5, PAGE_READWRITE, &dwOldProtect); // 更改内存属性
WriteProcessMemory(_CurProcess, _TagFuncPtr, &_NewCode, 5, NULL); // 将_TagFuncPtr的前5个字节改为JMP NewFuncPtr
VirtualProtectEx(_CurProcess, _TagFuncPtr, 5, dwOldProtect, &dwOldProtect);
_IsHooked=true;
}
}
void CHookClass::HookOff()
{
// !关闭 API Hook
if(_IsHooked)
{
DWORD dwOldProtect;
VirtualProtectEx(_CurProcess, _TagFuncPtr, 5, PAGE_READWRITE, &dwOldProtect);
WriteProcessMemory(_CurProcess, _TagFuncPtr, &_OrgCode, 5, NULL); // 恢复_TagFuncPtr的前5个字节
VirtualProtectEx(_CurProcess, _TagFuncPtr, 5, dwOldProtect, &dwOldProtect);
_IsHooked=false;
}
}
void CHookClass::Lock() // 进入临界区
{
EnterCriticalSection(&_cs);
}
void CHookClass::Unlock() // 退出临界区
{
LeaveCriticalSection(&_cs);
}
#endif