Your browser doesn't support JavaScript API Hooking and DLL Injection – Windows Programming

API Hooking and DLL Injection

Hooking is a technique used to intercept events or function calls so that an application can monitor, modify, or suppress their normal behaviour. The code that intercepts these events is called a hook procedure. A hook procedure can examine each event it receives, act on it, modify it, or pass it unchanged to the next hook procedure in the chain.

Windows allows developers to install hooks using the SetWindowsHookEx() API function. When an event such as a key press, mouse action, or window message occurs, Windows calls the appropriate hook procedure before the event reaches its normal destination. A hook chain is a list of application-defined hook procedures. Whenever an event associated with a particular hook type occurs, Windows passes the event to each hook procedure in the chain in turn.

Some types of hooks, particularly global hooks that monitor events in other processes, require the hook procedure to reside in a DLL. Windows loads this DLL into the address space of each target process so that the hook procedure can execute in that process. This mechanism is often referred to as DLL injection. DLL injection can also be performed by other techniques that do not involve Windows hooks and is commonly used by debugging tools, accessibility software, and application extensions, although it can also be misused by malicious software.

The prototype for SetWindowsHookEx is

HOOK SetWindowsHookEx(int idHook,HOOKPROC lpfn,HINSTANCE hmod,DWORD dwThreadId);

Where
idHook – is the type of hook procedure to be installed. This parameter can be one of the following values.
WH_DEBUG – used to monitor messages before the system sends them to the destination window procedure.
WH_CALLWNDPROCRET – used to monitor messages processed by the destination window procedure.
WH_CBT – used to receive notifications useful to a CBT application
WH_DEBUG – used when the application’s foreground thread is about to become idle.
WH_FOREGROUNDIDLE – used for performing low-priority tasks during idle time.
WH_JOURNALPLAYBACK – used to post messages previously recorded by a WH_JOURNALRECORD hook procedure.
WH_JOURNALRECORD – used to record input messages posted to the system message queue.
WH_KEYBOARD – used to monitor keystroke messages.
WH_KEYBOARD_LL – used to monitor low-level keyboard input events.
WH_MOUSE – Installs a hook procedure that monitors mouse messages.
WH_MOUSE_LL – used to monitor low-level mouse input events.
WH_MSGFILTER – used to monitor input events in a dialog box, message box, menu, or scroll bar.
WH_SHELL – used to monitor shell applications
WH_SYSMSGFILTER – used to monitor messages generated by an input event in a dialog box, message box, menu, or scroll bar.
Lpfn – A pointer to the hook procedure.
Hmod – A handle to the DLL containing the hook procedure pointed to by the lpfn parameter.
DwThreadId – The thread identifier with which the hook procedure is associated.

Return value – If the function succeeds, the return value is the handle to the hook procedure. If the function fails, the return value is NULL.

For detailed reading on the SetWindowsHookExA – https://docs.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-setwindowshookexa

The hook procedure

A hook procedure has the following syntax:

LRESULT CALLBACK HookProc(int nCode, WPARAM wParam, LPARAM lParam) { return CallNextHookEx(NULL, nCode, wParam, lParam); }

The nCode parameter is used to determine the action to perform. The value of the hook code depends on the type of the hook. The wParam and lParam parameters depend on the hook code, but they typically contain information about a message that was sent or posted

Calling the CallNextHookEx function to chain to the next hook procedure is not necessary, but it is highly recommended. This will enable other applications that have installed hooks to receive hook notifications and behave normally.

For further detailed reading about hooking
https://docs.microsoft.com/en-us/windows/win32/winmsg/about-hooks

Example

The following two examples demonstrate the use of the WH_KEYBOARD_LL hook. Each program installs a low-level keyboard hook, intercepts keyboard events, converts each virtual key into a readable name using GetKeyNameText(), and records the results in a text file. Pressing the Escape key removes the hook and terminates the program.

Both examples are written as Win32 Console Applications. They record keystrokes, not the characters ultimately produced by the keyboard. For example, pressing Shift+A records the individual key events rather than the character ‘A’. When creating the project, select the Console Application template rather than a Windows GUI application.

The first example (below) uses the WH_KEYBOARD hook. The hook procedure resides in a separate DLL, which is loaded using explicit linking. Windows injects the DLL into the address space of processes that receive keyboard input, allowing the hook procedure to monitor keyboard messages. The hook remains active until UnhookWindowsHookEx() is called, which occurs when the Enter key is pressed or when the console application is closed.

The second example (below) uses the WH_KEYBOARD_LL (low-level keyboard) hook. The hook procedure is exported from the executable itself rather than from a DLL. Unlike WH_KEYBOARD, the callback executes in the context of the application that installed the hook and therefore does not require process injection. Because the callback is delivered through the application’s message queue, the program must continue running and maintain a Windows message loop while the hook is active. The hook remains installed until UnhookWindowsHookEx() is called, which occurs when the Escape key is pressed or when the console application is closed.

WH_KEYBOARD versus WH_KEYBOARD_LL

Windows provides two keyboard hook types: WH_KEYBOARD and WH_KEYBOARD_LL. Although both allow an application to monitor keyboard activity, they operate in different ways and are intended for different purposes.

The WH_KEYBOARD hook is a traditional keyboard hook that monitors keyboard messages retrieved from a thread’s message queue. Because the hook procedure executes in the context of the target process, it must be implemented in a separate DLL so that Windows can load it into the address space of each process that receives keyboard input. On 64-bit versions of Windows, separate 32-bit and 64-bit DLLs are required if both types of applications are to be monitored.

The WH_KEYBOARD_LL hook is a low-level keyboard hook introduced with Windows 2000. Unlike WH_KEYBOARD, the hook procedure executes in the context of the application that installed the hook and therefore does not need to reside in a DLL. This makes low-level keyboard hooks significantly easier to implement and debug. However, because the callback executes in the installing process, that process must remain running and continue processing its message loop for the hook to remain active.

In most situations where an application simply needs to monitor or process keyboard input, WH_KEYBOARD_LL is the preferred choice. The older WH_KEYBOARD hook is generally only required when compatibility with legacy code or specialised message-hooking behaviour is needed.