Inline Hooking - Windows 10 ver. 1909

This post shows and explains how a  windows API inline hooking works. For folks who are not aware of what a hooking is, it's a technique which allows to intercept a given API & also the ability to control the values sent. There are various ways, in which hooking can be achieved. One of them being Inline Hooking. In Inline hooking, we write an inline assembly code, in order to modify the target API's starting instructions, with the intention to change the control flow.  Let's discuss in step wise, how it works.

- Get the address of the API call which we want to hook.
- Copy the address of the API call & save the first few bytes, since it will be modified & later needs to be restored.
- Create a Hooked Function, which would be called every time our target API is called. This would be possible by patching the original API function.
- Now Patch the target API, by modifying the first 6 bytes & injecting an Inline assembly, to redirect the control flow to our Hooked Function.
- After successful hooking, restore the original bytes of the target API by copying it back.

#include "stdafx.h"
#include <Windows.h>
#include <stdio.h>

FARPROC GetLocalTimeAddress = NULL;
SIZE_T bytesWritten = 0;
char GetLocalTimeOriginalBytes[6] = {};

void __stdcall HookedGetLocalTime(LPSYSTEMTIME lpSystemTime) {
// print intercepted values from the GetLocalTime function
SYSTEMTIME lt = { 0 };
lt.wHour = 99;
lt.wMinute = 2;
lt.wSecond = 3;

wprintf(L"The local time is: %02d:%02d:%02d\n",
lt.wHour, lt.wMinute, lt.wSecond);

// unpatch GetLocalTime
WriteProcessMemory(GetCurrentProcess(), (LPVOID)GetLocalTimeAddress, GetLocalTimeOriginalBytes, sizeof(GetLocalTimeOriginalBytes), &bytesWritten);

// call the original GetLocalTime
return GetLocalTime(&lt);

int main()
// show GetLocalTime before hooking
SYSTEMTIME lt = { 0 };
wprintf(L"The local time is: %02d:%02d:%02d\n",lt.wHour, lt.wMinute, lt.wSecond);

HINSTANCE library = LoadLibraryA("Kernel32.dll");
SIZE_T bytesRead = 0;

// get address of the GetLocalTime function in memory
GetLocalTimeAddress = GetProcAddress(library, "GetLocalTime");

// save the first 6 bytes of the original GetLocalTime function - will need for unhooking
ReadProcessMemory(GetCurrentProcess(), GetLocalTimeAddress, GetLocalTimeOriginalBytes, 6, &bytesRead);

// create a patch "push <address of new GetLocalTime); ret"
void* hookedGetLocalTimeAddress = &HookedGetLocalTime;
char patch[6] = { 0 };
memcpy_s(patch, 1, "\x68", 1);
memcpy_s(patch + 1, 4, &hookedGetLocalTimeAddress, 4);
memcpy_s(patch + 5, 1, "\xC3", 1);

// patch the GetLocalTime
WriteProcessMemory(GetCurrentProcess(), (LPVOID)GetLocalTimeAddress, patch, sizeof(patch), &bytesWritten);

// show GetLocalTime after hooking

return 0;

In the above example, we attempted to hook the GetLocalTime API for demonstration. Now we will try our some real-time example. We will try to hook the MessageBox API used by notepad. Another way of looking at this would be, trying to hook the alert box, used by the "Find" functionality of notepad. 

Generally, the very first step would be to figure out the API call used by the functionality, which to hook.  For this purpose, we can use any windows API monitoring tool. This would expose the expose the API used by any functionality. 

#include "stdafx.h"

// The address of the original function
BYTE g_OldData[5];
// Replaced data
BYTE g_NewData[5] = { 0xE9 };

// Declare your own function
HookMsg(_In_opt_ HWND hWnd,
_In_opt_ LPCWSTR lpText,
_In_opt_ LPCWSTR lpCaption,
_In_ UINT uType);

// install hook
void InHook()
// Save the original function address
memcpy(g_OldData, MessageBoxW, 5);

// Calculate the offset to jump (own function address-original function address-5)    
DWORD Offset = (DWORD)HookMsg - (DWORD)MessageBoxW - 5;
*(DWORD*)(g_NewData + 1) = Offset;

// Modify memory attributes
DWORD Protect;
VirtualProtect(MessageBoxW, 5, PAGE_EXECUTE_READWRITE, &Protect);

// Replace function address
memcpy(MessageBoxW, g_NewData, 5);

// Restore memory attributes
VirtualProtect(MessageBoxW, 5, Protect, &Protect);

// Uninstall hook
void UnHook()
DWORD Protect;
VirtualProtect(MessageBoxW, 5, PAGE_EXECUTE_READWRITE, &Protect);
memcpy(MessageBoxW, g_OldData, 5);
VirtualProtect(MessageBoxW, 5, Protect, &Protect);

// Own Hook function
_In_opt_ HWND hWnd,
_In_opt_ LPCWSTR lpText,
_In_opt_ LPCWSTR lpCaption,
_In_ UINT uType)
// Replace string
lpText = L "Jiuyang Taoist inline Hook success!";
lpCaption = L "Nine Sun Taoist";

// first uninstall the hook
// Calling the real MessageBoxW function
int nRet = MessageBoxW(hWnd, lpText, lpCaption, uType);
// Finally put the hook on
return nRet;

Post a Comment