API/Code Hooking 

www.madshi.net

Use "HookCode/HookAPI" to hook any function or API. Both your callback function and the next hook variable must have exactly the same definition (parameters + calling convention). Please use "HookAPI" as much as you can. "HookCode" is only meant for situations where "HookAPI" can't be used. Normally when calling HookCode/API you don't need to put anything into the "flags" parameter. However, in some specific situations the flags may be useful. So here's what they mean:

One thing you should know is that madCodeHook API hooks can be successfully installed even if the DLL which exports the to-be-hooked API is not loaded yet in the current process. For each API hook madCodeHook watches over DLL loading/unloading and installs/uninstalls its API hooks automatically at the right time. Can you have it any more comfortable?

// Hook any code or a specific API.
// api:
//    Name of the to-be-hooked API. Or a typecasted ordinal number.
// flags:
//    See flags defined above.
// numStackParams:
//    The parameter "numStackParams" is ignored, unless you specify the flag
//    STORE_THREAD_STATE at the same time. In that case "numStackParams" should
//    be set to the number of parameters that are stored on the stack. If you
//    set this number too low, your callback function will receive random param
//    values. Setting this number too high is not a problem. So if you're lazy,
//    you can just stick with the default of 32, which should be high enough
//    for all but the rarest situations. However, such a high value consumes
//    additional stack space and CPU performance. So in order to optimize RAM
//    and CPU consumption, it'd still be useful to set this parameter to the
//    correct value, or at least near to the correct value. You can estimate
//    high, just to be safe. A good estimate would be the number of parameters
//    plus one, that should work for all calling conventions, and also for
//    class methods.
function HookCode (code                 : pointer;
                   callbackFunc         : pointer;
                   out nextHook         : pointer;
                   flags                : dword = 0;
                   numStackParams       : dword = 32) : bool; stdcall;
function HookAPI  (module, api          : PAnsiChar;
                   callbackFunc         : pointer;
                   out nextHook         : pointer;
                   flags                : dword = 0;
                   numStackParams       : dword = 32) : bool; stdcall;

// Example:
var ExitProcessNext : procedure (exitCode: dword); stdcall;

procedure ExitProcessCallback(exitCode: dword); stdcall;
begin
  // okay, this doesn't make much sense, but who cares...  :-)
  ExitProcessNext(exitCode + 1);
end;

HookAPI('kernel32.dll', 'ExitProcess', @ExitProcessCallback, @ExitProcessNext);

