api hook还是挺常用的, 成熟的方案有微软自己的, 支持32位Detours。 还有支持32位、64位的开源库MHook。
按照MHook的api, 自己仿造了一个简化的, 用作学习。 只支持32位的, 要改成64位的话, 要对shellcode进行改写。
思路: 改写函数前面的机器码, 跳转到自己的函数。 要调用原函数时, 先写回原来函数的机器码, 再调用原函数, 调用完毕之后, 再次改写原函数前面的机器码。
坑的地方: 下面这两条质量生成的机器码不一样, 导致调试的时候花了很长时间。
pop dword ptr [eax + 12] //8F 40 0C
和
pop [eax + 12] //66 8F 40 0C
hookapi.h
#pragma once
typedef void * ApiAddress;
bool HookApi(ApiAddress *oldFunc, ApiAddress replaceWith);
void UnHookApi(ApiAddress *hookedApi);
hookapi.cpp
#include "hookapi.h"
#include "stdio.h"
#include "windows.h"
#define JMPSIZE 6
typedef void (* FUNCPTR)();
struct HookContext {
ApiAddress originalApiAddress;
ApiAddress replacedApiAddress;
DWORD esi;
DWORD eip;
CRITICAL_SECTION cs;
unsigned char *thunkBytes;
unsigned char originalBytes[JMPSIZE];
unsigned char replaceBytes[JMPSIZE];
HookContext *prev;
HookContext *next;
};
HookContext *ctxListHeader = nullptr, *ctxListTail = nullptr;
CRITICAL_SECTION ctxLock;
bool ctxLockInitialized;
HookContext * WINAPI findContext(ApiAddress api) {
//ODPRINTF(("findContext: %p", api));
HookContext *ctx = ctxListHeader;
while (ctx != nullptr) {
if (ctx->originalApiAddress == api) {
//ODPRINTF(("findContext:%p", ctx));
return ctx;
}
ctx = ctx->next;
}
return nullptr;
}
void WINAPI placeJmp(HookContext *ctx) {
//ODPRINTF((