Using Detours
Two things are necessary in order to detour a target function:
a target pointer containing the address of the target function
and a detour function. For proper interception the target
function, detour function, and the target pointer must have
exactly the same call signature including number of arguments
and calling convention. Using the same calling convention
insures that registers will be properly preserved and that the
stack will be properly aligned between detour and target
functions
The code fragment in Figure 5 illustrates the usage of the
Detours library. User code must include the
detours.h
header file and link with the
detours.lib
library.
#include <windows.h>
#include <detours.h>
static LONG dwSlept = 0;
// Target pointer for the uninstrumented Sleep API.
static VOID (WINAPI * TrueSleep)(DWORD dwMilliseconds) = Sleep;
// Detour function that replaces the Sleep API.
VOID WINAPI TimedSleep(DWORD dwMilliseconds)
// Save the before and after times around calling the Sleep API.
DWORD dwBeg = GetTickCount();
TrueSleep(dwMilliseconds);
DWORD dwEnd = GetTickCount();
InterlockedExchangeAdd(&dwSlept;, dwEnd - dwBeg);
// DllMain function attaches and detaches the TimedSleep detour to the
// Sleep target function. The Sleep target function is referred to
// through the TrueSleep target pointer.
BOOL WINAPI DllMain(HINSTANCE hinst, DWORD dwReason, LPVOID reserved)
if (DetourIsHelperProcess()) {
return TRUE;
if (dwReason == DLL_PROCESS_ATTACH) {
DetourRestoreAfterWith();
DetourTransactionBegin();
DetourUpdateThread(GetCurrentThread());
DetourAttach(&(PVOID&)TrueSleep, TimedSleep);
DetourTransactionCommit();
else if (dwReason == DLL_PROCESS_DETACH) {
DetourTransactionBegin();
DetourUpdateThread(GetCurrentThread());
DetourDetach(&(PVOID&)TrueSleep, TimedSleep);
DetourTransactionCommit();
return TRUE;
Figure 5. Simple detour to modify the
Windows Sleep API.
Interception of the target function is enabled by invoking the
DetourAttach API
within a detour transaction. A detour transaction is marked by
calls to the
DetourTransactionBegin
API and the
DetourTransactionCommit
API. The DetourAttach
API takes two arguments: the address of the target pointer and
the pointer to the detour function. The target function is not
given as an argument because it must already be stored in the
target pointer.
The DetourUpdateThread
API enlists threads in the transaction so that their instruction
pointers are appropriately updated when the transaction commits.
The DetourAttach API
allocates and prepares a trampoline for calling the target
function. When the detour transaction commits, the target
function and trampoline are rewritten and the target pointer is
updated to point to the trampoline function.
Once a target function has been detoured, any call to the target
function will be re-routed through the detour function. It is
the responsibility of the detour function to copy arguments
when invoking the target function through the trampoline. This
is intuitive as the target function becomes simply a subroutine
callable by the detour function.
Interception of a target function is removed by calling the
DetourDetach API
within a detour transaction. Like the
DetourAttach API, the
DetourDetach API
takes two arguments: the address of the target pointer and the
pointer to the detour function. When the detour transaction
commits, the target function is rewritten and restored to its
original code, the trampoline function is deleted, and the
target pointer is restored to point to the original target
function.
In cases where detour functions need to inserted into an existing
application without source code access, the detour functions
should be packaged in a DLL. The DLL can be loaded into a new
process at creation time using the
DetourCreateProcessWithDllEx or
DetourCreateProcessWithDlls
APIs. If a DLL is inserted using DetourCreateProcessWithDllEx
or
DetourCreateProcessWithDlls
,
the DllMain function must call the
DetourRestoreAfterWith API.
If the DLL may be used in mixed 32-bit and 64-bit environments, then the
DllMain function must call the
DetourIsHelperProcess API.
The DLL must export the
DetourFinishHelperProcess
API as export Ordinal 1, which will be called by
rundll32.exe
to perform the helper tasks.
NOTE: Microsoft in no way warrants or supports any Microsoft or third-party
code that has been altered either with a detour or with any other mechanism.
The withdll.exe program include
in the Detours package uses the
DetourCreateProcessWithDlls
API to start a new process with a named DLL.
previous page
start
next page