If you're done with hooking, you can uninstall the hooks again. Process wide hooks are uninstalled automatically, when your DLL is unloaded or when your process exits. System wide hooks (only available in win9x) keep installed, if you don't manually uninstall them. Uninstalling is normally (if you didn't specify DONT_COUNT when hooking) delayed until the hook callback function is not in use by any thread anymore. This avoids crashes when a hook DLL is being uninjected.

function UnhookCode (var nextHook: pointer) : boolean;
function UnhookAPI  (var nextHook: pointer) : boolean;

// Example:
UnhookAPI(@ExitProcessNext);

Here is an explanation of the flags you can use in your HookAPI/HookCode calls:

const
  // By default madCodeHook counts how many times any thread is currently
  // running inside of your callback function.
  // This way unhooking can be safely synchronized to that counter.
  // Sometimes you don't need/want this counting to happen, e.g.
  // (1) if you don't plan to ever unhook, anyway
  // (2) if the counting performance drop is too high for your taste
  // (3) if you want to unhook from inside the hook callback function
  // In those cases you can set the flag "NO_SAFE_UNHOOKING".
  NO_SAFE_UNHOOKING = $00000001;

  // Optionally madCodeHook can use a special technique to make sure that
  // hooking in multi threaded situations won't result in crashing threads.
  // This technique is not tested too well right now, so it's optional for now.
  // You can turn this feature on by setting the flag "SAFE_HOOKING".
  // Without this technique crashes can happen, if a thread is calling the API
  // which we want to hook in exactly the moment when the hook is installed.
  SAFE_HOOKING = $00000020;

  // madCodeHook implements two different API hooking methods.
  // The mixture mode is the second best method, it's only used if the main
  // hooking method doesn't work for whatever reason (e.g. API code structure).
  // Normally madCodeHook chooses automatically which mode to use.
  // You can force madCodeHook to use the mixture mode by specifying this flag.
  MIXTURE_MODE = $00000002;

  // If you don't want madCodeHook to use the mixture mode, you can say so.
  // However, if the main hooking mode can't be used, hooking then simply fails.
  NO_MIXTURE_MODE = $00000010;

  // Winsock2 normally doesn't like the mixture mode.
  // However, I've found a way to convince winsock2 to accept mixture hooks.
  // This is a somewhat experimental feature, though.
  // So it must be turned on explicitly.
  ALLOW_WINSOCK2_MIXTURE_MODE = $00000080;

  // By default, if the target API was already hooked by other hook library,
  // madCodeHook switches to mixture mode (if possible).
  // If the other hook library used code overwriting with a simple JMP,
  // using the flag FOLLOW_JMP will instead make madCodeHook hook the callback
  // function of the other hook library. This should work just fine. However,
  // your hook will stop working in this case in the moment when the other
  // hook library uninstalls its hook.
  FOLLOW_JMP = $00000200;

  // Use this flag to have madCodeHook store the thread state, every time the
  // hooked function/API is called. The thread state is stored on the stack.
  // You can retrieve it in your hook callback function by using the API
  // "GetStoredThreadState".
  STORE_THREAD_STATE = $00000400;

When calling HookAPI with the "STORE_THREAD_STATE" flag, madCodeHook will store the thread state, every time the hooked API is called. You can call "GetStoredThreadState" to get access to the thread state from within your hook callback function.

type
  TPThreadState = ^TThreadState;
  TThreadState = record
    {$ifdef win64}
      rflags : NativeUInt;
      r15    : NativeUInt;
      r14    : NativeUInt;
      r13    : NativeUInt;
      r12    : NativeUInt;
      r11    : NativeUInt;
      r10    : NativeUInt;
      r9     : NativeUInt;
      r8     : NativeUInt;
      rdi    : NativeUInt;
      rsi    : NativeUInt;
      rbp    : NativeUInt;
      rbx    : NativeUInt;
      rdx    : NativeUInt;
      rcx    : NativeUInt;
      rax    : NativeUInt;
      rsp    : NativeUInt;
    {$else}
      rflags : NativeUInt;
      edi    : NativeUInt;
      esi    : NativeUInt;
      ebp    : NativeUInt;
      esp    : NativeUInt;
      ebx    : NativeUInt;
      edx    : NativeUInt;
      ecx    : NativeUInt;
      eax    : NativeUInt;
    {$endif}
  end;

// which state was the thread in when the hooked API/function was called
function GetStoredThreadState (var threadState: TPThreadState) : bool; stdcall;

Some firewall/antivirus programs install API hooks, too. Sometimes they uninstall your hooks. So if you hook often hooked APIs like CreateProcess, you might want to call RenewHook inside of your hook callback function (after you called the next hook), to make sure that your hook is still installed. Don't have fear, it rarely happens that another program is uninstalling your hooks. And if it happens, it only happens for such APIs, which are hooked very often. So normally you don't need to care. RenewHook is only there just in case...

function RenewHook (var nextHook: pointer) : bool; stdcall;

When unhooking an API madCodeHook (normally) waits until the hook is not in use anymore. Only then the API is unhooked. This is what I call "safe unhooking". It makes sure that there are no access violations when a hook dll gets unloaded. However, if safe unhooking constantly thinks that an API hook is still in use, this will freeze the unhooking and thus also the unloading of the hook dll. In order to be able to debug such situations you can call "IsHookInUse" to ask whether safe unhooking thinks that the hook is still in use or not. The returned number indicates how often the hook is still in use. "0" means the hook is not in use anymore.

function IsHookInUse (var nextHook: pointer) : integer; stdcall;

Putting all your HookAPI calls into a "CollectHooks".."FlushHooks" frame can eventually speed up the installation of the hooks.

procedure CollectHooks;
procedure   FlushHooks;

// Example:
procedure InstallTextOutHooks;
begin
  CollectHooks;
  HookAPI('gdi32.dll',    'TextOutA',    @TextOutACallbackProc,    @TextOutANextHook);
  HookAPI('gdi32.dll',    'TextOutW',    @TextOutWCallbackProc,    @TextOutWNextHook);
  HookAPI('gdi32.dll', 'ExtTextOutA', @ExtTextOutACallbackProc, @ExtTextOutANextHook);
  HookAPI('gdi32.dll', 'ExtTextOutW', @ExtTextOutWCallbackProc, @ExtTextOutWNextHook);
  FlushHooks;
end;

In case you've not read enough yet, you can also have a look at the "ProcessFunc" Example or at the "ProcessAPI" Example.