[Kong API].hooking
API front-end to hook_interface derivatives
Synopsis:
A : IAT PE or PLT:GOT ELF hook
T hook(T)(dynamic_object* library, string symbol, T callback);
void unhook(dynamic_object* library, string symbol);
B : x86 code-overwrite hook
T hook(T)(T address, T callback);
void unhook(void* address);
C : x86 code-overwrite (load library, resolve address)
T hook(T)(string library_name, string symbol, T callback);
void unhook(string library_name, string symbol)
Description
The hook family of functions modify the runtime behavior of a given target function by rerouting it. Internally, hook targets are marked by an identifier, which is used to create a stack of hooks specific to its type (A, B, C). This chain allows the semantics of the previous entry to be expanded and recorded.
- The return value of a hook operation is the previous entry at the top of the hook stack.
- Type A is a private hook - catches calls from within the specified executable image only.
- Type B & C are global hooks - catches any call to the target.
Error Handling:
Throws hook_exception on failure. Check hook_exception.error_code for details.
| Condition | Error code |
| Failure to resolve hook target, | hook_exception.ERROR.NOTFOUND |
| Invalid instruction encountered when examining target. | hook_exception.ERROR.PARSE |
| Failure to modify a protected memory block. | hook_exception.ERROR.ACCESS |
| Internal library failure. | hook_exception.ERROR.INTERNAL |
Example:
extern (Windows) uint32_t GetVersion(); // exported by kernel32.dll
char A(){ return 'A'; }
char B(){ return 'B'; }
char C(){ return 'C'; }
extern (Windows){
uint32_t D(){ return 0x0D; }
uint32_t E(){ return 0x0E; }
}
void main()
{
assert(A() == 'A');
// code-overwrite hook of known function address
hook(&A, &B); assert(A() == 'B');
hook(&A, &C); assert(A() == 'C');
unhook(&A); assert(A() == 'B');
unhook(&A); assert(A() == 'A');
uint32_t orig = GetVersion();
dynamic_object* obj = process_modules[IMAGE_SELF]; // this.exe
// Private IAT hook for calls within this.exe
hook(obj, "GetVersion", &D); assert(0x0D == GetVersion());
hook(obj, "GetVersion", &E); assert(0x0E == GetVersion());
unhook(obj, "GetVersion"); assert(0x0D == GetVersion());
unhook(obj, "GetVersion"); assert(orig == GetVersion());
// code-overwrite hook of unknown library function location
hook("kernel32.dll", "GetVersion", &D); assert(0x0D == GetVersion());
hook("kernel32.dll", "GetVersion", &E); assert(0x0E == GetVersion());
unhook("kernel32.dll", "GetVersion"); assert(0x0D == GetVersion());
unhook("kernel32.dll", "GetVersion"); assert(orig == GetVersion());
// call original functions
char function() next_0 = hook(&A, &B);
char function() next_1 = hook(&A, &C);
assert(next_0() == 'A');
assert(next_1() == 'B');
assert(A() == 'C');
}
