Reputation: 2780
I am trying to write a simple hook class that installs a hook at the target address and detouring the flow into custom function.
Main.cpp
#include "SingleHook.h"
#include <iostream>
using namespace std;
void originalFunction()
{
cout << "originalFunction()" << endl;
}
void fakeFunction()
{
cout << "fakeFunction()" << endl;
}
void main()
{
SingleHook sHook((DWORD)originalFunction, (DWORD)fakeFunction);
originalFunction(); //Should call the original function
sHook.InstallHook();
originalFunction(); //Should call the fake function
sHook.UninstallHook();
originalFunction(); //Should again call the original function
cin.get();
}
SingleHook.h
#pragma once
#define HLength 6
#include <windows.h>
class SingleHook {
private:
void* hookTarget;
byte originalBytes[HLength];
byte hookBytes[HLength];
public:
SingleHook(DWORD originalFunction, DWORD targetFunction)
{
//backing up original bytes
::memcpy(originalBytes, &originalFunction, HLength);
//generating hook bytes
hookBytes[0] = 0x68; //push
hookBytes[1] = ((byte*)targetFunction)[0];
hookBytes[2] = ((byte*)targetFunction)[1];
hookBytes[3] = ((byte*)targetFunction)[2];
hookBytes[4] = ((byte*)targetFunction)[3];
hookBytes[5] = 0xC3; //retn
//setting up hook target
hookTarget = &originalFunction;
}
void* InvokeOriginalFunction(...);
void InstallHook();
void UninstallHook();
};
SingleHook.cpp
#include "SingleHook.h"
void* SingleHook::InvokeOriginalFunction(...)
{
UninstallHook();
//TODO INVOKE ORIGINAL SOMEHOW
InstallHook();
return nullptr;
}
void SingleHook::InstallHook()
{
DWORD oldProt;
::VirtualProtect(hookTarget, HLength, PAGE_EXECUTE_READWRITE, &oldProt);
::memcpy(hookTarget, hookBytes, HLength);
::VirtualProtect(hookTarget, HLength, oldProt, nullptr);
}
void SingleHook::UninstallHook()
{
DWORD oldProt;
::VirtualProtect(hookTarget, HLength, PAGE_EXECUTE_READWRITE, &oldProt);
::memcpy(hookTarget, originalBytes, HLength);
::VirtualProtect(hookTarget, HLength, oldProt, nullptr);
}
The problem now is that when i install the hook and try calling originalFunction()
it still goes into original function and no call to fakeFunction()
is made... i have double checked the code and everything seems to be fine but there must be a gotcha somewhere.
Upvotes: 0
Views: 233
Reputation: 283893
It's important to note that the C and C++ Standards do not associate any meaning to casts between function pointers and object pointers -- if the destination variable is big enough to hold the entire address (not guaranteed, systems do exist that have different sizes for code and data), and you cast back to the original pointer type, you get back the original value. Any other usage is undefined behavior.
Self-mutating code is also undefined behavior.
The only supported mechanism for redirecting function calls at runtime is when the call is made indirectly, using a function pointer, to change the function pointer.
Since the language provides no guarantees, you're delving into details of the actual instructions the compiler generated... which means you had better look at those instructions, see whether the call is to the address you expected (under various conditions &originalFunction
might be the address of a trampoline, but the compiler might still emit calls directly to the real function body, or inline the call, etc.)
You might also have to use machine-specific instructions to flush the instruction cache, because changes to data normally are assumed NOT to change code. On Windows, there's a FlushInstructionCache
API call which you need to use when patching code. Read this explanation of why it is needed (discusses a non-Windows system but still expresses the concept well)
Upvotes: -1
Reputation: 2629
Just look here:
SingleHook(DWORD originalFunction, DWORD targetFunction)
{
//backing up original bytes
::memcpy(originalBytes, &originalFunction, HLength);
The value &originalFunction
is the address of the variable originalFunction
on the stack. Use (void*)originalFunction
instead.
Upvotes: 4