15. IAT hooking

Note

See sample IAT hooking

15.1. Putting an IAT hook

To setup your IAT hook you just need:

You just need to use the function windows.pe_parse.IATEntry.set_hook()

Putting a hook:

import windows
from windows.hooks import *

@CreateFileACallback
def createfile_callback(lpFileName, dwDesiredAccess, dwShareMode, lpSecurityAttributes, dwCreationDisposition, dwFlagsAndAttributes, hTemplateFile, real_function):
    print("Trying to open {0}".format(lpFileName))
    if "secret" in lpFileName:
        return 0xffffffff
    return real_function()

my_exe = windows.current_process.peb.modules[0]
imp = my_exe.pe.imports

iat_create_file = [entry for entry in imp['kernel32.dll'] if entry.name == "CreateFileA"]
iat_create_file.set_hook(createfile_callback)

15.2. Hook protocol

15.2.1. Callback arguments

A hook callback must have the same number of argument as the hooked API, PLUS a last argument real_function.

The real_function argument is a callable that represent the hooked API, it can be called in two ways:

  • Without argument, the call will be done with the argument originaly passed to your callback. This allows simple redirection to the real API.
  • With arguments it will simply call the API with these.

Example:

def createfile_callback(lpFileName, dwDesiredAccess, dwShareMode, lpSecurityAttributes, dwCreationDisposition, dwFlagsAndAttributes, hTemplateFile, real_function):
    print("Trying to open {0}".format(lpFileName))
    if "secret" in lpFileName:
        return 0xffffffff
    # Perform the real call
    return real_function()

A hook callback must also embed some Type Information

15.2.2. Callback type information

In order make the magic behind hook callback, ctypes needs to have type information about the API parameters.

There is (again) two ways to give those informations to your hook callback. Both techniques use a decorator to setup type information to the callback.

  • Giving the type manualy using the decorator windows.hooks.Callback:

    from windows.hooks import *
    # First type is return type, others are parameters types
    @Callback(ctypes.c_void_p, ctypes.c_ulong)
    def exit_callback(x, real_function):
        print("Try to quit with {0} | {1}".format(x, type(x)))
        if x == 3:
            print("TRYING TO REAL EXIT")
            return real_function(1234)
        return 0x4242424243444546
    
  • Using the Callback decorator generated from known functions:

    from windows.hooks import *
    # Decorator name is always API_NAME + "CallBack"
    @CreateFileACallback
    def createfile_callback(lpFileName, dwDesiredAccess, dwShareMode, lpSecurityAttributes, dwCreationDisposition, dwFlagsAndAttributes, hTemplateFile, real_function):
        print("Trying to open {0}".format(lpFileName))
        if "secret" in lpFileName:
            return 0xffffffff
        return real_function()
    

Note

See the list of known functions

15.3. windows.hooks

class windows.hooks.Callback(*types)[source]

Give type information to hook callback

class windows.hooks.IATHook(IAT_entry, callback, types=None)[source]

Look at my hook <3

disable()[source]

Disable the IAT hook

enable()[source]

Enable the IAT hook: you MUST keep a reference to the IATHook while the hook is enabled