[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');
}

Related:

dynamic_object, hook_interface, process