15
26-11-2011 1/15 Function Hooking and Windows Dll Injection Function Hooking and Windows Dll Injection In this tutorial I'll show you how to modify at runtime the behavior of Windows programs. Function Hot Patching Problem: we have a function, foo() and we want bar() to be called instead. Solutions: modify the code, replace foo() with bar(), doh!. Works when the source is available. 1. write a library that exports a function with the same signature as foo(), which internally calls bar(). On Unix based 2. systems use the LD_PRELOAD trick 1) to load the library before any other. On Windows, either place your library in the System32 folder (it must have the same name as the one exporting foo()) or do the registry hack 2) to have it load instead. If foo() isn't available through a shared library, you're out of luck. Here's a better solution: modify foo() at runtime by writing your code inside it! asm break So simply take the code from bar() and write it on top of foo() with memmove()-like logic. If bar() is significantly larger than foo() then we might run into trouble by overwriting code residing in memory "after" foo(). To avoid this unwanted effect, we'd have to "move" everything "after" foo() to larger addresses, so that bar() fits without overwriting anything. This is bad because multiple calls from outside to the code that is shifted in the memory will break. We'd also have to patch those calls and jumps, update them with the newer, bigger addresses, ending up with a tremendous amount of work. Thankfully there's an easier hack through means of the unconditional jump - jmp distance to destination. It works in the following way: x : jmp dword ptr [y - (x + 5)] x + 5: ....................................... y : etc At first the Instruction Pointer is at offset x and execution goes through the jump, next it's going to be at offset y, running whatever lies there. The operand to this form of jmp is a 32 bit offset, a distance between the "landing point" and the "jump point". It can be negative. So we might run into less trouble by writing jmp distance between bar and (foo + 5) immediately after the entry point of foo(). Basic Hot Patch Example hotpatch.cpp #include <windows.h> #include <cstdio> using namespace std; const unsigned char OP_JMP = 0xE9; // 32 bit relative jmp const SIZE_T SIZE_PATCH = 5; // jmp dword ptr distance; 1 byte + 4 bytes typedef void (*MyProc)(); void SimpleFunction1() { printf("foo\n"); } void SimpleFunction2() { printf("bar\n"); } int main() { PBYTE foo = reinterpret_cast<PBYTE>(SimpleFunction1); PBYTE bar = reinterpret_cast<PBYTE>(SimpleFunction2); DWORD oldProtection; // make sure the bytes of the function are writable Sisteme de Operare - http://elf.cs.pub.ro/so/wiki/

Function Hooking and Windows Dll Injection.pdf

  • Upload
    deto

  • View
    85

  • Download
    6

Embed Size (px)

Citation preview

Page 1: Function Hooking and Windows Dll Injection.pdf

26-11-2011 115 Function Hooking and Windows Dll Injection

Function Hooking and Windows Dll Injection

In this tutorial Ill show you how to modify at runtime the behavior of Windows programs

Function Hot Patching

Problem we have a function foo() and we want bar() to be called insteadSolutions

modify the code replace foo() with bar() doh Works when the source is available1write a library that exports a function with the same signature as foo() which internally calls bar() On Unix based2systems use the LD_PRELOAD trick1) to load the library before any other On Windows either place your library in theSystem32 folder (it must have the same name as the one exporting foo()) or do the registry hack2) to have it loadinstead If foo() isnt available through a shared library youre out of luck

Heres a better solution modify foo() at runtime by writing your code inside it

asm break

So simply take the code from bar() and write it on top of foo() with memmove()-like logic If bar() is significantlylarger than foo() then we might run into trouble by overwriting code residing in memory after foo() To avoid thisunwanted effect wed have to move everything after foo() to larger addresses so that bar() fits without overwritinganything This is bad because multiple calls from outside to the code that is shifted in the memory will break Wed alsohave to patch those calls and jumps update them with the newer bigger addresses ending up with a tremendous amountof workThankfully theres an easier hack through means of the unconditional jump - jmp distance to destination It worksin the following way

x jmp dword ptr [y - (x + 5)]x + 5y etc

At first the Instruction Pointer is at offset x and execution goes through the jump next its going to be at offset y runningwhatever lies there The operand to this form of jmp is a 32 bit offset a distance between the landing point and thejump point It can be negativeSo we might run into less trouble by writing jmp distance between bar and (foo + 5) immediately after the entrypoint of foo()

Basic Hot Patch Example

hotpatchcppinclude ltwindowshgtinclude ltcstdiogtusing namespace std const unsigned char OP_JMP = 0xE9 32 bit relative jmpconst SIZE_T SIZE_PATCH = 5 jmp dword ptr distance 1 byte + 4 bytestypedef void (MyProc)() void SimpleFunction1() printf(foon) void SimpleFunction2() printf(barn) int main() PBYTE foo = reinterpret_castltPBYTEgt(SimpleFunction1) PBYTE bar = reinterpret_castltPBYTEgt(SimpleFunction2) DWORD oldProtection make sure the bytes of the function are writable

Sisteme de Operare - httpelfcspubrosowiki

Function Hooking and Windows Dll Injection 215 26-11-2011

by default they are only readable and executable BOOL res = VirtualProtect(foo SIZE_PATCH PAGE_EXECUTE_READWRITE ampoldProtection) if (res) return 1 be mindful of pointer arithmetic works with PBYTE wont with PDWORD DWORD distanceToNewFoo = bar - foo - SIZE_PATCH foo = OP_JMP reinterpret_castltPDWORDgt(foo + 1) = distanceToNewFoo called though the pointer instead of foo() to make sure the compiler wont inline or do some other stupid stuff reinterpret_castltMyProcgt(foo)() will print barn return 0

An important thing to have in mind here is that the conversion between function pointer and void (PVOID PBYTE etc)is illegal in both C and C++3) even though it works in Visual C and in GCC For Linux check mprotect() instead ofVirtualProtect()

code as data

The following image is an attempt at showing a map of the code from hotpatchcpp Keep in mind that the memoryaddresses from the left side are fictional

httpelfcspubrosowiki Printed on 20111126 0759

26-11-2011 315 Function Hooking and Windows Dll Injection

foo() is 02114B05 - 011A3518 = 00F715ED bytes long fits an unsigned char[16193005] bar() is 0852AB241

Sisteme de Operare - httpelfcspubrosowiki

Function Hooking and Windows Dll Injection 415 26-11-2011

- 0852AA02 = 00000122 bytes long fits an unsigned char[290]the idea is to inject an unconditional jump at the beginning of foo() jump that will land at the first instruction of bar()2notice the distance between the expected current instruction within foo() at address 011A351D and the landing3zone in bar() address 0852AA02 Were talking about 0852AA02 - 011A351D = 073874E5 bytes acrossthe E9 jump receives an immediate operand that means the operand is within the code and the whole thing eats up 54bytes 1 for the opcode and 4 for the operand Thats why the execution jumps from 011A351D and not directly from thebeginning of foo() at 011A3518

As an observation both statement n and statement m are far rets opcode = CB For the example in the picture theprogram would write E9 E5 74 38 07 just at the beginning of foo()

E9 is the opcode for far jmp A far jmp receives an immediate 32 bit argument

E5 74 38 07 represent - due to endianness - the number 073874E5 the argument

As a rule its better to make sure the new function matches the old one in both calling convention and return value +arguments

Dll Injection

Now why would I go through the lengths of such useless (but fun) trickery I wont answer in this section but its requiredto fully grasp what will followUnder the Windows operating system dll injection refers to executing foreign code in a different process Ever wonderedhow applications such as Fraps4) or RivaTuner5) MSI Aterburner6) manage to display a framerate counter on top of thecurrently running full screen and exclusive mode D3D OpenGL application Or how something like Sockscap7) managesto redirect an applications traffic through the given proxy Read on

While the above applications take advantage of dll injection keep in mind that the global hotkeys functionality fromprograms such as foobar20008) or AutoHotkey9) are implemented by means of a cousin method - via low level keyboardhooks

This is how one would run their code in a parasited process10)

with SetWindowsHookEx() Installing global hooks from dlls defining them is dll injection at work Its an OK method1explained herewith CreateRemoteThread(LoadLibrary()) This is the true dll injection2with WriteProcessMemory(OurThreadProc) CreateRemoteThread(OurThreadProc) This is so much in the true spirit of3dll injection that its not even dll injection anymore its directly code injection

Heres the recipe for setting up a global Windows hook and getting your code into victim process

think of a suitable criteria for example when a window gets created That type of event is called a shell event and1its hookable via SetWindowsHookEx(WH_SHELL ShellProc)write myhookdll that defines and exports the above ShellProc() see some steps below For convenience also2export something like InstallHook() from that dll and within the code add the call to SetWindowsHookEx()write a launcher program that will call once the InstallHook() function defined in our dll and then just wait (if it3unloads probably Windows will also unload the dll unless special measures are taken resulting in crashes)ShellProc() will get called by the system everytime the specific event - a shell event in our case - is to be received by4the application Its code will run in that applications address space

Watch the following picture if you dont believe

httpelfcspubrosowiki Printed on 20111126 0759

26-11-2011 515 Function Hooking and Windows Dll Injection

normally an event is dispatched to the message loop of the receiving thread and the message loop further sends that1message within the thread to a proper handlermyhookdll registers system-wide ShellProc() as an interceptor of shell events (out of which WM_CREATE) Now2the message goes through the code from ShellProc() and only after processing its (not even necessary only becauseIm too kind) forwarded to the shell handler in the original event loop

A Practical Example

I like playing my games in windowed mode Inspired by Media Player Classic Homecinemas11) borderless always on top

Sisteme de Operare - httpelfcspubrosowiki

Function Hooking and Windows Dll Injection 615 26-11-2011

window mode I thought to myself how cool would it be to have any games window borderless and always on top of theother windows A games window usually contains either WS_CAPTION or WS_THICKFRAME window styles Making itborderless is a simple matter of retrieving its style (GetWindowLong(GWL_STYLE)) removing (toggling) by means of XORthe relevant style and then applying the result on the window handle SetWindowLong(GWL_STYLE)

Removing The Window Decorations

As a first attempt I created a simple one-shot console application that targeted the Heroes of Newerth window removingthe WS_CAPTION style as reported by Spy++

Borderless1cppinclude ltcstdiogtusing namespace stdinclude ltwindowshgt int main() bool done = false finish when q is entered while (done) HWND hwnd = FindWindow(NULL TEXT(Heroes of Newerth)) if (NULL = hwnd) LONG styles = GetWindowLong(hwnd GWL_STYLE) if (0 = styles) styles ^= WS_CAPTION LONG result = SetWindowLong(hwnd GWL_STYLE styles) char c scanf(c ampc) if (q == c) done = true return 0

httpelfcspubrosowiki Printed on 20111126 0759

26-11-2011 715 Function Hooking and Windows Dll Injection

You can observe 2 problems in the current approach

the window is now blurry1the mouse hover effect is registered a few pixels off2

The blurriness problem happens because after removing the decorations (titlebar dialog borders) Windows tries tomaintain the program window within the same bounding rectangle In doing so it inflates the client area by a few pixelsin each direction pixels obtained from removing said decorations Indeed counting the pixels from the first picture we geta total window area (including borders) of 1616times858 and a client area (only the Direct3D part from within the borderswhere the application draws its updates) of 1600times820 pixels For the second picture we have a window area equal to theclient area (no more borders) of 1606times848 pixels Since Heroes of Newerth has a dialog frame (non-sizeable) it doesnttreat WM_SIZE messages the Direct3D context keeps rendering at the initial config file resolution and the resulting framebuffer gets drawn with stretching on top of a sligthly different window area so we dont have a perfect (logical)pixel-on-(screen )pixel mapping anymoreNote my config file for the game

snipSetSave vid_resolution 1600820snip

Heres a fix for keeping the client area of the window in place during the style change

Borderless2cppinclude ltcstdiogtusing namespace stdinclude ltwindowshgt int main() bool done = false while (done) HWND hwnd = FindWindow(NULL TEXT(Heroes of Newerth)) if (NULL = hwnd) LONG styles = GetWindowLong(hwnd GWL_STYLE) if (0 = styles) styles ^= WS_CAPTION bool deflate = 0 == (styles amp WS_CAPTION) RECT rc GetWindowRect(hwnd amprc) int captionHeight = GetSystemMetrics(SM_CYCAPTION) int borderWidth = GetSystemMetrics(SM_CXDLGFRAME) int borderHeight = GetSystemMetrics(SM_CYDLGFRAME)

Sisteme de Operare - httpelfcspubrosowiki

Function Hooking and Windows Dll Injection 815 26-11-2011

if (deflate) rcleft += borderWidth rcright -= borderWidth rctop += captionHeight + borderHeight rcbottom -= borderHeight else rcleft -= borderWidth rcright += borderWidth rctop -= captionHeight + borderHeight rcbottom += borderHeight LONG result = SetWindowLong(hwnd GWL_STYLE styles) if (0 = result) SetWindowPos(hwnd NULL rcleft rctop rcright - rcleft rcbottom - rctop SWP_FRAMECHANGED) char c scanf(c ampc) if (q == c) done = true return 0

A process such as Starcraft 2 owns a window with the WS_THICKFRAME style denoting a sizing border If I change the codeto remove that style from the Starcraft 2 main window (also SM_CTHICKFRAME instead of SM_CDLGFRAME I can onlynotice the mouse hover effect being off - the game catches WM_SIZE messages and adjusts the framebuffer accordingly

Fixing The Mouse Behavior

For the broken mouse hover effect its time to put The Injection to use Among the usual suspects for this problem are thewindow rectangle functions GetWindowRect() and GetClientRect() It would make sense due to the fact that games usuallyobtain mouse events through DirectInput that initially mouse coordinates are expressed in desktop-absolute form and notrelative to the application window Therefore theyd have to employ in one form or another a conversion between screen(absolute) coordinates and window coordinates in a similar manner to the operation of ClientToScreen()Lets take a look at an application window and the GetRect() logic relating to it

What the game does when handling mouse input is obtain some absolute screen coordinates from DirectInput convertthem to window coordinates then compensate for the window title and borders and then figure out what to do next with

httpelfcspubrosowiki Printed on 20111126 0759

26-11-2011 915 Function Hooking and Windows Dll Injection

the event Note that after removing the window decorations both GetWindowRect() and GetClientRect() return thesame coordinates Then the game compensates by subtracting the expected widths and heights of borders resulting inslightly off readings for the events The idea here is to modify at run-time GetWindowRect() so that it returns the oldrectangle with titlebar and borders as if the window style still contained those elements

The basic workflow for detouring GetWindowRect() is

insert exactly at the beginning of the function a jmp to our GetWindowRect() hot patch it1in our GetWindowRect() restore the code of the original function2call the original function and save the result3modify that result so that it fits our agenda4hot patch GetWindowRect() again5return the now modified result6

32 Bit Versus 64 Bit

Special care should be taken when moving to x86-64

Hot Patching

While the previous approach for hot patching a function (via relative jmp) is generally OK even in 64 bit mode there couldbe rare occasions when the distance between the patched function and the original one cant be expressed on only 32 bitsSince the specific form of jmp used expects a 32 bit displacement it would be useless in this case

The suggested solution here is a 64 bit absolute jump which comes by default with x86-6412) The idea here is just slightlydifferent than in the case of plain x86 While jmp accepted there as argument an immediate displacement the x86-64 longjump functions through an indirect register So wed simply load the destination address (not a distance any more for thisinstruction) into a register and pass that register as the operand to the jmp Fortunately x86-64 states that the special64-bit registries r10 and r11 arent preserved between call opcodes so picking r11 is a safe bet and guaranteed not toruin the program flow

Dll Injection

One cant insert an image compiled for 32 bits inside a 64 bit process and cant inject a 64 bit dll inside a 32 bit processThe idea is to have 2 separate programs making the dll injection 2 versions of the dll each of them for 64 bits andrespectively for 32 bits The 32 bit injector should set up the hooks as usual and launch a light weight version of itself thatonly sets up the hook and waits for an end event

Loader

TCHAR path[MAX_PATH] DWORD len = GetModuleFileName(NULL path MAX_PATH) while (path[len - 1] = ) --len MoveMemory(path + len TEXT(Deframe64dat) sizeof(TCHAR) (lstrlen(TEXT(Deframe64dat)) + 1)) STARTUPINFO siDeframe64 = sizeof(STARTUPINFO) PROCESS_INFORMATION piDeframe64 BOOL bRes = CreateProcess(0 path NULL NULL TRUE 0 NULL NULL ampsiDeframe64 amppiDeframe64) if (bRes) WaitForInputIdle(piDeframe64hProcess INFINITE) InstallHook()

Deframe64cppinclude ltwindowshgtinclude DeframeHelperh int WINAPI WinMain(HINSTANCE hInstance HINSTANCE hPrevInstance LPSTR lpCmdLine int nCmdShow) InstallHook() main message loop MSG msg while (GetMessage(ampmsg NULL 0 0) ampamp WM_QUIT = msgmessage) TranslateMessage(ampmsg) DispatchMessage(ampmsg)

Sisteme de Operare - httpelfcspubrosowiki

Function Hooking and Windows Dll Injection 1015 26-11-2011

RemoveHook() return static_castltintgt(msgwParam)

The first fragment of code residing in the normal 32 bit injector process first spawns a 64 bit child our Deframe64datThey both perform the same main function at this stage - calling InstallHook() which is exported by the guest dll Ivemessed with the output of Deframe64 so that it has the extension dat this is only an aesthetic step so that the userdoesnt accidentally launch the useless and with no means of terminating 64 bit process On 32 bit systemsCreateProcess() will fail and I simply ignore everything involving itHeres how the 32 bit injector terminates the 64 bit one

if (bRes) PostThreadMessage(piDeframe64dwThreadId WM_QUIT 0 0)

The Visual Studio 2010 Solution

All the required code can be found here Note that the project files wont work with the Express version of Visual Studiodue to the main program - Deframe being written with MFCFor a binary build see this archiveThe solution uses a C-like approach for the Injection

A C++ Template Library (for the impatient)

This code is not for the faint of heart C++ 2003 (talking about Microsoft Visual C 2010 here variadic template support)template code to simplify the hotpatching Include it and use it as exemplified further below (its not included in the sourcedownload)

HotPatchhpppragma once include ltwindowshgt HotPatch is a thin wrapper on top of the function hot patching layer It encapsulates a way to replace known functions with own functions by means of patching in jmps in both x86and x86-64 The basic workflow is 1 Declare HotPatchfunctionltftypegt thePatch assign target to this object with thePatch = target 2 set a replacement callback with thePatchSetPatch(myTarget) 3 call thePatchApply() to replace the target with the other callback In the replacement procedure

httpelfcspubrosowiki Printed on 20111126 0759

26-11-2011 1115 Function Hooking and Windows Dll Injection

31 do your stuff 32 call thePatch(arguments) 33 do other stuff When done 4 restore the opcodes with thePatchRemovePatch() 5 the destructor or assigning a new function to thePatch will restore the protection status of the memoryreferred by target Limitations wont work with variadic functions (blame C)namespace HotPatch class Exception class MemoryException public Exception class PatchException public Exception template lttypename FTypegt class function_impl public function_impl() _pFun(NULL) _pPatch(NULL) _detoured(false) ~function_impl() _RestoreProtection() res = function_implltFTypegtIsPatched() tells whether a call to the target will run the target or thehook Return value bool res - true if ApplyPatch() has been called without an accompanying RemovePatch() bool IsPatched() return _detoured function_implltFTypegtoperator=(pFun) directs the patch to a target and prepares the target memory forwrites Parameters FType pFun - the function to patch (see Apply()) Throws MemoryException - when changing the protection of the page where pFun points is impossible void operator=(FType pFun) _RestoreProtection() _pFun = pFun if (NULL == _pFun) return BOOL res = VirtualProtect(_pFun _64bit _PATCH_LENGTH64 _PATCH_LENGTH32 PAGE_EXECUTE_READWRITEamp_oldProtection) if (res) throw MemoryException() function_implltFTypegtSetPatch(patch[ alwaysUse32Bit]) prepares internal state for the patch Parameters FType patch - the patch to use instead of pFun (see operator=(FType )) bool alwaysUse32Bit - If true a 32 bit jmp is always inserted Else the best jmp is determined based on necessities (can still be 32 bit if it fits) Throws PatchException - if patch is NULL void SetPatch(FType patch bool alwaysUse32Bit = false) if (NULL == patch) throw PatchException() if (NULL = _pPatch) RemovePatch() _pPatch = patch _64bit = alwaysUse32Bit they havent expressed mandatory 32 bit only path try to guess the best path

Sisteme de Operare - httpelfcspubrosowiki

Function Hooking and Windows Dll Injection 1215 26-11-2011

if (_64bit) LONGLONG jumpDistance = reinterpret_castltLONGLONGgt(_pPatch) - reinterpret_castltLONGLONGgt(_pFun) - _PATCH_LENGTH32 if (abs(jumpDistance) gt 0x7FFFFFFF) the jump is too long to fit a regular 32 bit relative jmp _64bit = true else _64bit = false save the old patch opcodes plain old for is faster DO NOT call any library functions for (SIZE_T i = 0 i lt (_64bit _PATCH_LENGTH64 _PATCH_LENGTH32) ++i) (_backup + i) = (reinterpret_castltPBYTEgt(_pFun) + i) function_implltFTypegtApplyPatch() makes pFun (see operator=(FType )) jmp to patch (seeSetPatch(FType bool)) This is the actual hot patch mechanism at work void ApplyPatch() if (_64bit) movabs reinterpret_castltPBYTEgt(_pFun) = _OP_MOVABS r11 (reinterpret_castltPBYTEgt(_pFun) + 1) = _R11_WRITE _detourProc reinterpret_castltPLONGLONGgt(reinterpret_castltPBYTEgt(_pFun) + 2) =reinterpret_castltLONGLONGgt(_pPatch) jmp reinterpret_castltPWORDgt(reinterpret_castltPBYTEgt(_pFun) + 10) = _OP_JMP64 abs r11 (reinterpret_castltPBYTEgt(_pFun) + 12) = _R11_JMP else jmp reinterpret_castltPBYTEgt(_pFun) = _OP_JMP32 distance left to _detourProc reinterpret_castltPDWORDgt(reinterpret_castltPBYTEgt(_pFun) + 1) = static_castltDWORDgt( reinterpret_castltPBYTEgt(_pPatch) - reinterpret_castltPBYTEgt(_pFun) - static_castltDWORDgt(_PATCH_LENGTH32)) _detoured = true function_implltFTypegtRemovePatch() undoes what ApplyPatch() did pFun (see operator=(FType )) willbe its old self again void RemovePatch() plain old for is faster DO NOT call any library functions for (SIZE_T i = 0 i lt (_64bit _PATCH_LENGTH64 _PATCH_LENGTH32) ++i) (reinterpret_castltPBYTEgt(_pFun) + i) = (_backup + i) _detoured = false protected FType _pFun FType _pPatch bool _64bit bool _detoured BYTE _backup[13] DWORD _oldProtection static const BYTE _OP_JMP32 = 0xE9 static const WORD _OP_JMP64 = 0xFF41 static const BYTE _OP_MOVABS = 0x49 static const BYTE _R11_WRITE = 0xBB static const BYTE _R11_JMP = 0xE3 static const SIZE_T _PATCH_LENGTH32 = 5 jmp detourProc - originalProc = 1 + 4 static const SIZE_T _PATCH_LENGTH64 = 13 movabs R11 detourProc (64 bit) jmp (abs 64) R11 = 1+ 1 + 8 + 2 + 1 template lttypename Tgt static T abs(T val) return val gt 0 val -val

httpelfcspubrosowiki Printed on 20111126 0759

26-11-2011 1315 Function Hooking and Windows Dll Injection

void _RestoreProtection() if (NULL == _pFun) return DWORD unusedOldProtection BOOL res = VirtualProtect(_pFun _64bit _PATCH_LENGTH64 _PATCH_LENGTH32 _oldProtectionampunusedOldProtection) (void) res nothing to do template lttypename FTypegt class _NativeCallGuard public _NativeCallGuard(function_implltFTypegt ampfun) _fun(fun) _funRemovePatch() ~_NativeCallGuard() _funApplyPatch() private function_implltFTypegt amp_fun template lttypenamegt class function define HP_TARG0define HP_TARG1 typename Arg1define HP_TARG2 HP_TARG1 typename Arg2define HP_TARG3 HP_TARG2 typename Arg3define HP_TARG4 HP_TARG3 typename Arg4define HP_TARG5 HP_TARG4 typename Arg5define HP_TARG6 HP_TARG5 typename Arg6define HP_TARG7 HP_TARG6 typename Arg7define HP_TARG8 HP_TARG7 typename Arg8define HP_TARG9 HP_TARG8 typename Arg9define HP_TARG10 HP_TARG9 typename Arg10define HP_FARG0define HP_FARG1 Arg1define HP_FARG2 HP_FARG1 Arg2define HP_FARG3 HP_FARG2 Arg3define HP_FARG4 HP_FARG3 Arg4define HP_FARG5 HP_FARG4 Arg5define HP_FARG6 HP_FARG5 Arg6define HP_FARG7 HP_FARG6 Arg7define HP_FARG8 HP_FARG7 Arg8define HP_FARG9 HP_FARG8 Arg9define HP_FARG10 HP_FARG9 Arg10define HP_ARG0define HP_ARG1 arg1define HP_ARG2 HP_ARG1 arg2define HP_ARG3 HP_ARG2 arg3define HP_ARG4 HP_ARG3 arg4define HP_ARG5 HP_ARG4 arg5define HP_ARG6 HP_ARG5 arg6define HP_ARG7 HP_ARG6 arg7define HP_ARG8 HP_ARG7 arg8define HP_ARG9 HP_ARG8 arg9define HP_ARG10 HP_ARG9 arg10define HP_ARG_DECL0define HP_ARG_DECL1 Arg1 arg1define HP_ARG_DECL2 HP_ARG_DECL1 Arg2 arg2define HP_ARG_DECL3 HP_ARG_DECL2 Arg3 arg3define HP_ARG_DECL4 HP_ARG_DECL3 Arg4 arg4define HP_ARG_DECL5 HP_ARG_DECL4 Arg5 arg5define HP_ARG_DECL6 HP_ARG_DECL5 Arg6 arg6define HP_ARG_DECL7 HP_ARG_DECL6 Arg7 arg7define HP_ARG_DECL8 HP_ARG_DECL7 Arg8 arg8define HP_ARG_DECL9 HP_ARG_DECL8 Arg9 arg9define HP_ARG_DECL10 HP_ARG_DECL9 Arg10 arg10 template partial specialization for functionltreturn_type([arg_types])gtdefine HP_RET_FUNCTION(n callconv) template lttypename _Ret HP_TARGngt class functionlt_Ret callconv(HP_FARGn)gt public function_impllt_Ret callconv(HP_FARGn)gt

Sisteme de Operare - httpelfcspubrosowiki

Function Hooking and Windows Dll Injection 1415 26-11-2011

private typedef _Ret callconv type(HP_FARGn) public ~functionlttypegt() _RestoreProtection() using function_impllttypegtoperator= _Ret operator()(HP_ARG_DECLn) _NativeCallGuardlttypegt CallGuard(this) return (_pFun)(HP_ARGn) protected using function_impllttypegt_pFun declare the 11 templates handling functions in the form _Ret function() _Ret function(Arg1) _Ret function(Arg1 Arg2) _Ret function(Arg1 Arg2 Arg10) HP_RET_FUNCTION(0 __cdecl) HP_RET_FUNCTION(1 __cdecl) HP_RET_FUNCTION(2 __cdecl) HP_RET_FUNCTION(3 __cdecl) HP_RET_FUNCTION(4 __cdecl) HP_RET_FUNCTION(5 __cdecl) HP_RET_FUNCTION(6 __cdecl) HP_RET_FUNCTION(7 __cdecl) HP_RET_FUNCTION(8 __cdecl) HP_RET_FUNCTION(9 __cdecl) HP_RET_FUNCTION(10 __cdecl) ifndef _M_X64 HP_RET_FUNCTION(0 __stdcall) HP_RET_FUNCTION(1 __stdcall) HP_RET_FUNCTION(2 __stdcall) HP_RET_FUNCTION(3 __stdcall) HP_RET_FUNCTION(4 __stdcall) HP_RET_FUNCTION(5 __stdcall) HP_RET_FUNCTION(6 __stdcall) HP_RET_FUNCTION(7 __stdcall) HP_RET_FUNCTION(8 __stdcall) HP_RET_FUNCTION(9 __stdcall) HP_RET_FUNCTION(10 __stdcall)endif namespace HotPatch

What Im doing above is generating 11 partial tempate specializations for class HotPatchfunction The class isinspired by C++2011s stdfunction Its a class that models functions with up to 10 (included) arguments - you cansee the declarations through the HP_RET_FUNCTION macro calls in there Then another set of 11 declarations for x86-64where only calling convention __cdecl exists Do not worry abut understanding the above code its ugly and it sucksFocus on the usage instead it gets things done (for up to 10 arguments that is)

To use this HotPatch mini-lib write something like

HotPatchTestcppinclude ltcstdiogtinclude HotPatchhppusing namespace stdusing namespace HotPatch functionltvoid()gt fooPatch void foo() printf(In foo()n) void bar()

httpelfcspubrosowiki Printed on 20111126 0759

26-11-2011 1515 Function Hooking and Windows Dll Injection

printf(Im hackin ur functionn) if (fooPatchIsPatched()) fooPatch() int main() void (pfoo)() = foo void (pbar)() = bar pfoo() calls foo() pbar() calls bar() fooPatch = foo fooPatchSetPatch(bar) fooPatchApplyPatch() pfoo() calls bar() pbar() calls bar() fooPatchRemovePatch() pfoo() calls foo() pbar() calls bar() return 0

Further Info and Support

Im usually idling under the handle foxx1337 on ircfreenodenet on rosedu1) httpwwwkernelorgdocman-pagesonlinepagesman8ld-linuxso8html LD_PRELOAD2) httpsupportmicrosoftcomkb197571 AppInit_DLLs registry hack3) httpyosefkcomc++fqafunctionhtml4) Fraps5) RivaTuner6) MSI Afterburner7) Sockscap8) foobar20009) AutoHotkey10) Code Project Article on Code Injection11) Media Player Classic Homecinema12) httpcontinuationswordpresscom20110510hot-patching-unconditional-jumps-x86-x86-64 Article on 64 bit hotpatching

Fromhttpelfcspubrosowiki - Sisteme de Operare

Permanent linkhttpelfcspubrosowikilaboratoareresurseinjections

Last update 20111108 0213

Sisteme de Operare - httpelfcspubrosowiki

Page 2: Function Hooking and Windows Dll Injection.pdf

Function Hooking and Windows Dll Injection 215 26-11-2011

by default they are only readable and executable BOOL res = VirtualProtect(foo SIZE_PATCH PAGE_EXECUTE_READWRITE ampoldProtection) if (res) return 1 be mindful of pointer arithmetic works with PBYTE wont with PDWORD DWORD distanceToNewFoo = bar - foo - SIZE_PATCH foo = OP_JMP reinterpret_castltPDWORDgt(foo + 1) = distanceToNewFoo called though the pointer instead of foo() to make sure the compiler wont inline or do some other stupid stuff reinterpret_castltMyProcgt(foo)() will print barn return 0

An important thing to have in mind here is that the conversion between function pointer and void (PVOID PBYTE etc)is illegal in both C and C++3) even though it works in Visual C and in GCC For Linux check mprotect() instead ofVirtualProtect()

code as data

The following image is an attempt at showing a map of the code from hotpatchcpp Keep in mind that the memoryaddresses from the left side are fictional

httpelfcspubrosowiki Printed on 20111126 0759

26-11-2011 315 Function Hooking and Windows Dll Injection

foo() is 02114B05 - 011A3518 = 00F715ED bytes long fits an unsigned char[16193005] bar() is 0852AB241

Sisteme de Operare - httpelfcspubrosowiki

Function Hooking and Windows Dll Injection 415 26-11-2011

- 0852AA02 = 00000122 bytes long fits an unsigned char[290]the idea is to inject an unconditional jump at the beginning of foo() jump that will land at the first instruction of bar()2notice the distance between the expected current instruction within foo() at address 011A351D and the landing3zone in bar() address 0852AA02 Were talking about 0852AA02 - 011A351D = 073874E5 bytes acrossthe E9 jump receives an immediate operand that means the operand is within the code and the whole thing eats up 54bytes 1 for the opcode and 4 for the operand Thats why the execution jumps from 011A351D and not directly from thebeginning of foo() at 011A3518

As an observation both statement n and statement m are far rets opcode = CB For the example in the picture theprogram would write E9 E5 74 38 07 just at the beginning of foo()

E9 is the opcode for far jmp A far jmp receives an immediate 32 bit argument

E5 74 38 07 represent - due to endianness - the number 073874E5 the argument

As a rule its better to make sure the new function matches the old one in both calling convention and return value +arguments

Dll Injection

Now why would I go through the lengths of such useless (but fun) trickery I wont answer in this section but its requiredto fully grasp what will followUnder the Windows operating system dll injection refers to executing foreign code in a different process Ever wonderedhow applications such as Fraps4) or RivaTuner5) MSI Aterburner6) manage to display a framerate counter on top of thecurrently running full screen and exclusive mode D3D OpenGL application Or how something like Sockscap7) managesto redirect an applications traffic through the given proxy Read on

While the above applications take advantage of dll injection keep in mind that the global hotkeys functionality fromprograms such as foobar20008) or AutoHotkey9) are implemented by means of a cousin method - via low level keyboardhooks

This is how one would run their code in a parasited process10)

with SetWindowsHookEx() Installing global hooks from dlls defining them is dll injection at work Its an OK method1explained herewith CreateRemoteThread(LoadLibrary()) This is the true dll injection2with WriteProcessMemory(OurThreadProc) CreateRemoteThread(OurThreadProc) This is so much in the true spirit of3dll injection that its not even dll injection anymore its directly code injection

Heres the recipe for setting up a global Windows hook and getting your code into victim process

think of a suitable criteria for example when a window gets created That type of event is called a shell event and1its hookable via SetWindowsHookEx(WH_SHELL ShellProc)write myhookdll that defines and exports the above ShellProc() see some steps below For convenience also2export something like InstallHook() from that dll and within the code add the call to SetWindowsHookEx()write a launcher program that will call once the InstallHook() function defined in our dll and then just wait (if it3unloads probably Windows will also unload the dll unless special measures are taken resulting in crashes)ShellProc() will get called by the system everytime the specific event - a shell event in our case - is to be received by4the application Its code will run in that applications address space

Watch the following picture if you dont believe

httpelfcspubrosowiki Printed on 20111126 0759

26-11-2011 515 Function Hooking and Windows Dll Injection

normally an event is dispatched to the message loop of the receiving thread and the message loop further sends that1message within the thread to a proper handlermyhookdll registers system-wide ShellProc() as an interceptor of shell events (out of which WM_CREATE) Now2the message goes through the code from ShellProc() and only after processing its (not even necessary only becauseIm too kind) forwarded to the shell handler in the original event loop

A Practical Example

I like playing my games in windowed mode Inspired by Media Player Classic Homecinemas11) borderless always on top

Sisteme de Operare - httpelfcspubrosowiki

Function Hooking and Windows Dll Injection 615 26-11-2011

window mode I thought to myself how cool would it be to have any games window borderless and always on top of theother windows A games window usually contains either WS_CAPTION or WS_THICKFRAME window styles Making itborderless is a simple matter of retrieving its style (GetWindowLong(GWL_STYLE)) removing (toggling) by means of XORthe relevant style and then applying the result on the window handle SetWindowLong(GWL_STYLE)

Removing The Window Decorations

As a first attempt I created a simple one-shot console application that targeted the Heroes of Newerth window removingthe WS_CAPTION style as reported by Spy++

Borderless1cppinclude ltcstdiogtusing namespace stdinclude ltwindowshgt int main() bool done = false finish when q is entered while (done) HWND hwnd = FindWindow(NULL TEXT(Heroes of Newerth)) if (NULL = hwnd) LONG styles = GetWindowLong(hwnd GWL_STYLE) if (0 = styles) styles ^= WS_CAPTION LONG result = SetWindowLong(hwnd GWL_STYLE styles) char c scanf(c ampc) if (q == c) done = true return 0

httpelfcspubrosowiki Printed on 20111126 0759

26-11-2011 715 Function Hooking and Windows Dll Injection

You can observe 2 problems in the current approach

the window is now blurry1the mouse hover effect is registered a few pixels off2

The blurriness problem happens because after removing the decorations (titlebar dialog borders) Windows tries tomaintain the program window within the same bounding rectangle In doing so it inflates the client area by a few pixelsin each direction pixels obtained from removing said decorations Indeed counting the pixels from the first picture we geta total window area (including borders) of 1616times858 and a client area (only the Direct3D part from within the borderswhere the application draws its updates) of 1600times820 pixels For the second picture we have a window area equal to theclient area (no more borders) of 1606times848 pixels Since Heroes of Newerth has a dialog frame (non-sizeable) it doesnttreat WM_SIZE messages the Direct3D context keeps rendering at the initial config file resolution and the resulting framebuffer gets drawn with stretching on top of a sligthly different window area so we dont have a perfect (logical)pixel-on-(screen )pixel mapping anymoreNote my config file for the game

snipSetSave vid_resolution 1600820snip

Heres a fix for keeping the client area of the window in place during the style change

Borderless2cppinclude ltcstdiogtusing namespace stdinclude ltwindowshgt int main() bool done = false while (done) HWND hwnd = FindWindow(NULL TEXT(Heroes of Newerth)) if (NULL = hwnd) LONG styles = GetWindowLong(hwnd GWL_STYLE) if (0 = styles) styles ^= WS_CAPTION bool deflate = 0 == (styles amp WS_CAPTION) RECT rc GetWindowRect(hwnd amprc) int captionHeight = GetSystemMetrics(SM_CYCAPTION) int borderWidth = GetSystemMetrics(SM_CXDLGFRAME) int borderHeight = GetSystemMetrics(SM_CYDLGFRAME)

Sisteme de Operare - httpelfcspubrosowiki

Function Hooking and Windows Dll Injection 815 26-11-2011

if (deflate) rcleft += borderWidth rcright -= borderWidth rctop += captionHeight + borderHeight rcbottom -= borderHeight else rcleft -= borderWidth rcright += borderWidth rctop -= captionHeight + borderHeight rcbottom += borderHeight LONG result = SetWindowLong(hwnd GWL_STYLE styles) if (0 = result) SetWindowPos(hwnd NULL rcleft rctop rcright - rcleft rcbottom - rctop SWP_FRAMECHANGED) char c scanf(c ampc) if (q == c) done = true return 0

A process such as Starcraft 2 owns a window with the WS_THICKFRAME style denoting a sizing border If I change the codeto remove that style from the Starcraft 2 main window (also SM_CTHICKFRAME instead of SM_CDLGFRAME I can onlynotice the mouse hover effect being off - the game catches WM_SIZE messages and adjusts the framebuffer accordingly

Fixing The Mouse Behavior

For the broken mouse hover effect its time to put The Injection to use Among the usual suspects for this problem are thewindow rectangle functions GetWindowRect() and GetClientRect() It would make sense due to the fact that games usuallyobtain mouse events through DirectInput that initially mouse coordinates are expressed in desktop-absolute form and notrelative to the application window Therefore theyd have to employ in one form or another a conversion between screen(absolute) coordinates and window coordinates in a similar manner to the operation of ClientToScreen()Lets take a look at an application window and the GetRect() logic relating to it

What the game does when handling mouse input is obtain some absolute screen coordinates from DirectInput convertthem to window coordinates then compensate for the window title and borders and then figure out what to do next with

httpelfcspubrosowiki Printed on 20111126 0759

26-11-2011 915 Function Hooking and Windows Dll Injection

the event Note that after removing the window decorations both GetWindowRect() and GetClientRect() return thesame coordinates Then the game compensates by subtracting the expected widths and heights of borders resulting inslightly off readings for the events The idea here is to modify at run-time GetWindowRect() so that it returns the oldrectangle with titlebar and borders as if the window style still contained those elements

The basic workflow for detouring GetWindowRect() is

insert exactly at the beginning of the function a jmp to our GetWindowRect() hot patch it1in our GetWindowRect() restore the code of the original function2call the original function and save the result3modify that result so that it fits our agenda4hot patch GetWindowRect() again5return the now modified result6

32 Bit Versus 64 Bit

Special care should be taken when moving to x86-64

Hot Patching

While the previous approach for hot patching a function (via relative jmp) is generally OK even in 64 bit mode there couldbe rare occasions when the distance between the patched function and the original one cant be expressed on only 32 bitsSince the specific form of jmp used expects a 32 bit displacement it would be useless in this case

The suggested solution here is a 64 bit absolute jump which comes by default with x86-6412) The idea here is just slightlydifferent than in the case of plain x86 While jmp accepted there as argument an immediate displacement the x86-64 longjump functions through an indirect register So wed simply load the destination address (not a distance any more for thisinstruction) into a register and pass that register as the operand to the jmp Fortunately x86-64 states that the special64-bit registries r10 and r11 arent preserved between call opcodes so picking r11 is a safe bet and guaranteed not toruin the program flow

Dll Injection

One cant insert an image compiled for 32 bits inside a 64 bit process and cant inject a 64 bit dll inside a 32 bit processThe idea is to have 2 separate programs making the dll injection 2 versions of the dll each of them for 64 bits andrespectively for 32 bits The 32 bit injector should set up the hooks as usual and launch a light weight version of itself thatonly sets up the hook and waits for an end event

Loader

TCHAR path[MAX_PATH] DWORD len = GetModuleFileName(NULL path MAX_PATH) while (path[len - 1] = ) --len MoveMemory(path + len TEXT(Deframe64dat) sizeof(TCHAR) (lstrlen(TEXT(Deframe64dat)) + 1)) STARTUPINFO siDeframe64 = sizeof(STARTUPINFO) PROCESS_INFORMATION piDeframe64 BOOL bRes = CreateProcess(0 path NULL NULL TRUE 0 NULL NULL ampsiDeframe64 amppiDeframe64) if (bRes) WaitForInputIdle(piDeframe64hProcess INFINITE) InstallHook()

Deframe64cppinclude ltwindowshgtinclude DeframeHelperh int WINAPI WinMain(HINSTANCE hInstance HINSTANCE hPrevInstance LPSTR lpCmdLine int nCmdShow) InstallHook() main message loop MSG msg while (GetMessage(ampmsg NULL 0 0) ampamp WM_QUIT = msgmessage) TranslateMessage(ampmsg) DispatchMessage(ampmsg)

Sisteme de Operare - httpelfcspubrosowiki

Function Hooking and Windows Dll Injection 1015 26-11-2011

RemoveHook() return static_castltintgt(msgwParam)

The first fragment of code residing in the normal 32 bit injector process first spawns a 64 bit child our Deframe64datThey both perform the same main function at this stage - calling InstallHook() which is exported by the guest dll Ivemessed with the output of Deframe64 so that it has the extension dat this is only an aesthetic step so that the userdoesnt accidentally launch the useless and with no means of terminating 64 bit process On 32 bit systemsCreateProcess() will fail and I simply ignore everything involving itHeres how the 32 bit injector terminates the 64 bit one

if (bRes) PostThreadMessage(piDeframe64dwThreadId WM_QUIT 0 0)

The Visual Studio 2010 Solution

All the required code can be found here Note that the project files wont work with the Express version of Visual Studiodue to the main program - Deframe being written with MFCFor a binary build see this archiveThe solution uses a C-like approach for the Injection

A C++ Template Library (for the impatient)

This code is not for the faint of heart C++ 2003 (talking about Microsoft Visual C 2010 here variadic template support)template code to simplify the hotpatching Include it and use it as exemplified further below (its not included in the sourcedownload)

HotPatchhpppragma once include ltwindowshgt HotPatch is a thin wrapper on top of the function hot patching layer It encapsulates a way to replace known functions with own functions by means of patching in jmps in both x86and x86-64 The basic workflow is 1 Declare HotPatchfunctionltftypegt thePatch assign target to this object with thePatch = target 2 set a replacement callback with thePatchSetPatch(myTarget) 3 call thePatchApply() to replace the target with the other callback In the replacement procedure

httpelfcspubrosowiki Printed on 20111126 0759

26-11-2011 1115 Function Hooking and Windows Dll Injection

31 do your stuff 32 call thePatch(arguments) 33 do other stuff When done 4 restore the opcodes with thePatchRemovePatch() 5 the destructor or assigning a new function to thePatch will restore the protection status of the memoryreferred by target Limitations wont work with variadic functions (blame C)namespace HotPatch class Exception class MemoryException public Exception class PatchException public Exception template lttypename FTypegt class function_impl public function_impl() _pFun(NULL) _pPatch(NULL) _detoured(false) ~function_impl() _RestoreProtection() res = function_implltFTypegtIsPatched() tells whether a call to the target will run the target or thehook Return value bool res - true if ApplyPatch() has been called without an accompanying RemovePatch() bool IsPatched() return _detoured function_implltFTypegtoperator=(pFun) directs the patch to a target and prepares the target memory forwrites Parameters FType pFun - the function to patch (see Apply()) Throws MemoryException - when changing the protection of the page where pFun points is impossible void operator=(FType pFun) _RestoreProtection() _pFun = pFun if (NULL == _pFun) return BOOL res = VirtualProtect(_pFun _64bit _PATCH_LENGTH64 _PATCH_LENGTH32 PAGE_EXECUTE_READWRITEamp_oldProtection) if (res) throw MemoryException() function_implltFTypegtSetPatch(patch[ alwaysUse32Bit]) prepares internal state for the patch Parameters FType patch - the patch to use instead of pFun (see operator=(FType )) bool alwaysUse32Bit - If true a 32 bit jmp is always inserted Else the best jmp is determined based on necessities (can still be 32 bit if it fits) Throws PatchException - if patch is NULL void SetPatch(FType patch bool alwaysUse32Bit = false) if (NULL == patch) throw PatchException() if (NULL = _pPatch) RemovePatch() _pPatch = patch _64bit = alwaysUse32Bit they havent expressed mandatory 32 bit only path try to guess the best path

Sisteme de Operare - httpelfcspubrosowiki

Function Hooking and Windows Dll Injection 1215 26-11-2011

if (_64bit) LONGLONG jumpDistance = reinterpret_castltLONGLONGgt(_pPatch) - reinterpret_castltLONGLONGgt(_pFun) - _PATCH_LENGTH32 if (abs(jumpDistance) gt 0x7FFFFFFF) the jump is too long to fit a regular 32 bit relative jmp _64bit = true else _64bit = false save the old patch opcodes plain old for is faster DO NOT call any library functions for (SIZE_T i = 0 i lt (_64bit _PATCH_LENGTH64 _PATCH_LENGTH32) ++i) (_backup + i) = (reinterpret_castltPBYTEgt(_pFun) + i) function_implltFTypegtApplyPatch() makes pFun (see operator=(FType )) jmp to patch (seeSetPatch(FType bool)) This is the actual hot patch mechanism at work void ApplyPatch() if (_64bit) movabs reinterpret_castltPBYTEgt(_pFun) = _OP_MOVABS r11 (reinterpret_castltPBYTEgt(_pFun) + 1) = _R11_WRITE _detourProc reinterpret_castltPLONGLONGgt(reinterpret_castltPBYTEgt(_pFun) + 2) =reinterpret_castltLONGLONGgt(_pPatch) jmp reinterpret_castltPWORDgt(reinterpret_castltPBYTEgt(_pFun) + 10) = _OP_JMP64 abs r11 (reinterpret_castltPBYTEgt(_pFun) + 12) = _R11_JMP else jmp reinterpret_castltPBYTEgt(_pFun) = _OP_JMP32 distance left to _detourProc reinterpret_castltPDWORDgt(reinterpret_castltPBYTEgt(_pFun) + 1) = static_castltDWORDgt( reinterpret_castltPBYTEgt(_pPatch) - reinterpret_castltPBYTEgt(_pFun) - static_castltDWORDgt(_PATCH_LENGTH32)) _detoured = true function_implltFTypegtRemovePatch() undoes what ApplyPatch() did pFun (see operator=(FType )) willbe its old self again void RemovePatch() plain old for is faster DO NOT call any library functions for (SIZE_T i = 0 i lt (_64bit _PATCH_LENGTH64 _PATCH_LENGTH32) ++i) (reinterpret_castltPBYTEgt(_pFun) + i) = (_backup + i) _detoured = false protected FType _pFun FType _pPatch bool _64bit bool _detoured BYTE _backup[13] DWORD _oldProtection static const BYTE _OP_JMP32 = 0xE9 static const WORD _OP_JMP64 = 0xFF41 static const BYTE _OP_MOVABS = 0x49 static const BYTE _R11_WRITE = 0xBB static const BYTE _R11_JMP = 0xE3 static const SIZE_T _PATCH_LENGTH32 = 5 jmp detourProc - originalProc = 1 + 4 static const SIZE_T _PATCH_LENGTH64 = 13 movabs R11 detourProc (64 bit) jmp (abs 64) R11 = 1+ 1 + 8 + 2 + 1 template lttypename Tgt static T abs(T val) return val gt 0 val -val

httpelfcspubrosowiki Printed on 20111126 0759

26-11-2011 1315 Function Hooking and Windows Dll Injection

void _RestoreProtection() if (NULL == _pFun) return DWORD unusedOldProtection BOOL res = VirtualProtect(_pFun _64bit _PATCH_LENGTH64 _PATCH_LENGTH32 _oldProtectionampunusedOldProtection) (void) res nothing to do template lttypename FTypegt class _NativeCallGuard public _NativeCallGuard(function_implltFTypegt ampfun) _fun(fun) _funRemovePatch() ~_NativeCallGuard() _funApplyPatch() private function_implltFTypegt amp_fun template lttypenamegt class function define HP_TARG0define HP_TARG1 typename Arg1define HP_TARG2 HP_TARG1 typename Arg2define HP_TARG3 HP_TARG2 typename Arg3define HP_TARG4 HP_TARG3 typename Arg4define HP_TARG5 HP_TARG4 typename Arg5define HP_TARG6 HP_TARG5 typename Arg6define HP_TARG7 HP_TARG6 typename Arg7define HP_TARG8 HP_TARG7 typename Arg8define HP_TARG9 HP_TARG8 typename Arg9define HP_TARG10 HP_TARG9 typename Arg10define HP_FARG0define HP_FARG1 Arg1define HP_FARG2 HP_FARG1 Arg2define HP_FARG3 HP_FARG2 Arg3define HP_FARG4 HP_FARG3 Arg4define HP_FARG5 HP_FARG4 Arg5define HP_FARG6 HP_FARG5 Arg6define HP_FARG7 HP_FARG6 Arg7define HP_FARG8 HP_FARG7 Arg8define HP_FARG9 HP_FARG8 Arg9define HP_FARG10 HP_FARG9 Arg10define HP_ARG0define HP_ARG1 arg1define HP_ARG2 HP_ARG1 arg2define HP_ARG3 HP_ARG2 arg3define HP_ARG4 HP_ARG3 arg4define HP_ARG5 HP_ARG4 arg5define HP_ARG6 HP_ARG5 arg6define HP_ARG7 HP_ARG6 arg7define HP_ARG8 HP_ARG7 arg8define HP_ARG9 HP_ARG8 arg9define HP_ARG10 HP_ARG9 arg10define HP_ARG_DECL0define HP_ARG_DECL1 Arg1 arg1define HP_ARG_DECL2 HP_ARG_DECL1 Arg2 arg2define HP_ARG_DECL3 HP_ARG_DECL2 Arg3 arg3define HP_ARG_DECL4 HP_ARG_DECL3 Arg4 arg4define HP_ARG_DECL5 HP_ARG_DECL4 Arg5 arg5define HP_ARG_DECL6 HP_ARG_DECL5 Arg6 arg6define HP_ARG_DECL7 HP_ARG_DECL6 Arg7 arg7define HP_ARG_DECL8 HP_ARG_DECL7 Arg8 arg8define HP_ARG_DECL9 HP_ARG_DECL8 Arg9 arg9define HP_ARG_DECL10 HP_ARG_DECL9 Arg10 arg10 template partial specialization for functionltreturn_type([arg_types])gtdefine HP_RET_FUNCTION(n callconv) template lttypename _Ret HP_TARGngt class functionlt_Ret callconv(HP_FARGn)gt public function_impllt_Ret callconv(HP_FARGn)gt

Sisteme de Operare - httpelfcspubrosowiki

Function Hooking and Windows Dll Injection 1415 26-11-2011

private typedef _Ret callconv type(HP_FARGn) public ~functionlttypegt() _RestoreProtection() using function_impllttypegtoperator= _Ret operator()(HP_ARG_DECLn) _NativeCallGuardlttypegt CallGuard(this) return (_pFun)(HP_ARGn) protected using function_impllttypegt_pFun declare the 11 templates handling functions in the form _Ret function() _Ret function(Arg1) _Ret function(Arg1 Arg2) _Ret function(Arg1 Arg2 Arg10) HP_RET_FUNCTION(0 __cdecl) HP_RET_FUNCTION(1 __cdecl) HP_RET_FUNCTION(2 __cdecl) HP_RET_FUNCTION(3 __cdecl) HP_RET_FUNCTION(4 __cdecl) HP_RET_FUNCTION(5 __cdecl) HP_RET_FUNCTION(6 __cdecl) HP_RET_FUNCTION(7 __cdecl) HP_RET_FUNCTION(8 __cdecl) HP_RET_FUNCTION(9 __cdecl) HP_RET_FUNCTION(10 __cdecl) ifndef _M_X64 HP_RET_FUNCTION(0 __stdcall) HP_RET_FUNCTION(1 __stdcall) HP_RET_FUNCTION(2 __stdcall) HP_RET_FUNCTION(3 __stdcall) HP_RET_FUNCTION(4 __stdcall) HP_RET_FUNCTION(5 __stdcall) HP_RET_FUNCTION(6 __stdcall) HP_RET_FUNCTION(7 __stdcall) HP_RET_FUNCTION(8 __stdcall) HP_RET_FUNCTION(9 __stdcall) HP_RET_FUNCTION(10 __stdcall)endif namespace HotPatch

What Im doing above is generating 11 partial tempate specializations for class HotPatchfunction The class isinspired by C++2011s stdfunction Its a class that models functions with up to 10 (included) arguments - you cansee the declarations through the HP_RET_FUNCTION macro calls in there Then another set of 11 declarations for x86-64where only calling convention __cdecl exists Do not worry abut understanding the above code its ugly and it sucksFocus on the usage instead it gets things done (for up to 10 arguments that is)

To use this HotPatch mini-lib write something like

HotPatchTestcppinclude ltcstdiogtinclude HotPatchhppusing namespace stdusing namespace HotPatch functionltvoid()gt fooPatch void foo() printf(In foo()n) void bar()

httpelfcspubrosowiki Printed on 20111126 0759

26-11-2011 1515 Function Hooking and Windows Dll Injection

printf(Im hackin ur functionn) if (fooPatchIsPatched()) fooPatch() int main() void (pfoo)() = foo void (pbar)() = bar pfoo() calls foo() pbar() calls bar() fooPatch = foo fooPatchSetPatch(bar) fooPatchApplyPatch() pfoo() calls bar() pbar() calls bar() fooPatchRemovePatch() pfoo() calls foo() pbar() calls bar() return 0

Further Info and Support

Im usually idling under the handle foxx1337 on ircfreenodenet on rosedu1) httpwwwkernelorgdocman-pagesonlinepagesman8ld-linuxso8html LD_PRELOAD2) httpsupportmicrosoftcomkb197571 AppInit_DLLs registry hack3) httpyosefkcomc++fqafunctionhtml4) Fraps5) RivaTuner6) MSI Afterburner7) Sockscap8) foobar20009) AutoHotkey10) Code Project Article on Code Injection11) Media Player Classic Homecinema12) httpcontinuationswordpresscom20110510hot-patching-unconditional-jumps-x86-x86-64 Article on 64 bit hotpatching

Fromhttpelfcspubrosowiki - Sisteme de Operare

Permanent linkhttpelfcspubrosowikilaboratoareresurseinjections

Last update 20111108 0213

Sisteme de Operare - httpelfcspubrosowiki

Page 3: Function Hooking and Windows Dll Injection.pdf

26-11-2011 315 Function Hooking and Windows Dll Injection

foo() is 02114B05 - 011A3518 = 00F715ED bytes long fits an unsigned char[16193005] bar() is 0852AB241

Sisteme de Operare - httpelfcspubrosowiki

Function Hooking and Windows Dll Injection 415 26-11-2011

- 0852AA02 = 00000122 bytes long fits an unsigned char[290]the idea is to inject an unconditional jump at the beginning of foo() jump that will land at the first instruction of bar()2notice the distance between the expected current instruction within foo() at address 011A351D and the landing3zone in bar() address 0852AA02 Were talking about 0852AA02 - 011A351D = 073874E5 bytes acrossthe E9 jump receives an immediate operand that means the operand is within the code and the whole thing eats up 54bytes 1 for the opcode and 4 for the operand Thats why the execution jumps from 011A351D and not directly from thebeginning of foo() at 011A3518

As an observation both statement n and statement m are far rets opcode = CB For the example in the picture theprogram would write E9 E5 74 38 07 just at the beginning of foo()

E9 is the opcode for far jmp A far jmp receives an immediate 32 bit argument

E5 74 38 07 represent - due to endianness - the number 073874E5 the argument

As a rule its better to make sure the new function matches the old one in both calling convention and return value +arguments

Dll Injection

Now why would I go through the lengths of such useless (but fun) trickery I wont answer in this section but its requiredto fully grasp what will followUnder the Windows operating system dll injection refers to executing foreign code in a different process Ever wonderedhow applications such as Fraps4) or RivaTuner5) MSI Aterburner6) manage to display a framerate counter on top of thecurrently running full screen and exclusive mode D3D OpenGL application Or how something like Sockscap7) managesto redirect an applications traffic through the given proxy Read on

While the above applications take advantage of dll injection keep in mind that the global hotkeys functionality fromprograms such as foobar20008) or AutoHotkey9) are implemented by means of a cousin method - via low level keyboardhooks

This is how one would run their code in a parasited process10)

with SetWindowsHookEx() Installing global hooks from dlls defining them is dll injection at work Its an OK method1explained herewith CreateRemoteThread(LoadLibrary()) This is the true dll injection2with WriteProcessMemory(OurThreadProc) CreateRemoteThread(OurThreadProc) This is so much in the true spirit of3dll injection that its not even dll injection anymore its directly code injection

Heres the recipe for setting up a global Windows hook and getting your code into victim process

think of a suitable criteria for example when a window gets created That type of event is called a shell event and1its hookable via SetWindowsHookEx(WH_SHELL ShellProc)write myhookdll that defines and exports the above ShellProc() see some steps below For convenience also2export something like InstallHook() from that dll and within the code add the call to SetWindowsHookEx()write a launcher program that will call once the InstallHook() function defined in our dll and then just wait (if it3unloads probably Windows will also unload the dll unless special measures are taken resulting in crashes)ShellProc() will get called by the system everytime the specific event - a shell event in our case - is to be received by4the application Its code will run in that applications address space

Watch the following picture if you dont believe

httpelfcspubrosowiki Printed on 20111126 0759

26-11-2011 515 Function Hooking and Windows Dll Injection

normally an event is dispatched to the message loop of the receiving thread and the message loop further sends that1message within the thread to a proper handlermyhookdll registers system-wide ShellProc() as an interceptor of shell events (out of which WM_CREATE) Now2the message goes through the code from ShellProc() and only after processing its (not even necessary only becauseIm too kind) forwarded to the shell handler in the original event loop

A Practical Example

I like playing my games in windowed mode Inspired by Media Player Classic Homecinemas11) borderless always on top

Sisteme de Operare - httpelfcspubrosowiki

Function Hooking and Windows Dll Injection 615 26-11-2011

window mode I thought to myself how cool would it be to have any games window borderless and always on top of theother windows A games window usually contains either WS_CAPTION or WS_THICKFRAME window styles Making itborderless is a simple matter of retrieving its style (GetWindowLong(GWL_STYLE)) removing (toggling) by means of XORthe relevant style and then applying the result on the window handle SetWindowLong(GWL_STYLE)

Removing The Window Decorations

As a first attempt I created a simple one-shot console application that targeted the Heroes of Newerth window removingthe WS_CAPTION style as reported by Spy++

Borderless1cppinclude ltcstdiogtusing namespace stdinclude ltwindowshgt int main() bool done = false finish when q is entered while (done) HWND hwnd = FindWindow(NULL TEXT(Heroes of Newerth)) if (NULL = hwnd) LONG styles = GetWindowLong(hwnd GWL_STYLE) if (0 = styles) styles ^= WS_CAPTION LONG result = SetWindowLong(hwnd GWL_STYLE styles) char c scanf(c ampc) if (q == c) done = true return 0

httpelfcspubrosowiki Printed on 20111126 0759

26-11-2011 715 Function Hooking and Windows Dll Injection

You can observe 2 problems in the current approach

the window is now blurry1the mouse hover effect is registered a few pixels off2

The blurriness problem happens because after removing the decorations (titlebar dialog borders) Windows tries tomaintain the program window within the same bounding rectangle In doing so it inflates the client area by a few pixelsin each direction pixels obtained from removing said decorations Indeed counting the pixels from the first picture we geta total window area (including borders) of 1616times858 and a client area (only the Direct3D part from within the borderswhere the application draws its updates) of 1600times820 pixels For the second picture we have a window area equal to theclient area (no more borders) of 1606times848 pixels Since Heroes of Newerth has a dialog frame (non-sizeable) it doesnttreat WM_SIZE messages the Direct3D context keeps rendering at the initial config file resolution and the resulting framebuffer gets drawn with stretching on top of a sligthly different window area so we dont have a perfect (logical)pixel-on-(screen )pixel mapping anymoreNote my config file for the game

snipSetSave vid_resolution 1600820snip

Heres a fix for keeping the client area of the window in place during the style change

Borderless2cppinclude ltcstdiogtusing namespace stdinclude ltwindowshgt int main() bool done = false while (done) HWND hwnd = FindWindow(NULL TEXT(Heroes of Newerth)) if (NULL = hwnd) LONG styles = GetWindowLong(hwnd GWL_STYLE) if (0 = styles) styles ^= WS_CAPTION bool deflate = 0 == (styles amp WS_CAPTION) RECT rc GetWindowRect(hwnd amprc) int captionHeight = GetSystemMetrics(SM_CYCAPTION) int borderWidth = GetSystemMetrics(SM_CXDLGFRAME) int borderHeight = GetSystemMetrics(SM_CYDLGFRAME)

Sisteme de Operare - httpelfcspubrosowiki

Function Hooking and Windows Dll Injection 815 26-11-2011

if (deflate) rcleft += borderWidth rcright -= borderWidth rctop += captionHeight + borderHeight rcbottom -= borderHeight else rcleft -= borderWidth rcright += borderWidth rctop -= captionHeight + borderHeight rcbottom += borderHeight LONG result = SetWindowLong(hwnd GWL_STYLE styles) if (0 = result) SetWindowPos(hwnd NULL rcleft rctop rcright - rcleft rcbottom - rctop SWP_FRAMECHANGED) char c scanf(c ampc) if (q == c) done = true return 0

A process such as Starcraft 2 owns a window with the WS_THICKFRAME style denoting a sizing border If I change the codeto remove that style from the Starcraft 2 main window (also SM_CTHICKFRAME instead of SM_CDLGFRAME I can onlynotice the mouse hover effect being off - the game catches WM_SIZE messages and adjusts the framebuffer accordingly

Fixing The Mouse Behavior

For the broken mouse hover effect its time to put The Injection to use Among the usual suspects for this problem are thewindow rectangle functions GetWindowRect() and GetClientRect() It would make sense due to the fact that games usuallyobtain mouse events through DirectInput that initially mouse coordinates are expressed in desktop-absolute form and notrelative to the application window Therefore theyd have to employ in one form or another a conversion between screen(absolute) coordinates and window coordinates in a similar manner to the operation of ClientToScreen()Lets take a look at an application window and the GetRect() logic relating to it

What the game does when handling mouse input is obtain some absolute screen coordinates from DirectInput convertthem to window coordinates then compensate for the window title and borders and then figure out what to do next with

httpelfcspubrosowiki Printed on 20111126 0759

26-11-2011 915 Function Hooking and Windows Dll Injection

the event Note that after removing the window decorations both GetWindowRect() and GetClientRect() return thesame coordinates Then the game compensates by subtracting the expected widths and heights of borders resulting inslightly off readings for the events The idea here is to modify at run-time GetWindowRect() so that it returns the oldrectangle with titlebar and borders as if the window style still contained those elements

The basic workflow for detouring GetWindowRect() is

insert exactly at the beginning of the function a jmp to our GetWindowRect() hot patch it1in our GetWindowRect() restore the code of the original function2call the original function and save the result3modify that result so that it fits our agenda4hot patch GetWindowRect() again5return the now modified result6

32 Bit Versus 64 Bit

Special care should be taken when moving to x86-64

Hot Patching

While the previous approach for hot patching a function (via relative jmp) is generally OK even in 64 bit mode there couldbe rare occasions when the distance between the patched function and the original one cant be expressed on only 32 bitsSince the specific form of jmp used expects a 32 bit displacement it would be useless in this case

The suggested solution here is a 64 bit absolute jump which comes by default with x86-6412) The idea here is just slightlydifferent than in the case of plain x86 While jmp accepted there as argument an immediate displacement the x86-64 longjump functions through an indirect register So wed simply load the destination address (not a distance any more for thisinstruction) into a register and pass that register as the operand to the jmp Fortunately x86-64 states that the special64-bit registries r10 and r11 arent preserved between call opcodes so picking r11 is a safe bet and guaranteed not toruin the program flow

Dll Injection

One cant insert an image compiled for 32 bits inside a 64 bit process and cant inject a 64 bit dll inside a 32 bit processThe idea is to have 2 separate programs making the dll injection 2 versions of the dll each of them for 64 bits andrespectively for 32 bits The 32 bit injector should set up the hooks as usual and launch a light weight version of itself thatonly sets up the hook and waits for an end event

Loader

TCHAR path[MAX_PATH] DWORD len = GetModuleFileName(NULL path MAX_PATH) while (path[len - 1] = ) --len MoveMemory(path + len TEXT(Deframe64dat) sizeof(TCHAR) (lstrlen(TEXT(Deframe64dat)) + 1)) STARTUPINFO siDeframe64 = sizeof(STARTUPINFO) PROCESS_INFORMATION piDeframe64 BOOL bRes = CreateProcess(0 path NULL NULL TRUE 0 NULL NULL ampsiDeframe64 amppiDeframe64) if (bRes) WaitForInputIdle(piDeframe64hProcess INFINITE) InstallHook()

Deframe64cppinclude ltwindowshgtinclude DeframeHelperh int WINAPI WinMain(HINSTANCE hInstance HINSTANCE hPrevInstance LPSTR lpCmdLine int nCmdShow) InstallHook() main message loop MSG msg while (GetMessage(ampmsg NULL 0 0) ampamp WM_QUIT = msgmessage) TranslateMessage(ampmsg) DispatchMessage(ampmsg)

Sisteme de Operare - httpelfcspubrosowiki

Function Hooking and Windows Dll Injection 1015 26-11-2011

RemoveHook() return static_castltintgt(msgwParam)

The first fragment of code residing in the normal 32 bit injector process first spawns a 64 bit child our Deframe64datThey both perform the same main function at this stage - calling InstallHook() which is exported by the guest dll Ivemessed with the output of Deframe64 so that it has the extension dat this is only an aesthetic step so that the userdoesnt accidentally launch the useless and with no means of terminating 64 bit process On 32 bit systemsCreateProcess() will fail and I simply ignore everything involving itHeres how the 32 bit injector terminates the 64 bit one

if (bRes) PostThreadMessage(piDeframe64dwThreadId WM_QUIT 0 0)

The Visual Studio 2010 Solution

All the required code can be found here Note that the project files wont work with the Express version of Visual Studiodue to the main program - Deframe being written with MFCFor a binary build see this archiveThe solution uses a C-like approach for the Injection

A C++ Template Library (for the impatient)

This code is not for the faint of heart C++ 2003 (talking about Microsoft Visual C 2010 here variadic template support)template code to simplify the hotpatching Include it and use it as exemplified further below (its not included in the sourcedownload)

HotPatchhpppragma once include ltwindowshgt HotPatch is a thin wrapper on top of the function hot patching layer It encapsulates a way to replace known functions with own functions by means of patching in jmps in both x86and x86-64 The basic workflow is 1 Declare HotPatchfunctionltftypegt thePatch assign target to this object with thePatch = target 2 set a replacement callback with thePatchSetPatch(myTarget) 3 call thePatchApply() to replace the target with the other callback In the replacement procedure

httpelfcspubrosowiki Printed on 20111126 0759

26-11-2011 1115 Function Hooking and Windows Dll Injection

31 do your stuff 32 call thePatch(arguments) 33 do other stuff When done 4 restore the opcodes with thePatchRemovePatch() 5 the destructor or assigning a new function to thePatch will restore the protection status of the memoryreferred by target Limitations wont work with variadic functions (blame C)namespace HotPatch class Exception class MemoryException public Exception class PatchException public Exception template lttypename FTypegt class function_impl public function_impl() _pFun(NULL) _pPatch(NULL) _detoured(false) ~function_impl() _RestoreProtection() res = function_implltFTypegtIsPatched() tells whether a call to the target will run the target or thehook Return value bool res - true if ApplyPatch() has been called without an accompanying RemovePatch() bool IsPatched() return _detoured function_implltFTypegtoperator=(pFun) directs the patch to a target and prepares the target memory forwrites Parameters FType pFun - the function to patch (see Apply()) Throws MemoryException - when changing the protection of the page where pFun points is impossible void operator=(FType pFun) _RestoreProtection() _pFun = pFun if (NULL == _pFun) return BOOL res = VirtualProtect(_pFun _64bit _PATCH_LENGTH64 _PATCH_LENGTH32 PAGE_EXECUTE_READWRITEamp_oldProtection) if (res) throw MemoryException() function_implltFTypegtSetPatch(patch[ alwaysUse32Bit]) prepares internal state for the patch Parameters FType patch - the patch to use instead of pFun (see operator=(FType )) bool alwaysUse32Bit - If true a 32 bit jmp is always inserted Else the best jmp is determined based on necessities (can still be 32 bit if it fits) Throws PatchException - if patch is NULL void SetPatch(FType patch bool alwaysUse32Bit = false) if (NULL == patch) throw PatchException() if (NULL = _pPatch) RemovePatch() _pPatch = patch _64bit = alwaysUse32Bit they havent expressed mandatory 32 bit only path try to guess the best path

Sisteme de Operare - httpelfcspubrosowiki

Function Hooking and Windows Dll Injection 1215 26-11-2011

if (_64bit) LONGLONG jumpDistance = reinterpret_castltLONGLONGgt(_pPatch) - reinterpret_castltLONGLONGgt(_pFun) - _PATCH_LENGTH32 if (abs(jumpDistance) gt 0x7FFFFFFF) the jump is too long to fit a regular 32 bit relative jmp _64bit = true else _64bit = false save the old patch opcodes plain old for is faster DO NOT call any library functions for (SIZE_T i = 0 i lt (_64bit _PATCH_LENGTH64 _PATCH_LENGTH32) ++i) (_backup + i) = (reinterpret_castltPBYTEgt(_pFun) + i) function_implltFTypegtApplyPatch() makes pFun (see operator=(FType )) jmp to patch (seeSetPatch(FType bool)) This is the actual hot patch mechanism at work void ApplyPatch() if (_64bit) movabs reinterpret_castltPBYTEgt(_pFun) = _OP_MOVABS r11 (reinterpret_castltPBYTEgt(_pFun) + 1) = _R11_WRITE _detourProc reinterpret_castltPLONGLONGgt(reinterpret_castltPBYTEgt(_pFun) + 2) =reinterpret_castltLONGLONGgt(_pPatch) jmp reinterpret_castltPWORDgt(reinterpret_castltPBYTEgt(_pFun) + 10) = _OP_JMP64 abs r11 (reinterpret_castltPBYTEgt(_pFun) + 12) = _R11_JMP else jmp reinterpret_castltPBYTEgt(_pFun) = _OP_JMP32 distance left to _detourProc reinterpret_castltPDWORDgt(reinterpret_castltPBYTEgt(_pFun) + 1) = static_castltDWORDgt( reinterpret_castltPBYTEgt(_pPatch) - reinterpret_castltPBYTEgt(_pFun) - static_castltDWORDgt(_PATCH_LENGTH32)) _detoured = true function_implltFTypegtRemovePatch() undoes what ApplyPatch() did pFun (see operator=(FType )) willbe its old self again void RemovePatch() plain old for is faster DO NOT call any library functions for (SIZE_T i = 0 i lt (_64bit _PATCH_LENGTH64 _PATCH_LENGTH32) ++i) (reinterpret_castltPBYTEgt(_pFun) + i) = (_backup + i) _detoured = false protected FType _pFun FType _pPatch bool _64bit bool _detoured BYTE _backup[13] DWORD _oldProtection static const BYTE _OP_JMP32 = 0xE9 static const WORD _OP_JMP64 = 0xFF41 static const BYTE _OP_MOVABS = 0x49 static const BYTE _R11_WRITE = 0xBB static const BYTE _R11_JMP = 0xE3 static const SIZE_T _PATCH_LENGTH32 = 5 jmp detourProc - originalProc = 1 + 4 static const SIZE_T _PATCH_LENGTH64 = 13 movabs R11 detourProc (64 bit) jmp (abs 64) R11 = 1+ 1 + 8 + 2 + 1 template lttypename Tgt static T abs(T val) return val gt 0 val -val

httpelfcspubrosowiki Printed on 20111126 0759

26-11-2011 1315 Function Hooking and Windows Dll Injection

void _RestoreProtection() if (NULL == _pFun) return DWORD unusedOldProtection BOOL res = VirtualProtect(_pFun _64bit _PATCH_LENGTH64 _PATCH_LENGTH32 _oldProtectionampunusedOldProtection) (void) res nothing to do template lttypename FTypegt class _NativeCallGuard public _NativeCallGuard(function_implltFTypegt ampfun) _fun(fun) _funRemovePatch() ~_NativeCallGuard() _funApplyPatch() private function_implltFTypegt amp_fun template lttypenamegt class function define HP_TARG0define HP_TARG1 typename Arg1define HP_TARG2 HP_TARG1 typename Arg2define HP_TARG3 HP_TARG2 typename Arg3define HP_TARG4 HP_TARG3 typename Arg4define HP_TARG5 HP_TARG4 typename Arg5define HP_TARG6 HP_TARG5 typename Arg6define HP_TARG7 HP_TARG6 typename Arg7define HP_TARG8 HP_TARG7 typename Arg8define HP_TARG9 HP_TARG8 typename Arg9define HP_TARG10 HP_TARG9 typename Arg10define HP_FARG0define HP_FARG1 Arg1define HP_FARG2 HP_FARG1 Arg2define HP_FARG3 HP_FARG2 Arg3define HP_FARG4 HP_FARG3 Arg4define HP_FARG5 HP_FARG4 Arg5define HP_FARG6 HP_FARG5 Arg6define HP_FARG7 HP_FARG6 Arg7define HP_FARG8 HP_FARG7 Arg8define HP_FARG9 HP_FARG8 Arg9define HP_FARG10 HP_FARG9 Arg10define HP_ARG0define HP_ARG1 arg1define HP_ARG2 HP_ARG1 arg2define HP_ARG3 HP_ARG2 arg3define HP_ARG4 HP_ARG3 arg4define HP_ARG5 HP_ARG4 arg5define HP_ARG6 HP_ARG5 arg6define HP_ARG7 HP_ARG6 arg7define HP_ARG8 HP_ARG7 arg8define HP_ARG9 HP_ARG8 arg9define HP_ARG10 HP_ARG9 arg10define HP_ARG_DECL0define HP_ARG_DECL1 Arg1 arg1define HP_ARG_DECL2 HP_ARG_DECL1 Arg2 arg2define HP_ARG_DECL3 HP_ARG_DECL2 Arg3 arg3define HP_ARG_DECL4 HP_ARG_DECL3 Arg4 arg4define HP_ARG_DECL5 HP_ARG_DECL4 Arg5 arg5define HP_ARG_DECL6 HP_ARG_DECL5 Arg6 arg6define HP_ARG_DECL7 HP_ARG_DECL6 Arg7 arg7define HP_ARG_DECL8 HP_ARG_DECL7 Arg8 arg8define HP_ARG_DECL9 HP_ARG_DECL8 Arg9 arg9define HP_ARG_DECL10 HP_ARG_DECL9 Arg10 arg10 template partial specialization for functionltreturn_type([arg_types])gtdefine HP_RET_FUNCTION(n callconv) template lttypename _Ret HP_TARGngt class functionlt_Ret callconv(HP_FARGn)gt public function_impllt_Ret callconv(HP_FARGn)gt

Sisteme de Operare - httpelfcspubrosowiki

Function Hooking and Windows Dll Injection 1415 26-11-2011

private typedef _Ret callconv type(HP_FARGn) public ~functionlttypegt() _RestoreProtection() using function_impllttypegtoperator= _Ret operator()(HP_ARG_DECLn) _NativeCallGuardlttypegt CallGuard(this) return (_pFun)(HP_ARGn) protected using function_impllttypegt_pFun declare the 11 templates handling functions in the form _Ret function() _Ret function(Arg1) _Ret function(Arg1 Arg2) _Ret function(Arg1 Arg2 Arg10) HP_RET_FUNCTION(0 __cdecl) HP_RET_FUNCTION(1 __cdecl) HP_RET_FUNCTION(2 __cdecl) HP_RET_FUNCTION(3 __cdecl) HP_RET_FUNCTION(4 __cdecl) HP_RET_FUNCTION(5 __cdecl) HP_RET_FUNCTION(6 __cdecl) HP_RET_FUNCTION(7 __cdecl) HP_RET_FUNCTION(8 __cdecl) HP_RET_FUNCTION(9 __cdecl) HP_RET_FUNCTION(10 __cdecl) ifndef _M_X64 HP_RET_FUNCTION(0 __stdcall) HP_RET_FUNCTION(1 __stdcall) HP_RET_FUNCTION(2 __stdcall) HP_RET_FUNCTION(3 __stdcall) HP_RET_FUNCTION(4 __stdcall) HP_RET_FUNCTION(5 __stdcall) HP_RET_FUNCTION(6 __stdcall) HP_RET_FUNCTION(7 __stdcall) HP_RET_FUNCTION(8 __stdcall) HP_RET_FUNCTION(9 __stdcall) HP_RET_FUNCTION(10 __stdcall)endif namespace HotPatch

What Im doing above is generating 11 partial tempate specializations for class HotPatchfunction The class isinspired by C++2011s stdfunction Its a class that models functions with up to 10 (included) arguments - you cansee the declarations through the HP_RET_FUNCTION macro calls in there Then another set of 11 declarations for x86-64where only calling convention __cdecl exists Do not worry abut understanding the above code its ugly and it sucksFocus on the usage instead it gets things done (for up to 10 arguments that is)

To use this HotPatch mini-lib write something like

HotPatchTestcppinclude ltcstdiogtinclude HotPatchhppusing namespace stdusing namespace HotPatch functionltvoid()gt fooPatch void foo() printf(In foo()n) void bar()

httpelfcspubrosowiki Printed on 20111126 0759

26-11-2011 1515 Function Hooking and Windows Dll Injection

printf(Im hackin ur functionn) if (fooPatchIsPatched()) fooPatch() int main() void (pfoo)() = foo void (pbar)() = bar pfoo() calls foo() pbar() calls bar() fooPatch = foo fooPatchSetPatch(bar) fooPatchApplyPatch() pfoo() calls bar() pbar() calls bar() fooPatchRemovePatch() pfoo() calls foo() pbar() calls bar() return 0

Further Info and Support

Im usually idling under the handle foxx1337 on ircfreenodenet on rosedu1) httpwwwkernelorgdocman-pagesonlinepagesman8ld-linuxso8html LD_PRELOAD2) httpsupportmicrosoftcomkb197571 AppInit_DLLs registry hack3) httpyosefkcomc++fqafunctionhtml4) Fraps5) RivaTuner6) MSI Afterburner7) Sockscap8) foobar20009) AutoHotkey10) Code Project Article on Code Injection11) Media Player Classic Homecinema12) httpcontinuationswordpresscom20110510hot-patching-unconditional-jumps-x86-x86-64 Article on 64 bit hotpatching

Fromhttpelfcspubrosowiki - Sisteme de Operare

Permanent linkhttpelfcspubrosowikilaboratoareresurseinjections

Last update 20111108 0213

Sisteme de Operare - httpelfcspubrosowiki

Page 4: Function Hooking and Windows Dll Injection.pdf

Function Hooking and Windows Dll Injection 415 26-11-2011

- 0852AA02 = 00000122 bytes long fits an unsigned char[290]the idea is to inject an unconditional jump at the beginning of foo() jump that will land at the first instruction of bar()2notice the distance between the expected current instruction within foo() at address 011A351D and the landing3zone in bar() address 0852AA02 Were talking about 0852AA02 - 011A351D = 073874E5 bytes acrossthe E9 jump receives an immediate operand that means the operand is within the code and the whole thing eats up 54bytes 1 for the opcode and 4 for the operand Thats why the execution jumps from 011A351D and not directly from thebeginning of foo() at 011A3518

As an observation both statement n and statement m are far rets opcode = CB For the example in the picture theprogram would write E9 E5 74 38 07 just at the beginning of foo()

E9 is the opcode for far jmp A far jmp receives an immediate 32 bit argument

E5 74 38 07 represent - due to endianness - the number 073874E5 the argument

As a rule its better to make sure the new function matches the old one in both calling convention and return value +arguments

Dll Injection

Now why would I go through the lengths of such useless (but fun) trickery I wont answer in this section but its requiredto fully grasp what will followUnder the Windows operating system dll injection refers to executing foreign code in a different process Ever wonderedhow applications such as Fraps4) or RivaTuner5) MSI Aterburner6) manage to display a framerate counter on top of thecurrently running full screen and exclusive mode D3D OpenGL application Or how something like Sockscap7) managesto redirect an applications traffic through the given proxy Read on

While the above applications take advantage of dll injection keep in mind that the global hotkeys functionality fromprograms such as foobar20008) or AutoHotkey9) are implemented by means of a cousin method - via low level keyboardhooks

This is how one would run their code in a parasited process10)

with SetWindowsHookEx() Installing global hooks from dlls defining them is dll injection at work Its an OK method1explained herewith CreateRemoteThread(LoadLibrary()) This is the true dll injection2with WriteProcessMemory(OurThreadProc) CreateRemoteThread(OurThreadProc) This is so much in the true spirit of3dll injection that its not even dll injection anymore its directly code injection

Heres the recipe for setting up a global Windows hook and getting your code into victim process

think of a suitable criteria for example when a window gets created That type of event is called a shell event and1its hookable via SetWindowsHookEx(WH_SHELL ShellProc)write myhookdll that defines and exports the above ShellProc() see some steps below For convenience also2export something like InstallHook() from that dll and within the code add the call to SetWindowsHookEx()write a launcher program that will call once the InstallHook() function defined in our dll and then just wait (if it3unloads probably Windows will also unload the dll unless special measures are taken resulting in crashes)ShellProc() will get called by the system everytime the specific event - a shell event in our case - is to be received by4the application Its code will run in that applications address space

Watch the following picture if you dont believe

httpelfcspubrosowiki Printed on 20111126 0759

26-11-2011 515 Function Hooking and Windows Dll Injection

normally an event is dispatched to the message loop of the receiving thread and the message loop further sends that1message within the thread to a proper handlermyhookdll registers system-wide ShellProc() as an interceptor of shell events (out of which WM_CREATE) Now2the message goes through the code from ShellProc() and only after processing its (not even necessary only becauseIm too kind) forwarded to the shell handler in the original event loop

A Practical Example

I like playing my games in windowed mode Inspired by Media Player Classic Homecinemas11) borderless always on top

Sisteme de Operare - httpelfcspubrosowiki

Function Hooking and Windows Dll Injection 615 26-11-2011

window mode I thought to myself how cool would it be to have any games window borderless and always on top of theother windows A games window usually contains either WS_CAPTION or WS_THICKFRAME window styles Making itborderless is a simple matter of retrieving its style (GetWindowLong(GWL_STYLE)) removing (toggling) by means of XORthe relevant style and then applying the result on the window handle SetWindowLong(GWL_STYLE)

Removing The Window Decorations

As a first attempt I created a simple one-shot console application that targeted the Heroes of Newerth window removingthe WS_CAPTION style as reported by Spy++

Borderless1cppinclude ltcstdiogtusing namespace stdinclude ltwindowshgt int main() bool done = false finish when q is entered while (done) HWND hwnd = FindWindow(NULL TEXT(Heroes of Newerth)) if (NULL = hwnd) LONG styles = GetWindowLong(hwnd GWL_STYLE) if (0 = styles) styles ^= WS_CAPTION LONG result = SetWindowLong(hwnd GWL_STYLE styles) char c scanf(c ampc) if (q == c) done = true return 0

httpelfcspubrosowiki Printed on 20111126 0759

26-11-2011 715 Function Hooking and Windows Dll Injection

You can observe 2 problems in the current approach

the window is now blurry1the mouse hover effect is registered a few pixels off2

The blurriness problem happens because after removing the decorations (titlebar dialog borders) Windows tries tomaintain the program window within the same bounding rectangle In doing so it inflates the client area by a few pixelsin each direction pixels obtained from removing said decorations Indeed counting the pixels from the first picture we geta total window area (including borders) of 1616times858 and a client area (only the Direct3D part from within the borderswhere the application draws its updates) of 1600times820 pixels For the second picture we have a window area equal to theclient area (no more borders) of 1606times848 pixels Since Heroes of Newerth has a dialog frame (non-sizeable) it doesnttreat WM_SIZE messages the Direct3D context keeps rendering at the initial config file resolution and the resulting framebuffer gets drawn with stretching on top of a sligthly different window area so we dont have a perfect (logical)pixel-on-(screen )pixel mapping anymoreNote my config file for the game

snipSetSave vid_resolution 1600820snip

Heres a fix for keeping the client area of the window in place during the style change

Borderless2cppinclude ltcstdiogtusing namespace stdinclude ltwindowshgt int main() bool done = false while (done) HWND hwnd = FindWindow(NULL TEXT(Heroes of Newerth)) if (NULL = hwnd) LONG styles = GetWindowLong(hwnd GWL_STYLE) if (0 = styles) styles ^= WS_CAPTION bool deflate = 0 == (styles amp WS_CAPTION) RECT rc GetWindowRect(hwnd amprc) int captionHeight = GetSystemMetrics(SM_CYCAPTION) int borderWidth = GetSystemMetrics(SM_CXDLGFRAME) int borderHeight = GetSystemMetrics(SM_CYDLGFRAME)

Sisteme de Operare - httpelfcspubrosowiki

Function Hooking and Windows Dll Injection 815 26-11-2011

if (deflate) rcleft += borderWidth rcright -= borderWidth rctop += captionHeight + borderHeight rcbottom -= borderHeight else rcleft -= borderWidth rcright += borderWidth rctop -= captionHeight + borderHeight rcbottom += borderHeight LONG result = SetWindowLong(hwnd GWL_STYLE styles) if (0 = result) SetWindowPos(hwnd NULL rcleft rctop rcright - rcleft rcbottom - rctop SWP_FRAMECHANGED) char c scanf(c ampc) if (q == c) done = true return 0

A process such as Starcraft 2 owns a window with the WS_THICKFRAME style denoting a sizing border If I change the codeto remove that style from the Starcraft 2 main window (also SM_CTHICKFRAME instead of SM_CDLGFRAME I can onlynotice the mouse hover effect being off - the game catches WM_SIZE messages and adjusts the framebuffer accordingly

Fixing The Mouse Behavior

For the broken mouse hover effect its time to put The Injection to use Among the usual suspects for this problem are thewindow rectangle functions GetWindowRect() and GetClientRect() It would make sense due to the fact that games usuallyobtain mouse events through DirectInput that initially mouse coordinates are expressed in desktop-absolute form and notrelative to the application window Therefore theyd have to employ in one form or another a conversion between screen(absolute) coordinates and window coordinates in a similar manner to the operation of ClientToScreen()Lets take a look at an application window and the GetRect() logic relating to it

What the game does when handling mouse input is obtain some absolute screen coordinates from DirectInput convertthem to window coordinates then compensate for the window title and borders and then figure out what to do next with

httpelfcspubrosowiki Printed on 20111126 0759

26-11-2011 915 Function Hooking and Windows Dll Injection

the event Note that after removing the window decorations both GetWindowRect() and GetClientRect() return thesame coordinates Then the game compensates by subtracting the expected widths and heights of borders resulting inslightly off readings for the events The idea here is to modify at run-time GetWindowRect() so that it returns the oldrectangle with titlebar and borders as if the window style still contained those elements

The basic workflow for detouring GetWindowRect() is

insert exactly at the beginning of the function a jmp to our GetWindowRect() hot patch it1in our GetWindowRect() restore the code of the original function2call the original function and save the result3modify that result so that it fits our agenda4hot patch GetWindowRect() again5return the now modified result6

32 Bit Versus 64 Bit

Special care should be taken when moving to x86-64

Hot Patching

While the previous approach for hot patching a function (via relative jmp) is generally OK even in 64 bit mode there couldbe rare occasions when the distance between the patched function and the original one cant be expressed on only 32 bitsSince the specific form of jmp used expects a 32 bit displacement it would be useless in this case

The suggested solution here is a 64 bit absolute jump which comes by default with x86-6412) The idea here is just slightlydifferent than in the case of plain x86 While jmp accepted there as argument an immediate displacement the x86-64 longjump functions through an indirect register So wed simply load the destination address (not a distance any more for thisinstruction) into a register and pass that register as the operand to the jmp Fortunately x86-64 states that the special64-bit registries r10 and r11 arent preserved between call opcodes so picking r11 is a safe bet and guaranteed not toruin the program flow

Dll Injection

One cant insert an image compiled for 32 bits inside a 64 bit process and cant inject a 64 bit dll inside a 32 bit processThe idea is to have 2 separate programs making the dll injection 2 versions of the dll each of them for 64 bits andrespectively for 32 bits The 32 bit injector should set up the hooks as usual and launch a light weight version of itself thatonly sets up the hook and waits for an end event

Loader

TCHAR path[MAX_PATH] DWORD len = GetModuleFileName(NULL path MAX_PATH) while (path[len - 1] = ) --len MoveMemory(path + len TEXT(Deframe64dat) sizeof(TCHAR) (lstrlen(TEXT(Deframe64dat)) + 1)) STARTUPINFO siDeframe64 = sizeof(STARTUPINFO) PROCESS_INFORMATION piDeframe64 BOOL bRes = CreateProcess(0 path NULL NULL TRUE 0 NULL NULL ampsiDeframe64 amppiDeframe64) if (bRes) WaitForInputIdle(piDeframe64hProcess INFINITE) InstallHook()

Deframe64cppinclude ltwindowshgtinclude DeframeHelperh int WINAPI WinMain(HINSTANCE hInstance HINSTANCE hPrevInstance LPSTR lpCmdLine int nCmdShow) InstallHook() main message loop MSG msg while (GetMessage(ampmsg NULL 0 0) ampamp WM_QUIT = msgmessage) TranslateMessage(ampmsg) DispatchMessage(ampmsg)

Sisteme de Operare - httpelfcspubrosowiki

Function Hooking and Windows Dll Injection 1015 26-11-2011

RemoveHook() return static_castltintgt(msgwParam)

The first fragment of code residing in the normal 32 bit injector process first spawns a 64 bit child our Deframe64datThey both perform the same main function at this stage - calling InstallHook() which is exported by the guest dll Ivemessed with the output of Deframe64 so that it has the extension dat this is only an aesthetic step so that the userdoesnt accidentally launch the useless and with no means of terminating 64 bit process On 32 bit systemsCreateProcess() will fail and I simply ignore everything involving itHeres how the 32 bit injector terminates the 64 bit one

if (bRes) PostThreadMessage(piDeframe64dwThreadId WM_QUIT 0 0)

The Visual Studio 2010 Solution

All the required code can be found here Note that the project files wont work with the Express version of Visual Studiodue to the main program - Deframe being written with MFCFor a binary build see this archiveThe solution uses a C-like approach for the Injection

A C++ Template Library (for the impatient)

This code is not for the faint of heart C++ 2003 (talking about Microsoft Visual C 2010 here variadic template support)template code to simplify the hotpatching Include it and use it as exemplified further below (its not included in the sourcedownload)

HotPatchhpppragma once include ltwindowshgt HotPatch is a thin wrapper on top of the function hot patching layer It encapsulates a way to replace known functions with own functions by means of patching in jmps in both x86and x86-64 The basic workflow is 1 Declare HotPatchfunctionltftypegt thePatch assign target to this object with thePatch = target 2 set a replacement callback with thePatchSetPatch(myTarget) 3 call thePatchApply() to replace the target with the other callback In the replacement procedure

httpelfcspubrosowiki Printed on 20111126 0759

26-11-2011 1115 Function Hooking and Windows Dll Injection

31 do your stuff 32 call thePatch(arguments) 33 do other stuff When done 4 restore the opcodes with thePatchRemovePatch() 5 the destructor or assigning a new function to thePatch will restore the protection status of the memoryreferred by target Limitations wont work with variadic functions (blame C)namespace HotPatch class Exception class MemoryException public Exception class PatchException public Exception template lttypename FTypegt class function_impl public function_impl() _pFun(NULL) _pPatch(NULL) _detoured(false) ~function_impl() _RestoreProtection() res = function_implltFTypegtIsPatched() tells whether a call to the target will run the target or thehook Return value bool res - true if ApplyPatch() has been called without an accompanying RemovePatch() bool IsPatched() return _detoured function_implltFTypegtoperator=(pFun) directs the patch to a target and prepares the target memory forwrites Parameters FType pFun - the function to patch (see Apply()) Throws MemoryException - when changing the protection of the page where pFun points is impossible void operator=(FType pFun) _RestoreProtection() _pFun = pFun if (NULL == _pFun) return BOOL res = VirtualProtect(_pFun _64bit _PATCH_LENGTH64 _PATCH_LENGTH32 PAGE_EXECUTE_READWRITEamp_oldProtection) if (res) throw MemoryException() function_implltFTypegtSetPatch(patch[ alwaysUse32Bit]) prepares internal state for the patch Parameters FType patch - the patch to use instead of pFun (see operator=(FType )) bool alwaysUse32Bit - If true a 32 bit jmp is always inserted Else the best jmp is determined based on necessities (can still be 32 bit if it fits) Throws PatchException - if patch is NULL void SetPatch(FType patch bool alwaysUse32Bit = false) if (NULL == patch) throw PatchException() if (NULL = _pPatch) RemovePatch() _pPatch = patch _64bit = alwaysUse32Bit they havent expressed mandatory 32 bit only path try to guess the best path

Sisteme de Operare - httpelfcspubrosowiki

Function Hooking and Windows Dll Injection 1215 26-11-2011

if (_64bit) LONGLONG jumpDistance = reinterpret_castltLONGLONGgt(_pPatch) - reinterpret_castltLONGLONGgt(_pFun) - _PATCH_LENGTH32 if (abs(jumpDistance) gt 0x7FFFFFFF) the jump is too long to fit a regular 32 bit relative jmp _64bit = true else _64bit = false save the old patch opcodes plain old for is faster DO NOT call any library functions for (SIZE_T i = 0 i lt (_64bit _PATCH_LENGTH64 _PATCH_LENGTH32) ++i) (_backup + i) = (reinterpret_castltPBYTEgt(_pFun) + i) function_implltFTypegtApplyPatch() makes pFun (see operator=(FType )) jmp to patch (seeSetPatch(FType bool)) This is the actual hot patch mechanism at work void ApplyPatch() if (_64bit) movabs reinterpret_castltPBYTEgt(_pFun) = _OP_MOVABS r11 (reinterpret_castltPBYTEgt(_pFun) + 1) = _R11_WRITE _detourProc reinterpret_castltPLONGLONGgt(reinterpret_castltPBYTEgt(_pFun) + 2) =reinterpret_castltLONGLONGgt(_pPatch) jmp reinterpret_castltPWORDgt(reinterpret_castltPBYTEgt(_pFun) + 10) = _OP_JMP64 abs r11 (reinterpret_castltPBYTEgt(_pFun) + 12) = _R11_JMP else jmp reinterpret_castltPBYTEgt(_pFun) = _OP_JMP32 distance left to _detourProc reinterpret_castltPDWORDgt(reinterpret_castltPBYTEgt(_pFun) + 1) = static_castltDWORDgt( reinterpret_castltPBYTEgt(_pPatch) - reinterpret_castltPBYTEgt(_pFun) - static_castltDWORDgt(_PATCH_LENGTH32)) _detoured = true function_implltFTypegtRemovePatch() undoes what ApplyPatch() did pFun (see operator=(FType )) willbe its old self again void RemovePatch() plain old for is faster DO NOT call any library functions for (SIZE_T i = 0 i lt (_64bit _PATCH_LENGTH64 _PATCH_LENGTH32) ++i) (reinterpret_castltPBYTEgt(_pFun) + i) = (_backup + i) _detoured = false protected FType _pFun FType _pPatch bool _64bit bool _detoured BYTE _backup[13] DWORD _oldProtection static const BYTE _OP_JMP32 = 0xE9 static const WORD _OP_JMP64 = 0xFF41 static const BYTE _OP_MOVABS = 0x49 static const BYTE _R11_WRITE = 0xBB static const BYTE _R11_JMP = 0xE3 static const SIZE_T _PATCH_LENGTH32 = 5 jmp detourProc - originalProc = 1 + 4 static const SIZE_T _PATCH_LENGTH64 = 13 movabs R11 detourProc (64 bit) jmp (abs 64) R11 = 1+ 1 + 8 + 2 + 1 template lttypename Tgt static T abs(T val) return val gt 0 val -val

httpelfcspubrosowiki Printed on 20111126 0759

26-11-2011 1315 Function Hooking and Windows Dll Injection

void _RestoreProtection() if (NULL == _pFun) return DWORD unusedOldProtection BOOL res = VirtualProtect(_pFun _64bit _PATCH_LENGTH64 _PATCH_LENGTH32 _oldProtectionampunusedOldProtection) (void) res nothing to do template lttypename FTypegt class _NativeCallGuard public _NativeCallGuard(function_implltFTypegt ampfun) _fun(fun) _funRemovePatch() ~_NativeCallGuard() _funApplyPatch() private function_implltFTypegt amp_fun template lttypenamegt class function define HP_TARG0define HP_TARG1 typename Arg1define HP_TARG2 HP_TARG1 typename Arg2define HP_TARG3 HP_TARG2 typename Arg3define HP_TARG4 HP_TARG3 typename Arg4define HP_TARG5 HP_TARG4 typename Arg5define HP_TARG6 HP_TARG5 typename Arg6define HP_TARG7 HP_TARG6 typename Arg7define HP_TARG8 HP_TARG7 typename Arg8define HP_TARG9 HP_TARG8 typename Arg9define HP_TARG10 HP_TARG9 typename Arg10define HP_FARG0define HP_FARG1 Arg1define HP_FARG2 HP_FARG1 Arg2define HP_FARG3 HP_FARG2 Arg3define HP_FARG4 HP_FARG3 Arg4define HP_FARG5 HP_FARG4 Arg5define HP_FARG6 HP_FARG5 Arg6define HP_FARG7 HP_FARG6 Arg7define HP_FARG8 HP_FARG7 Arg8define HP_FARG9 HP_FARG8 Arg9define HP_FARG10 HP_FARG9 Arg10define HP_ARG0define HP_ARG1 arg1define HP_ARG2 HP_ARG1 arg2define HP_ARG3 HP_ARG2 arg3define HP_ARG4 HP_ARG3 arg4define HP_ARG5 HP_ARG4 arg5define HP_ARG6 HP_ARG5 arg6define HP_ARG7 HP_ARG6 arg7define HP_ARG8 HP_ARG7 arg8define HP_ARG9 HP_ARG8 arg9define HP_ARG10 HP_ARG9 arg10define HP_ARG_DECL0define HP_ARG_DECL1 Arg1 arg1define HP_ARG_DECL2 HP_ARG_DECL1 Arg2 arg2define HP_ARG_DECL3 HP_ARG_DECL2 Arg3 arg3define HP_ARG_DECL4 HP_ARG_DECL3 Arg4 arg4define HP_ARG_DECL5 HP_ARG_DECL4 Arg5 arg5define HP_ARG_DECL6 HP_ARG_DECL5 Arg6 arg6define HP_ARG_DECL7 HP_ARG_DECL6 Arg7 arg7define HP_ARG_DECL8 HP_ARG_DECL7 Arg8 arg8define HP_ARG_DECL9 HP_ARG_DECL8 Arg9 arg9define HP_ARG_DECL10 HP_ARG_DECL9 Arg10 arg10 template partial specialization for functionltreturn_type([arg_types])gtdefine HP_RET_FUNCTION(n callconv) template lttypename _Ret HP_TARGngt class functionlt_Ret callconv(HP_FARGn)gt public function_impllt_Ret callconv(HP_FARGn)gt

Sisteme de Operare - httpelfcspubrosowiki

Function Hooking and Windows Dll Injection 1415 26-11-2011

private typedef _Ret callconv type(HP_FARGn) public ~functionlttypegt() _RestoreProtection() using function_impllttypegtoperator= _Ret operator()(HP_ARG_DECLn) _NativeCallGuardlttypegt CallGuard(this) return (_pFun)(HP_ARGn) protected using function_impllttypegt_pFun declare the 11 templates handling functions in the form _Ret function() _Ret function(Arg1) _Ret function(Arg1 Arg2) _Ret function(Arg1 Arg2 Arg10) HP_RET_FUNCTION(0 __cdecl) HP_RET_FUNCTION(1 __cdecl) HP_RET_FUNCTION(2 __cdecl) HP_RET_FUNCTION(3 __cdecl) HP_RET_FUNCTION(4 __cdecl) HP_RET_FUNCTION(5 __cdecl) HP_RET_FUNCTION(6 __cdecl) HP_RET_FUNCTION(7 __cdecl) HP_RET_FUNCTION(8 __cdecl) HP_RET_FUNCTION(9 __cdecl) HP_RET_FUNCTION(10 __cdecl) ifndef _M_X64 HP_RET_FUNCTION(0 __stdcall) HP_RET_FUNCTION(1 __stdcall) HP_RET_FUNCTION(2 __stdcall) HP_RET_FUNCTION(3 __stdcall) HP_RET_FUNCTION(4 __stdcall) HP_RET_FUNCTION(5 __stdcall) HP_RET_FUNCTION(6 __stdcall) HP_RET_FUNCTION(7 __stdcall) HP_RET_FUNCTION(8 __stdcall) HP_RET_FUNCTION(9 __stdcall) HP_RET_FUNCTION(10 __stdcall)endif namespace HotPatch

What Im doing above is generating 11 partial tempate specializations for class HotPatchfunction The class isinspired by C++2011s stdfunction Its a class that models functions with up to 10 (included) arguments - you cansee the declarations through the HP_RET_FUNCTION macro calls in there Then another set of 11 declarations for x86-64where only calling convention __cdecl exists Do not worry abut understanding the above code its ugly and it sucksFocus on the usage instead it gets things done (for up to 10 arguments that is)

To use this HotPatch mini-lib write something like

HotPatchTestcppinclude ltcstdiogtinclude HotPatchhppusing namespace stdusing namespace HotPatch functionltvoid()gt fooPatch void foo() printf(In foo()n) void bar()

httpelfcspubrosowiki Printed on 20111126 0759

26-11-2011 1515 Function Hooking and Windows Dll Injection

printf(Im hackin ur functionn) if (fooPatchIsPatched()) fooPatch() int main() void (pfoo)() = foo void (pbar)() = bar pfoo() calls foo() pbar() calls bar() fooPatch = foo fooPatchSetPatch(bar) fooPatchApplyPatch() pfoo() calls bar() pbar() calls bar() fooPatchRemovePatch() pfoo() calls foo() pbar() calls bar() return 0

Further Info and Support

Im usually idling under the handle foxx1337 on ircfreenodenet on rosedu1) httpwwwkernelorgdocman-pagesonlinepagesman8ld-linuxso8html LD_PRELOAD2) httpsupportmicrosoftcomkb197571 AppInit_DLLs registry hack3) httpyosefkcomc++fqafunctionhtml4) Fraps5) RivaTuner6) MSI Afterburner7) Sockscap8) foobar20009) AutoHotkey10) Code Project Article on Code Injection11) Media Player Classic Homecinema12) httpcontinuationswordpresscom20110510hot-patching-unconditional-jumps-x86-x86-64 Article on 64 bit hotpatching

Fromhttpelfcspubrosowiki - Sisteme de Operare

Permanent linkhttpelfcspubrosowikilaboratoareresurseinjections

Last update 20111108 0213

Sisteme de Operare - httpelfcspubrosowiki

Page 5: Function Hooking and Windows Dll Injection.pdf

26-11-2011 515 Function Hooking and Windows Dll Injection

normally an event is dispatched to the message loop of the receiving thread and the message loop further sends that1message within the thread to a proper handlermyhookdll registers system-wide ShellProc() as an interceptor of shell events (out of which WM_CREATE) Now2the message goes through the code from ShellProc() and only after processing its (not even necessary only becauseIm too kind) forwarded to the shell handler in the original event loop

A Practical Example

I like playing my games in windowed mode Inspired by Media Player Classic Homecinemas11) borderless always on top

Sisteme de Operare - httpelfcspubrosowiki

Function Hooking and Windows Dll Injection 615 26-11-2011

window mode I thought to myself how cool would it be to have any games window borderless and always on top of theother windows A games window usually contains either WS_CAPTION or WS_THICKFRAME window styles Making itborderless is a simple matter of retrieving its style (GetWindowLong(GWL_STYLE)) removing (toggling) by means of XORthe relevant style and then applying the result on the window handle SetWindowLong(GWL_STYLE)

Removing The Window Decorations

As a first attempt I created a simple one-shot console application that targeted the Heroes of Newerth window removingthe WS_CAPTION style as reported by Spy++

Borderless1cppinclude ltcstdiogtusing namespace stdinclude ltwindowshgt int main() bool done = false finish when q is entered while (done) HWND hwnd = FindWindow(NULL TEXT(Heroes of Newerth)) if (NULL = hwnd) LONG styles = GetWindowLong(hwnd GWL_STYLE) if (0 = styles) styles ^= WS_CAPTION LONG result = SetWindowLong(hwnd GWL_STYLE styles) char c scanf(c ampc) if (q == c) done = true return 0

httpelfcspubrosowiki Printed on 20111126 0759

26-11-2011 715 Function Hooking and Windows Dll Injection

You can observe 2 problems in the current approach

the window is now blurry1the mouse hover effect is registered a few pixels off2

The blurriness problem happens because after removing the decorations (titlebar dialog borders) Windows tries tomaintain the program window within the same bounding rectangle In doing so it inflates the client area by a few pixelsin each direction pixels obtained from removing said decorations Indeed counting the pixels from the first picture we geta total window area (including borders) of 1616times858 and a client area (only the Direct3D part from within the borderswhere the application draws its updates) of 1600times820 pixels For the second picture we have a window area equal to theclient area (no more borders) of 1606times848 pixels Since Heroes of Newerth has a dialog frame (non-sizeable) it doesnttreat WM_SIZE messages the Direct3D context keeps rendering at the initial config file resolution and the resulting framebuffer gets drawn with stretching on top of a sligthly different window area so we dont have a perfect (logical)pixel-on-(screen )pixel mapping anymoreNote my config file for the game

snipSetSave vid_resolution 1600820snip

Heres a fix for keeping the client area of the window in place during the style change

Borderless2cppinclude ltcstdiogtusing namespace stdinclude ltwindowshgt int main() bool done = false while (done) HWND hwnd = FindWindow(NULL TEXT(Heroes of Newerth)) if (NULL = hwnd) LONG styles = GetWindowLong(hwnd GWL_STYLE) if (0 = styles) styles ^= WS_CAPTION bool deflate = 0 == (styles amp WS_CAPTION) RECT rc GetWindowRect(hwnd amprc) int captionHeight = GetSystemMetrics(SM_CYCAPTION) int borderWidth = GetSystemMetrics(SM_CXDLGFRAME) int borderHeight = GetSystemMetrics(SM_CYDLGFRAME)

Sisteme de Operare - httpelfcspubrosowiki

Function Hooking and Windows Dll Injection 815 26-11-2011

if (deflate) rcleft += borderWidth rcright -= borderWidth rctop += captionHeight + borderHeight rcbottom -= borderHeight else rcleft -= borderWidth rcright += borderWidth rctop -= captionHeight + borderHeight rcbottom += borderHeight LONG result = SetWindowLong(hwnd GWL_STYLE styles) if (0 = result) SetWindowPos(hwnd NULL rcleft rctop rcright - rcleft rcbottom - rctop SWP_FRAMECHANGED) char c scanf(c ampc) if (q == c) done = true return 0

A process such as Starcraft 2 owns a window with the WS_THICKFRAME style denoting a sizing border If I change the codeto remove that style from the Starcraft 2 main window (also SM_CTHICKFRAME instead of SM_CDLGFRAME I can onlynotice the mouse hover effect being off - the game catches WM_SIZE messages and adjusts the framebuffer accordingly

Fixing The Mouse Behavior

For the broken mouse hover effect its time to put The Injection to use Among the usual suspects for this problem are thewindow rectangle functions GetWindowRect() and GetClientRect() It would make sense due to the fact that games usuallyobtain mouse events through DirectInput that initially mouse coordinates are expressed in desktop-absolute form and notrelative to the application window Therefore theyd have to employ in one form or another a conversion between screen(absolute) coordinates and window coordinates in a similar manner to the operation of ClientToScreen()Lets take a look at an application window and the GetRect() logic relating to it

What the game does when handling mouse input is obtain some absolute screen coordinates from DirectInput convertthem to window coordinates then compensate for the window title and borders and then figure out what to do next with

httpelfcspubrosowiki Printed on 20111126 0759

26-11-2011 915 Function Hooking and Windows Dll Injection

the event Note that after removing the window decorations both GetWindowRect() and GetClientRect() return thesame coordinates Then the game compensates by subtracting the expected widths and heights of borders resulting inslightly off readings for the events The idea here is to modify at run-time GetWindowRect() so that it returns the oldrectangle with titlebar and borders as if the window style still contained those elements

The basic workflow for detouring GetWindowRect() is

insert exactly at the beginning of the function a jmp to our GetWindowRect() hot patch it1in our GetWindowRect() restore the code of the original function2call the original function and save the result3modify that result so that it fits our agenda4hot patch GetWindowRect() again5return the now modified result6

32 Bit Versus 64 Bit

Special care should be taken when moving to x86-64

Hot Patching

While the previous approach for hot patching a function (via relative jmp) is generally OK even in 64 bit mode there couldbe rare occasions when the distance between the patched function and the original one cant be expressed on only 32 bitsSince the specific form of jmp used expects a 32 bit displacement it would be useless in this case

The suggested solution here is a 64 bit absolute jump which comes by default with x86-6412) The idea here is just slightlydifferent than in the case of plain x86 While jmp accepted there as argument an immediate displacement the x86-64 longjump functions through an indirect register So wed simply load the destination address (not a distance any more for thisinstruction) into a register and pass that register as the operand to the jmp Fortunately x86-64 states that the special64-bit registries r10 and r11 arent preserved between call opcodes so picking r11 is a safe bet and guaranteed not toruin the program flow

Dll Injection

One cant insert an image compiled for 32 bits inside a 64 bit process and cant inject a 64 bit dll inside a 32 bit processThe idea is to have 2 separate programs making the dll injection 2 versions of the dll each of them for 64 bits andrespectively for 32 bits The 32 bit injector should set up the hooks as usual and launch a light weight version of itself thatonly sets up the hook and waits for an end event

Loader

TCHAR path[MAX_PATH] DWORD len = GetModuleFileName(NULL path MAX_PATH) while (path[len - 1] = ) --len MoveMemory(path + len TEXT(Deframe64dat) sizeof(TCHAR) (lstrlen(TEXT(Deframe64dat)) + 1)) STARTUPINFO siDeframe64 = sizeof(STARTUPINFO) PROCESS_INFORMATION piDeframe64 BOOL bRes = CreateProcess(0 path NULL NULL TRUE 0 NULL NULL ampsiDeframe64 amppiDeframe64) if (bRes) WaitForInputIdle(piDeframe64hProcess INFINITE) InstallHook()

Deframe64cppinclude ltwindowshgtinclude DeframeHelperh int WINAPI WinMain(HINSTANCE hInstance HINSTANCE hPrevInstance LPSTR lpCmdLine int nCmdShow) InstallHook() main message loop MSG msg while (GetMessage(ampmsg NULL 0 0) ampamp WM_QUIT = msgmessage) TranslateMessage(ampmsg) DispatchMessage(ampmsg)

Sisteme de Operare - httpelfcspubrosowiki

Function Hooking and Windows Dll Injection 1015 26-11-2011

RemoveHook() return static_castltintgt(msgwParam)

The first fragment of code residing in the normal 32 bit injector process first spawns a 64 bit child our Deframe64datThey both perform the same main function at this stage - calling InstallHook() which is exported by the guest dll Ivemessed with the output of Deframe64 so that it has the extension dat this is only an aesthetic step so that the userdoesnt accidentally launch the useless and with no means of terminating 64 bit process On 32 bit systemsCreateProcess() will fail and I simply ignore everything involving itHeres how the 32 bit injector terminates the 64 bit one

if (bRes) PostThreadMessage(piDeframe64dwThreadId WM_QUIT 0 0)

The Visual Studio 2010 Solution

All the required code can be found here Note that the project files wont work with the Express version of Visual Studiodue to the main program - Deframe being written with MFCFor a binary build see this archiveThe solution uses a C-like approach for the Injection

A C++ Template Library (for the impatient)

This code is not for the faint of heart C++ 2003 (talking about Microsoft Visual C 2010 here variadic template support)template code to simplify the hotpatching Include it and use it as exemplified further below (its not included in the sourcedownload)

HotPatchhpppragma once include ltwindowshgt HotPatch is a thin wrapper on top of the function hot patching layer It encapsulates a way to replace known functions with own functions by means of patching in jmps in both x86and x86-64 The basic workflow is 1 Declare HotPatchfunctionltftypegt thePatch assign target to this object with thePatch = target 2 set a replacement callback with thePatchSetPatch(myTarget) 3 call thePatchApply() to replace the target with the other callback In the replacement procedure

httpelfcspubrosowiki Printed on 20111126 0759

26-11-2011 1115 Function Hooking and Windows Dll Injection

31 do your stuff 32 call thePatch(arguments) 33 do other stuff When done 4 restore the opcodes with thePatchRemovePatch() 5 the destructor or assigning a new function to thePatch will restore the protection status of the memoryreferred by target Limitations wont work with variadic functions (blame C)namespace HotPatch class Exception class MemoryException public Exception class PatchException public Exception template lttypename FTypegt class function_impl public function_impl() _pFun(NULL) _pPatch(NULL) _detoured(false) ~function_impl() _RestoreProtection() res = function_implltFTypegtIsPatched() tells whether a call to the target will run the target or thehook Return value bool res - true if ApplyPatch() has been called without an accompanying RemovePatch() bool IsPatched() return _detoured function_implltFTypegtoperator=(pFun) directs the patch to a target and prepares the target memory forwrites Parameters FType pFun - the function to patch (see Apply()) Throws MemoryException - when changing the protection of the page where pFun points is impossible void operator=(FType pFun) _RestoreProtection() _pFun = pFun if (NULL == _pFun) return BOOL res = VirtualProtect(_pFun _64bit _PATCH_LENGTH64 _PATCH_LENGTH32 PAGE_EXECUTE_READWRITEamp_oldProtection) if (res) throw MemoryException() function_implltFTypegtSetPatch(patch[ alwaysUse32Bit]) prepares internal state for the patch Parameters FType patch - the patch to use instead of pFun (see operator=(FType )) bool alwaysUse32Bit - If true a 32 bit jmp is always inserted Else the best jmp is determined based on necessities (can still be 32 bit if it fits) Throws PatchException - if patch is NULL void SetPatch(FType patch bool alwaysUse32Bit = false) if (NULL == patch) throw PatchException() if (NULL = _pPatch) RemovePatch() _pPatch = patch _64bit = alwaysUse32Bit they havent expressed mandatory 32 bit only path try to guess the best path

Sisteme de Operare - httpelfcspubrosowiki

Function Hooking and Windows Dll Injection 1215 26-11-2011

if (_64bit) LONGLONG jumpDistance = reinterpret_castltLONGLONGgt(_pPatch) - reinterpret_castltLONGLONGgt(_pFun) - _PATCH_LENGTH32 if (abs(jumpDistance) gt 0x7FFFFFFF) the jump is too long to fit a regular 32 bit relative jmp _64bit = true else _64bit = false save the old patch opcodes plain old for is faster DO NOT call any library functions for (SIZE_T i = 0 i lt (_64bit _PATCH_LENGTH64 _PATCH_LENGTH32) ++i) (_backup + i) = (reinterpret_castltPBYTEgt(_pFun) + i) function_implltFTypegtApplyPatch() makes pFun (see operator=(FType )) jmp to patch (seeSetPatch(FType bool)) This is the actual hot patch mechanism at work void ApplyPatch() if (_64bit) movabs reinterpret_castltPBYTEgt(_pFun) = _OP_MOVABS r11 (reinterpret_castltPBYTEgt(_pFun) + 1) = _R11_WRITE _detourProc reinterpret_castltPLONGLONGgt(reinterpret_castltPBYTEgt(_pFun) + 2) =reinterpret_castltLONGLONGgt(_pPatch) jmp reinterpret_castltPWORDgt(reinterpret_castltPBYTEgt(_pFun) + 10) = _OP_JMP64 abs r11 (reinterpret_castltPBYTEgt(_pFun) + 12) = _R11_JMP else jmp reinterpret_castltPBYTEgt(_pFun) = _OP_JMP32 distance left to _detourProc reinterpret_castltPDWORDgt(reinterpret_castltPBYTEgt(_pFun) + 1) = static_castltDWORDgt( reinterpret_castltPBYTEgt(_pPatch) - reinterpret_castltPBYTEgt(_pFun) - static_castltDWORDgt(_PATCH_LENGTH32)) _detoured = true function_implltFTypegtRemovePatch() undoes what ApplyPatch() did pFun (see operator=(FType )) willbe its old self again void RemovePatch() plain old for is faster DO NOT call any library functions for (SIZE_T i = 0 i lt (_64bit _PATCH_LENGTH64 _PATCH_LENGTH32) ++i) (reinterpret_castltPBYTEgt(_pFun) + i) = (_backup + i) _detoured = false protected FType _pFun FType _pPatch bool _64bit bool _detoured BYTE _backup[13] DWORD _oldProtection static const BYTE _OP_JMP32 = 0xE9 static const WORD _OP_JMP64 = 0xFF41 static const BYTE _OP_MOVABS = 0x49 static const BYTE _R11_WRITE = 0xBB static const BYTE _R11_JMP = 0xE3 static const SIZE_T _PATCH_LENGTH32 = 5 jmp detourProc - originalProc = 1 + 4 static const SIZE_T _PATCH_LENGTH64 = 13 movabs R11 detourProc (64 bit) jmp (abs 64) R11 = 1+ 1 + 8 + 2 + 1 template lttypename Tgt static T abs(T val) return val gt 0 val -val

httpelfcspubrosowiki Printed on 20111126 0759

26-11-2011 1315 Function Hooking and Windows Dll Injection

void _RestoreProtection() if (NULL == _pFun) return DWORD unusedOldProtection BOOL res = VirtualProtect(_pFun _64bit _PATCH_LENGTH64 _PATCH_LENGTH32 _oldProtectionampunusedOldProtection) (void) res nothing to do template lttypename FTypegt class _NativeCallGuard public _NativeCallGuard(function_implltFTypegt ampfun) _fun(fun) _funRemovePatch() ~_NativeCallGuard() _funApplyPatch() private function_implltFTypegt amp_fun template lttypenamegt class function define HP_TARG0define HP_TARG1 typename Arg1define HP_TARG2 HP_TARG1 typename Arg2define HP_TARG3 HP_TARG2 typename Arg3define HP_TARG4 HP_TARG3 typename Arg4define HP_TARG5 HP_TARG4 typename Arg5define HP_TARG6 HP_TARG5 typename Arg6define HP_TARG7 HP_TARG6 typename Arg7define HP_TARG8 HP_TARG7 typename Arg8define HP_TARG9 HP_TARG8 typename Arg9define HP_TARG10 HP_TARG9 typename Arg10define HP_FARG0define HP_FARG1 Arg1define HP_FARG2 HP_FARG1 Arg2define HP_FARG3 HP_FARG2 Arg3define HP_FARG4 HP_FARG3 Arg4define HP_FARG5 HP_FARG4 Arg5define HP_FARG6 HP_FARG5 Arg6define HP_FARG7 HP_FARG6 Arg7define HP_FARG8 HP_FARG7 Arg8define HP_FARG9 HP_FARG8 Arg9define HP_FARG10 HP_FARG9 Arg10define HP_ARG0define HP_ARG1 arg1define HP_ARG2 HP_ARG1 arg2define HP_ARG3 HP_ARG2 arg3define HP_ARG4 HP_ARG3 arg4define HP_ARG5 HP_ARG4 arg5define HP_ARG6 HP_ARG5 arg6define HP_ARG7 HP_ARG6 arg7define HP_ARG8 HP_ARG7 arg8define HP_ARG9 HP_ARG8 arg9define HP_ARG10 HP_ARG9 arg10define HP_ARG_DECL0define HP_ARG_DECL1 Arg1 arg1define HP_ARG_DECL2 HP_ARG_DECL1 Arg2 arg2define HP_ARG_DECL3 HP_ARG_DECL2 Arg3 arg3define HP_ARG_DECL4 HP_ARG_DECL3 Arg4 arg4define HP_ARG_DECL5 HP_ARG_DECL4 Arg5 arg5define HP_ARG_DECL6 HP_ARG_DECL5 Arg6 arg6define HP_ARG_DECL7 HP_ARG_DECL6 Arg7 arg7define HP_ARG_DECL8 HP_ARG_DECL7 Arg8 arg8define HP_ARG_DECL9 HP_ARG_DECL8 Arg9 arg9define HP_ARG_DECL10 HP_ARG_DECL9 Arg10 arg10 template partial specialization for functionltreturn_type([arg_types])gtdefine HP_RET_FUNCTION(n callconv) template lttypename _Ret HP_TARGngt class functionlt_Ret callconv(HP_FARGn)gt public function_impllt_Ret callconv(HP_FARGn)gt

Sisteme de Operare - httpelfcspubrosowiki

Function Hooking and Windows Dll Injection 1415 26-11-2011

private typedef _Ret callconv type(HP_FARGn) public ~functionlttypegt() _RestoreProtection() using function_impllttypegtoperator= _Ret operator()(HP_ARG_DECLn) _NativeCallGuardlttypegt CallGuard(this) return (_pFun)(HP_ARGn) protected using function_impllttypegt_pFun declare the 11 templates handling functions in the form _Ret function() _Ret function(Arg1) _Ret function(Arg1 Arg2) _Ret function(Arg1 Arg2 Arg10) HP_RET_FUNCTION(0 __cdecl) HP_RET_FUNCTION(1 __cdecl) HP_RET_FUNCTION(2 __cdecl) HP_RET_FUNCTION(3 __cdecl) HP_RET_FUNCTION(4 __cdecl) HP_RET_FUNCTION(5 __cdecl) HP_RET_FUNCTION(6 __cdecl) HP_RET_FUNCTION(7 __cdecl) HP_RET_FUNCTION(8 __cdecl) HP_RET_FUNCTION(9 __cdecl) HP_RET_FUNCTION(10 __cdecl) ifndef _M_X64 HP_RET_FUNCTION(0 __stdcall) HP_RET_FUNCTION(1 __stdcall) HP_RET_FUNCTION(2 __stdcall) HP_RET_FUNCTION(3 __stdcall) HP_RET_FUNCTION(4 __stdcall) HP_RET_FUNCTION(5 __stdcall) HP_RET_FUNCTION(6 __stdcall) HP_RET_FUNCTION(7 __stdcall) HP_RET_FUNCTION(8 __stdcall) HP_RET_FUNCTION(9 __stdcall) HP_RET_FUNCTION(10 __stdcall)endif namespace HotPatch

What Im doing above is generating 11 partial tempate specializations for class HotPatchfunction The class isinspired by C++2011s stdfunction Its a class that models functions with up to 10 (included) arguments - you cansee the declarations through the HP_RET_FUNCTION macro calls in there Then another set of 11 declarations for x86-64where only calling convention __cdecl exists Do not worry abut understanding the above code its ugly and it sucksFocus on the usage instead it gets things done (for up to 10 arguments that is)

To use this HotPatch mini-lib write something like

HotPatchTestcppinclude ltcstdiogtinclude HotPatchhppusing namespace stdusing namespace HotPatch functionltvoid()gt fooPatch void foo() printf(In foo()n) void bar()

httpelfcspubrosowiki Printed on 20111126 0759

26-11-2011 1515 Function Hooking and Windows Dll Injection

printf(Im hackin ur functionn) if (fooPatchIsPatched()) fooPatch() int main() void (pfoo)() = foo void (pbar)() = bar pfoo() calls foo() pbar() calls bar() fooPatch = foo fooPatchSetPatch(bar) fooPatchApplyPatch() pfoo() calls bar() pbar() calls bar() fooPatchRemovePatch() pfoo() calls foo() pbar() calls bar() return 0

Further Info and Support

Im usually idling under the handle foxx1337 on ircfreenodenet on rosedu1) httpwwwkernelorgdocman-pagesonlinepagesman8ld-linuxso8html LD_PRELOAD2) httpsupportmicrosoftcomkb197571 AppInit_DLLs registry hack3) httpyosefkcomc++fqafunctionhtml4) Fraps5) RivaTuner6) MSI Afterburner7) Sockscap8) foobar20009) AutoHotkey10) Code Project Article on Code Injection11) Media Player Classic Homecinema12) httpcontinuationswordpresscom20110510hot-patching-unconditional-jumps-x86-x86-64 Article on 64 bit hotpatching

Fromhttpelfcspubrosowiki - Sisteme de Operare

Permanent linkhttpelfcspubrosowikilaboratoareresurseinjections

Last update 20111108 0213

Sisteme de Operare - httpelfcspubrosowiki

Page 6: Function Hooking and Windows Dll Injection.pdf

Function Hooking and Windows Dll Injection 615 26-11-2011

window mode I thought to myself how cool would it be to have any games window borderless and always on top of theother windows A games window usually contains either WS_CAPTION or WS_THICKFRAME window styles Making itborderless is a simple matter of retrieving its style (GetWindowLong(GWL_STYLE)) removing (toggling) by means of XORthe relevant style and then applying the result on the window handle SetWindowLong(GWL_STYLE)

Removing The Window Decorations

As a first attempt I created a simple one-shot console application that targeted the Heroes of Newerth window removingthe WS_CAPTION style as reported by Spy++

Borderless1cppinclude ltcstdiogtusing namespace stdinclude ltwindowshgt int main() bool done = false finish when q is entered while (done) HWND hwnd = FindWindow(NULL TEXT(Heroes of Newerth)) if (NULL = hwnd) LONG styles = GetWindowLong(hwnd GWL_STYLE) if (0 = styles) styles ^= WS_CAPTION LONG result = SetWindowLong(hwnd GWL_STYLE styles) char c scanf(c ampc) if (q == c) done = true return 0

httpelfcspubrosowiki Printed on 20111126 0759

26-11-2011 715 Function Hooking and Windows Dll Injection

You can observe 2 problems in the current approach

the window is now blurry1the mouse hover effect is registered a few pixels off2

The blurriness problem happens because after removing the decorations (titlebar dialog borders) Windows tries tomaintain the program window within the same bounding rectangle In doing so it inflates the client area by a few pixelsin each direction pixels obtained from removing said decorations Indeed counting the pixels from the first picture we geta total window area (including borders) of 1616times858 and a client area (only the Direct3D part from within the borderswhere the application draws its updates) of 1600times820 pixels For the second picture we have a window area equal to theclient area (no more borders) of 1606times848 pixels Since Heroes of Newerth has a dialog frame (non-sizeable) it doesnttreat WM_SIZE messages the Direct3D context keeps rendering at the initial config file resolution and the resulting framebuffer gets drawn with stretching on top of a sligthly different window area so we dont have a perfect (logical)pixel-on-(screen )pixel mapping anymoreNote my config file for the game

snipSetSave vid_resolution 1600820snip

Heres a fix for keeping the client area of the window in place during the style change

Borderless2cppinclude ltcstdiogtusing namespace stdinclude ltwindowshgt int main() bool done = false while (done) HWND hwnd = FindWindow(NULL TEXT(Heroes of Newerth)) if (NULL = hwnd) LONG styles = GetWindowLong(hwnd GWL_STYLE) if (0 = styles) styles ^= WS_CAPTION bool deflate = 0 == (styles amp WS_CAPTION) RECT rc GetWindowRect(hwnd amprc) int captionHeight = GetSystemMetrics(SM_CYCAPTION) int borderWidth = GetSystemMetrics(SM_CXDLGFRAME) int borderHeight = GetSystemMetrics(SM_CYDLGFRAME)

Sisteme de Operare - httpelfcspubrosowiki

Function Hooking and Windows Dll Injection 815 26-11-2011

if (deflate) rcleft += borderWidth rcright -= borderWidth rctop += captionHeight + borderHeight rcbottom -= borderHeight else rcleft -= borderWidth rcright += borderWidth rctop -= captionHeight + borderHeight rcbottom += borderHeight LONG result = SetWindowLong(hwnd GWL_STYLE styles) if (0 = result) SetWindowPos(hwnd NULL rcleft rctop rcright - rcleft rcbottom - rctop SWP_FRAMECHANGED) char c scanf(c ampc) if (q == c) done = true return 0

A process such as Starcraft 2 owns a window with the WS_THICKFRAME style denoting a sizing border If I change the codeto remove that style from the Starcraft 2 main window (also SM_CTHICKFRAME instead of SM_CDLGFRAME I can onlynotice the mouse hover effect being off - the game catches WM_SIZE messages and adjusts the framebuffer accordingly

Fixing The Mouse Behavior

For the broken mouse hover effect its time to put The Injection to use Among the usual suspects for this problem are thewindow rectangle functions GetWindowRect() and GetClientRect() It would make sense due to the fact that games usuallyobtain mouse events through DirectInput that initially mouse coordinates are expressed in desktop-absolute form and notrelative to the application window Therefore theyd have to employ in one form or another a conversion between screen(absolute) coordinates and window coordinates in a similar manner to the operation of ClientToScreen()Lets take a look at an application window and the GetRect() logic relating to it

What the game does when handling mouse input is obtain some absolute screen coordinates from DirectInput convertthem to window coordinates then compensate for the window title and borders and then figure out what to do next with

httpelfcspubrosowiki Printed on 20111126 0759

26-11-2011 915 Function Hooking and Windows Dll Injection

the event Note that after removing the window decorations both GetWindowRect() and GetClientRect() return thesame coordinates Then the game compensates by subtracting the expected widths and heights of borders resulting inslightly off readings for the events The idea here is to modify at run-time GetWindowRect() so that it returns the oldrectangle with titlebar and borders as if the window style still contained those elements

The basic workflow for detouring GetWindowRect() is

insert exactly at the beginning of the function a jmp to our GetWindowRect() hot patch it1in our GetWindowRect() restore the code of the original function2call the original function and save the result3modify that result so that it fits our agenda4hot patch GetWindowRect() again5return the now modified result6

32 Bit Versus 64 Bit

Special care should be taken when moving to x86-64

Hot Patching

While the previous approach for hot patching a function (via relative jmp) is generally OK even in 64 bit mode there couldbe rare occasions when the distance between the patched function and the original one cant be expressed on only 32 bitsSince the specific form of jmp used expects a 32 bit displacement it would be useless in this case

The suggested solution here is a 64 bit absolute jump which comes by default with x86-6412) The idea here is just slightlydifferent than in the case of plain x86 While jmp accepted there as argument an immediate displacement the x86-64 longjump functions through an indirect register So wed simply load the destination address (not a distance any more for thisinstruction) into a register and pass that register as the operand to the jmp Fortunately x86-64 states that the special64-bit registries r10 and r11 arent preserved between call opcodes so picking r11 is a safe bet and guaranteed not toruin the program flow

Dll Injection

One cant insert an image compiled for 32 bits inside a 64 bit process and cant inject a 64 bit dll inside a 32 bit processThe idea is to have 2 separate programs making the dll injection 2 versions of the dll each of them for 64 bits andrespectively for 32 bits The 32 bit injector should set up the hooks as usual and launch a light weight version of itself thatonly sets up the hook and waits for an end event

Loader

TCHAR path[MAX_PATH] DWORD len = GetModuleFileName(NULL path MAX_PATH) while (path[len - 1] = ) --len MoveMemory(path + len TEXT(Deframe64dat) sizeof(TCHAR) (lstrlen(TEXT(Deframe64dat)) + 1)) STARTUPINFO siDeframe64 = sizeof(STARTUPINFO) PROCESS_INFORMATION piDeframe64 BOOL bRes = CreateProcess(0 path NULL NULL TRUE 0 NULL NULL ampsiDeframe64 amppiDeframe64) if (bRes) WaitForInputIdle(piDeframe64hProcess INFINITE) InstallHook()

Deframe64cppinclude ltwindowshgtinclude DeframeHelperh int WINAPI WinMain(HINSTANCE hInstance HINSTANCE hPrevInstance LPSTR lpCmdLine int nCmdShow) InstallHook() main message loop MSG msg while (GetMessage(ampmsg NULL 0 0) ampamp WM_QUIT = msgmessage) TranslateMessage(ampmsg) DispatchMessage(ampmsg)

Sisteme de Operare - httpelfcspubrosowiki

Function Hooking and Windows Dll Injection 1015 26-11-2011

RemoveHook() return static_castltintgt(msgwParam)

The first fragment of code residing in the normal 32 bit injector process first spawns a 64 bit child our Deframe64datThey both perform the same main function at this stage - calling InstallHook() which is exported by the guest dll Ivemessed with the output of Deframe64 so that it has the extension dat this is only an aesthetic step so that the userdoesnt accidentally launch the useless and with no means of terminating 64 bit process On 32 bit systemsCreateProcess() will fail and I simply ignore everything involving itHeres how the 32 bit injector terminates the 64 bit one

if (bRes) PostThreadMessage(piDeframe64dwThreadId WM_QUIT 0 0)

The Visual Studio 2010 Solution

All the required code can be found here Note that the project files wont work with the Express version of Visual Studiodue to the main program - Deframe being written with MFCFor a binary build see this archiveThe solution uses a C-like approach for the Injection

A C++ Template Library (for the impatient)

This code is not for the faint of heart C++ 2003 (talking about Microsoft Visual C 2010 here variadic template support)template code to simplify the hotpatching Include it and use it as exemplified further below (its not included in the sourcedownload)

HotPatchhpppragma once include ltwindowshgt HotPatch is a thin wrapper on top of the function hot patching layer It encapsulates a way to replace known functions with own functions by means of patching in jmps in both x86and x86-64 The basic workflow is 1 Declare HotPatchfunctionltftypegt thePatch assign target to this object with thePatch = target 2 set a replacement callback with thePatchSetPatch(myTarget) 3 call thePatchApply() to replace the target with the other callback In the replacement procedure

httpelfcspubrosowiki Printed on 20111126 0759

26-11-2011 1115 Function Hooking and Windows Dll Injection

31 do your stuff 32 call thePatch(arguments) 33 do other stuff When done 4 restore the opcodes with thePatchRemovePatch() 5 the destructor or assigning a new function to thePatch will restore the protection status of the memoryreferred by target Limitations wont work with variadic functions (blame C)namespace HotPatch class Exception class MemoryException public Exception class PatchException public Exception template lttypename FTypegt class function_impl public function_impl() _pFun(NULL) _pPatch(NULL) _detoured(false) ~function_impl() _RestoreProtection() res = function_implltFTypegtIsPatched() tells whether a call to the target will run the target or thehook Return value bool res - true if ApplyPatch() has been called without an accompanying RemovePatch() bool IsPatched() return _detoured function_implltFTypegtoperator=(pFun) directs the patch to a target and prepares the target memory forwrites Parameters FType pFun - the function to patch (see Apply()) Throws MemoryException - when changing the protection of the page where pFun points is impossible void operator=(FType pFun) _RestoreProtection() _pFun = pFun if (NULL == _pFun) return BOOL res = VirtualProtect(_pFun _64bit _PATCH_LENGTH64 _PATCH_LENGTH32 PAGE_EXECUTE_READWRITEamp_oldProtection) if (res) throw MemoryException() function_implltFTypegtSetPatch(patch[ alwaysUse32Bit]) prepares internal state for the patch Parameters FType patch - the patch to use instead of pFun (see operator=(FType )) bool alwaysUse32Bit - If true a 32 bit jmp is always inserted Else the best jmp is determined based on necessities (can still be 32 bit if it fits) Throws PatchException - if patch is NULL void SetPatch(FType patch bool alwaysUse32Bit = false) if (NULL == patch) throw PatchException() if (NULL = _pPatch) RemovePatch() _pPatch = patch _64bit = alwaysUse32Bit they havent expressed mandatory 32 bit only path try to guess the best path

Sisteme de Operare - httpelfcspubrosowiki

Function Hooking and Windows Dll Injection 1215 26-11-2011

if (_64bit) LONGLONG jumpDistance = reinterpret_castltLONGLONGgt(_pPatch) - reinterpret_castltLONGLONGgt(_pFun) - _PATCH_LENGTH32 if (abs(jumpDistance) gt 0x7FFFFFFF) the jump is too long to fit a regular 32 bit relative jmp _64bit = true else _64bit = false save the old patch opcodes plain old for is faster DO NOT call any library functions for (SIZE_T i = 0 i lt (_64bit _PATCH_LENGTH64 _PATCH_LENGTH32) ++i) (_backup + i) = (reinterpret_castltPBYTEgt(_pFun) + i) function_implltFTypegtApplyPatch() makes pFun (see operator=(FType )) jmp to patch (seeSetPatch(FType bool)) This is the actual hot patch mechanism at work void ApplyPatch() if (_64bit) movabs reinterpret_castltPBYTEgt(_pFun) = _OP_MOVABS r11 (reinterpret_castltPBYTEgt(_pFun) + 1) = _R11_WRITE _detourProc reinterpret_castltPLONGLONGgt(reinterpret_castltPBYTEgt(_pFun) + 2) =reinterpret_castltLONGLONGgt(_pPatch) jmp reinterpret_castltPWORDgt(reinterpret_castltPBYTEgt(_pFun) + 10) = _OP_JMP64 abs r11 (reinterpret_castltPBYTEgt(_pFun) + 12) = _R11_JMP else jmp reinterpret_castltPBYTEgt(_pFun) = _OP_JMP32 distance left to _detourProc reinterpret_castltPDWORDgt(reinterpret_castltPBYTEgt(_pFun) + 1) = static_castltDWORDgt( reinterpret_castltPBYTEgt(_pPatch) - reinterpret_castltPBYTEgt(_pFun) - static_castltDWORDgt(_PATCH_LENGTH32)) _detoured = true function_implltFTypegtRemovePatch() undoes what ApplyPatch() did pFun (see operator=(FType )) willbe its old self again void RemovePatch() plain old for is faster DO NOT call any library functions for (SIZE_T i = 0 i lt (_64bit _PATCH_LENGTH64 _PATCH_LENGTH32) ++i) (reinterpret_castltPBYTEgt(_pFun) + i) = (_backup + i) _detoured = false protected FType _pFun FType _pPatch bool _64bit bool _detoured BYTE _backup[13] DWORD _oldProtection static const BYTE _OP_JMP32 = 0xE9 static const WORD _OP_JMP64 = 0xFF41 static const BYTE _OP_MOVABS = 0x49 static const BYTE _R11_WRITE = 0xBB static const BYTE _R11_JMP = 0xE3 static const SIZE_T _PATCH_LENGTH32 = 5 jmp detourProc - originalProc = 1 + 4 static const SIZE_T _PATCH_LENGTH64 = 13 movabs R11 detourProc (64 bit) jmp (abs 64) R11 = 1+ 1 + 8 + 2 + 1 template lttypename Tgt static T abs(T val) return val gt 0 val -val

httpelfcspubrosowiki Printed on 20111126 0759

26-11-2011 1315 Function Hooking and Windows Dll Injection

void _RestoreProtection() if (NULL == _pFun) return DWORD unusedOldProtection BOOL res = VirtualProtect(_pFun _64bit _PATCH_LENGTH64 _PATCH_LENGTH32 _oldProtectionampunusedOldProtection) (void) res nothing to do template lttypename FTypegt class _NativeCallGuard public _NativeCallGuard(function_implltFTypegt ampfun) _fun(fun) _funRemovePatch() ~_NativeCallGuard() _funApplyPatch() private function_implltFTypegt amp_fun template lttypenamegt class function define HP_TARG0define HP_TARG1 typename Arg1define HP_TARG2 HP_TARG1 typename Arg2define HP_TARG3 HP_TARG2 typename Arg3define HP_TARG4 HP_TARG3 typename Arg4define HP_TARG5 HP_TARG4 typename Arg5define HP_TARG6 HP_TARG5 typename Arg6define HP_TARG7 HP_TARG6 typename Arg7define HP_TARG8 HP_TARG7 typename Arg8define HP_TARG9 HP_TARG8 typename Arg9define HP_TARG10 HP_TARG9 typename Arg10define HP_FARG0define HP_FARG1 Arg1define HP_FARG2 HP_FARG1 Arg2define HP_FARG3 HP_FARG2 Arg3define HP_FARG4 HP_FARG3 Arg4define HP_FARG5 HP_FARG4 Arg5define HP_FARG6 HP_FARG5 Arg6define HP_FARG7 HP_FARG6 Arg7define HP_FARG8 HP_FARG7 Arg8define HP_FARG9 HP_FARG8 Arg9define HP_FARG10 HP_FARG9 Arg10define HP_ARG0define HP_ARG1 arg1define HP_ARG2 HP_ARG1 arg2define HP_ARG3 HP_ARG2 arg3define HP_ARG4 HP_ARG3 arg4define HP_ARG5 HP_ARG4 arg5define HP_ARG6 HP_ARG5 arg6define HP_ARG7 HP_ARG6 arg7define HP_ARG8 HP_ARG7 arg8define HP_ARG9 HP_ARG8 arg9define HP_ARG10 HP_ARG9 arg10define HP_ARG_DECL0define HP_ARG_DECL1 Arg1 arg1define HP_ARG_DECL2 HP_ARG_DECL1 Arg2 arg2define HP_ARG_DECL3 HP_ARG_DECL2 Arg3 arg3define HP_ARG_DECL4 HP_ARG_DECL3 Arg4 arg4define HP_ARG_DECL5 HP_ARG_DECL4 Arg5 arg5define HP_ARG_DECL6 HP_ARG_DECL5 Arg6 arg6define HP_ARG_DECL7 HP_ARG_DECL6 Arg7 arg7define HP_ARG_DECL8 HP_ARG_DECL7 Arg8 arg8define HP_ARG_DECL9 HP_ARG_DECL8 Arg9 arg9define HP_ARG_DECL10 HP_ARG_DECL9 Arg10 arg10 template partial specialization for functionltreturn_type([arg_types])gtdefine HP_RET_FUNCTION(n callconv) template lttypename _Ret HP_TARGngt class functionlt_Ret callconv(HP_FARGn)gt public function_impllt_Ret callconv(HP_FARGn)gt

Sisteme de Operare - httpelfcspubrosowiki

Function Hooking and Windows Dll Injection 1415 26-11-2011

private typedef _Ret callconv type(HP_FARGn) public ~functionlttypegt() _RestoreProtection() using function_impllttypegtoperator= _Ret operator()(HP_ARG_DECLn) _NativeCallGuardlttypegt CallGuard(this) return (_pFun)(HP_ARGn) protected using function_impllttypegt_pFun declare the 11 templates handling functions in the form _Ret function() _Ret function(Arg1) _Ret function(Arg1 Arg2) _Ret function(Arg1 Arg2 Arg10) HP_RET_FUNCTION(0 __cdecl) HP_RET_FUNCTION(1 __cdecl) HP_RET_FUNCTION(2 __cdecl) HP_RET_FUNCTION(3 __cdecl) HP_RET_FUNCTION(4 __cdecl) HP_RET_FUNCTION(5 __cdecl) HP_RET_FUNCTION(6 __cdecl) HP_RET_FUNCTION(7 __cdecl) HP_RET_FUNCTION(8 __cdecl) HP_RET_FUNCTION(9 __cdecl) HP_RET_FUNCTION(10 __cdecl) ifndef _M_X64 HP_RET_FUNCTION(0 __stdcall) HP_RET_FUNCTION(1 __stdcall) HP_RET_FUNCTION(2 __stdcall) HP_RET_FUNCTION(3 __stdcall) HP_RET_FUNCTION(4 __stdcall) HP_RET_FUNCTION(5 __stdcall) HP_RET_FUNCTION(6 __stdcall) HP_RET_FUNCTION(7 __stdcall) HP_RET_FUNCTION(8 __stdcall) HP_RET_FUNCTION(9 __stdcall) HP_RET_FUNCTION(10 __stdcall)endif namespace HotPatch

What Im doing above is generating 11 partial tempate specializations for class HotPatchfunction The class isinspired by C++2011s stdfunction Its a class that models functions with up to 10 (included) arguments - you cansee the declarations through the HP_RET_FUNCTION macro calls in there Then another set of 11 declarations for x86-64where only calling convention __cdecl exists Do not worry abut understanding the above code its ugly and it sucksFocus on the usage instead it gets things done (for up to 10 arguments that is)

To use this HotPatch mini-lib write something like

HotPatchTestcppinclude ltcstdiogtinclude HotPatchhppusing namespace stdusing namespace HotPatch functionltvoid()gt fooPatch void foo() printf(In foo()n) void bar()

httpelfcspubrosowiki Printed on 20111126 0759

26-11-2011 1515 Function Hooking and Windows Dll Injection

printf(Im hackin ur functionn) if (fooPatchIsPatched()) fooPatch() int main() void (pfoo)() = foo void (pbar)() = bar pfoo() calls foo() pbar() calls bar() fooPatch = foo fooPatchSetPatch(bar) fooPatchApplyPatch() pfoo() calls bar() pbar() calls bar() fooPatchRemovePatch() pfoo() calls foo() pbar() calls bar() return 0

Further Info and Support

Im usually idling under the handle foxx1337 on ircfreenodenet on rosedu1) httpwwwkernelorgdocman-pagesonlinepagesman8ld-linuxso8html LD_PRELOAD2) httpsupportmicrosoftcomkb197571 AppInit_DLLs registry hack3) httpyosefkcomc++fqafunctionhtml4) Fraps5) RivaTuner6) MSI Afterburner7) Sockscap8) foobar20009) AutoHotkey10) Code Project Article on Code Injection11) Media Player Classic Homecinema12) httpcontinuationswordpresscom20110510hot-patching-unconditional-jumps-x86-x86-64 Article on 64 bit hotpatching

Fromhttpelfcspubrosowiki - Sisteme de Operare

Permanent linkhttpelfcspubrosowikilaboratoareresurseinjections

Last update 20111108 0213

Sisteme de Operare - httpelfcspubrosowiki

Page 7: Function Hooking and Windows Dll Injection.pdf

26-11-2011 715 Function Hooking and Windows Dll Injection

You can observe 2 problems in the current approach

the window is now blurry1the mouse hover effect is registered a few pixels off2

The blurriness problem happens because after removing the decorations (titlebar dialog borders) Windows tries tomaintain the program window within the same bounding rectangle In doing so it inflates the client area by a few pixelsin each direction pixels obtained from removing said decorations Indeed counting the pixels from the first picture we geta total window area (including borders) of 1616times858 and a client area (only the Direct3D part from within the borderswhere the application draws its updates) of 1600times820 pixels For the second picture we have a window area equal to theclient area (no more borders) of 1606times848 pixels Since Heroes of Newerth has a dialog frame (non-sizeable) it doesnttreat WM_SIZE messages the Direct3D context keeps rendering at the initial config file resolution and the resulting framebuffer gets drawn with stretching on top of a sligthly different window area so we dont have a perfect (logical)pixel-on-(screen )pixel mapping anymoreNote my config file for the game

snipSetSave vid_resolution 1600820snip

Heres a fix for keeping the client area of the window in place during the style change

Borderless2cppinclude ltcstdiogtusing namespace stdinclude ltwindowshgt int main() bool done = false while (done) HWND hwnd = FindWindow(NULL TEXT(Heroes of Newerth)) if (NULL = hwnd) LONG styles = GetWindowLong(hwnd GWL_STYLE) if (0 = styles) styles ^= WS_CAPTION bool deflate = 0 == (styles amp WS_CAPTION) RECT rc GetWindowRect(hwnd amprc) int captionHeight = GetSystemMetrics(SM_CYCAPTION) int borderWidth = GetSystemMetrics(SM_CXDLGFRAME) int borderHeight = GetSystemMetrics(SM_CYDLGFRAME)

Sisteme de Operare - httpelfcspubrosowiki

Function Hooking and Windows Dll Injection 815 26-11-2011

if (deflate) rcleft += borderWidth rcright -= borderWidth rctop += captionHeight + borderHeight rcbottom -= borderHeight else rcleft -= borderWidth rcright += borderWidth rctop -= captionHeight + borderHeight rcbottom += borderHeight LONG result = SetWindowLong(hwnd GWL_STYLE styles) if (0 = result) SetWindowPos(hwnd NULL rcleft rctop rcright - rcleft rcbottom - rctop SWP_FRAMECHANGED) char c scanf(c ampc) if (q == c) done = true return 0

A process such as Starcraft 2 owns a window with the WS_THICKFRAME style denoting a sizing border If I change the codeto remove that style from the Starcraft 2 main window (also SM_CTHICKFRAME instead of SM_CDLGFRAME I can onlynotice the mouse hover effect being off - the game catches WM_SIZE messages and adjusts the framebuffer accordingly

Fixing The Mouse Behavior

For the broken mouse hover effect its time to put The Injection to use Among the usual suspects for this problem are thewindow rectangle functions GetWindowRect() and GetClientRect() It would make sense due to the fact that games usuallyobtain mouse events through DirectInput that initially mouse coordinates are expressed in desktop-absolute form and notrelative to the application window Therefore theyd have to employ in one form or another a conversion between screen(absolute) coordinates and window coordinates in a similar manner to the operation of ClientToScreen()Lets take a look at an application window and the GetRect() logic relating to it

What the game does when handling mouse input is obtain some absolute screen coordinates from DirectInput convertthem to window coordinates then compensate for the window title and borders and then figure out what to do next with

httpelfcspubrosowiki Printed on 20111126 0759

26-11-2011 915 Function Hooking and Windows Dll Injection

the event Note that after removing the window decorations both GetWindowRect() and GetClientRect() return thesame coordinates Then the game compensates by subtracting the expected widths and heights of borders resulting inslightly off readings for the events The idea here is to modify at run-time GetWindowRect() so that it returns the oldrectangle with titlebar and borders as if the window style still contained those elements

The basic workflow for detouring GetWindowRect() is

insert exactly at the beginning of the function a jmp to our GetWindowRect() hot patch it1in our GetWindowRect() restore the code of the original function2call the original function and save the result3modify that result so that it fits our agenda4hot patch GetWindowRect() again5return the now modified result6

32 Bit Versus 64 Bit

Special care should be taken when moving to x86-64

Hot Patching

While the previous approach for hot patching a function (via relative jmp) is generally OK even in 64 bit mode there couldbe rare occasions when the distance between the patched function and the original one cant be expressed on only 32 bitsSince the specific form of jmp used expects a 32 bit displacement it would be useless in this case

The suggested solution here is a 64 bit absolute jump which comes by default with x86-6412) The idea here is just slightlydifferent than in the case of plain x86 While jmp accepted there as argument an immediate displacement the x86-64 longjump functions through an indirect register So wed simply load the destination address (not a distance any more for thisinstruction) into a register and pass that register as the operand to the jmp Fortunately x86-64 states that the special64-bit registries r10 and r11 arent preserved between call opcodes so picking r11 is a safe bet and guaranteed not toruin the program flow

Dll Injection

One cant insert an image compiled for 32 bits inside a 64 bit process and cant inject a 64 bit dll inside a 32 bit processThe idea is to have 2 separate programs making the dll injection 2 versions of the dll each of them for 64 bits andrespectively for 32 bits The 32 bit injector should set up the hooks as usual and launch a light weight version of itself thatonly sets up the hook and waits for an end event

Loader

TCHAR path[MAX_PATH] DWORD len = GetModuleFileName(NULL path MAX_PATH) while (path[len - 1] = ) --len MoveMemory(path + len TEXT(Deframe64dat) sizeof(TCHAR) (lstrlen(TEXT(Deframe64dat)) + 1)) STARTUPINFO siDeframe64 = sizeof(STARTUPINFO) PROCESS_INFORMATION piDeframe64 BOOL bRes = CreateProcess(0 path NULL NULL TRUE 0 NULL NULL ampsiDeframe64 amppiDeframe64) if (bRes) WaitForInputIdle(piDeframe64hProcess INFINITE) InstallHook()

Deframe64cppinclude ltwindowshgtinclude DeframeHelperh int WINAPI WinMain(HINSTANCE hInstance HINSTANCE hPrevInstance LPSTR lpCmdLine int nCmdShow) InstallHook() main message loop MSG msg while (GetMessage(ampmsg NULL 0 0) ampamp WM_QUIT = msgmessage) TranslateMessage(ampmsg) DispatchMessage(ampmsg)

Sisteme de Operare - httpelfcspubrosowiki

Function Hooking and Windows Dll Injection 1015 26-11-2011

RemoveHook() return static_castltintgt(msgwParam)

The first fragment of code residing in the normal 32 bit injector process first spawns a 64 bit child our Deframe64datThey both perform the same main function at this stage - calling InstallHook() which is exported by the guest dll Ivemessed with the output of Deframe64 so that it has the extension dat this is only an aesthetic step so that the userdoesnt accidentally launch the useless and with no means of terminating 64 bit process On 32 bit systemsCreateProcess() will fail and I simply ignore everything involving itHeres how the 32 bit injector terminates the 64 bit one

if (bRes) PostThreadMessage(piDeframe64dwThreadId WM_QUIT 0 0)

The Visual Studio 2010 Solution

All the required code can be found here Note that the project files wont work with the Express version of Visual Studiodue to the main program - Deframe being written with MFCFor a binary build see this archiveThe solution uses a C-like approach for the Injection

A C++ Template Library (for the impatient)

This code is not for the faint of heart C++ 2003 (talking about Microsoft Visual C 2010 here variadic template support)template code to simplify the hotpatching Include it and use it as exemplified further below (its not included in the sourcedownload)

HotPatchhpppragma once include ltwindowshgt HotPatch is a thin wrapper on top of the function hot patching layer It encapsulates a way to replace known functions with own functions by means of patching in jmps in both x86and x86-64 The basic workflow is 1 Declare HotPatchfunctionltftypegt thePatch assign target to this object with thePatch = target 2 set a replacement callback with thePatchSetPatch(myTarget) 3 call thePatchApply() to replace the target with the other callback In the replacement procedure

httpelfcspubrosowiki Printed on 20111126 0759

26-11-2011 1115 Function Hooking and Windows Dll Injection

31 do your stuff 32 call thePatch(arguments) 33 do other stuff When done 4 restore the opcodes with thePatchRemovePatch() 5 the destructor or assigning a new function to thePatch will restore the protection status of the memoryreferred by target Limitations wont work with variadic functions (blame C)namespace HotPatch class Exception class MemoryException public Exception class PatchException public Exception template lttypename FTypegt class function_impl public function_impl() _pFun(NULL) _pPatch(NULL) _detoured(false) ~function_impl() _RestoreProtection() res = function_implltFTypegtIsPatched() tells whether a call to the target will run the target or thehook Return value bool res - true if ApplyPatch() has been called without an accompanying RemovePatch() bool IsPatched() return _detoured function_implltFTypegtoperator=(pFun) directs the patch to a target and prepares the target memory forwrites Parameters FType pFun - the function to patch (see Apply()) Throws MemoryException - when changing the protection of the page where pFun points is impossible void operator=(FType pFun) _RestoreProtection() _pFun = pFun if (NULL == _pFun) return BOOL res = VirtualProtect(_pFun _64bit _PATCH_LENGTH64 _PATCH_LENGTH32 PAGE_EXECUTE_READWRITEamp_oldProtection) if (res) throw MemoryException() function_implltFTypegtSetPatch(patch[ alwaysUse32Bit]) prepares internal state for the patch Parameters FType patch - the patch to use instead of pFun (see operator=(FType )) bool alwaysUse32Bit - If true a 32 bit jmp is always inserted Else the best jmp is determined based on necessities (can still be 32 bit if it fits) Throws PatchException - if patch is NULL void SetPatch(FType patch bool alwaysUse32Bit = false) if (NULL == patch) throw PatchException() if (NULL = _pPatch) RemovePatch() _pPatch = patch _64bit = alwaysUse32Bit they havent expressed mandatory 32 bit only path try to guess the best path

Sisteme de Operare - httpelfcspubrosowiki

Function Hooking and Windows Dll Injection 1215 26-11-2011

if (_64bit) LONGLONG jumpDistance = reinterpret_castltLONGLONGgt(_pPatch) - reinterpret_castltLONGLONGgt(_pFun) - _PATCH_LENGTH32 if (abs(jumpDistance) gt 0x7FFFFFFF) the jump is too long to fit a regular 32 bit relative jmp _64bit = true else _64bit = false save the old patch opcodes plain old for is faster DO NOT call any library functions for (SIZE_T i = 0 i lt (_64bit _PATCH_LENGTH64 _PATCH_LENGTH32) ++i) (_backup + i) = (reinterpret_castltPBYTEgt(_pFun) + i) function_implltFTypegtApplyPatch() makes pFun (see operator=(FType )) jmp to patch (seeSetPatch(FType bool)) This is the actual hot patch mechanism at work void ApplyPatch() if (_64bit) movabs reinterpret_castltPBYTEgt(_pFun) = _OP_MOVABS r11 (reinterpret_castltPBYTEgt(_pFun) + 1) = _R11_WRITE _detourProc reinterpret_castltPLONGLONGgt(reinterpret_castltPBYTEgt(_pFun) + 2) =reinterpret_castltLONGLONGgt(_pPatch) jmp reinterpret_castltPWORDgt(reinterpret_castltPBYTEgt(_pFun) + 10) = _OP_JMP64 abs r11 (reinterpret_castltPBYTEgt(_pFun) + 12) = _R11_JMP else jmp reinterpret_castltPBYTEgt(_pFun) = _OP_JMP32 distance left to _detourProc reinterpret_castltPDWORDgt(reinterpret_castltPBYTEgt(_pFun) + 1) = static_castltDWORDgt( reinterpret_castltPBYTEgt(_pPatch) - reinterpret_castltPBYTEgt(_pFun) - static_castltDWORDgt(_PATCH_LENGTH32)) _detoured = true function_implltFTypegtRemovePatch() undoes what ApplyPatch() did pFun (see operator=(FType )) willbe its old self again void RemovePatch() plain old for is faster DO NOT call any library functions for (SIZE_T i = 0 i lt (_64bit _PATCH_LENGTH64 _PATCH_LENGTH32) ++i) (reinterpret_castltPBYTEgt(_pFun) + i) = (_backup + i) _detoured = false protected FType _pFun FType _pPatch bool _64bit bool _detoured BYTE _backup[13] DWORD _oldProtection static const BYTE _OP_JMP32 = 0xE9 static const WORD _OP_JMP64 = 0xFF41 static const BYTE _OP_MOVABS = 0x49 static const BYTE _R11_WRITE = 0xBB static const BYTE _R11_JMP = 0xE3 static const SIZE_T _PATCH_LENGTH32 = 5 jmp detourProc - originalProc = 1 + 4 static const SIZE_T _PATCH_LENGTH64 = 13 movabs R11 detourProc (64 bit) jmp (abs 64) R11 = 1+ 1 + 8 + 2 + 1 template lttypename Tgt static T abs(T val) return val gt 0 val -val

httpelfcspubrosowiki Printed on 20111126 0759

26-11-2011 1315 Function Hooking and Windows Dll Injection

void _RestoreProtection() if (NULL == _pFun) return DWORD unusedOldProtection BOOL res = VirtualProtect(_pFun _64bit _PATCH_LENGTH64 _PATCH_LENGTH32 _oldProtectionampunusedOldProtection) (void) res nothing to do template lttypename FTypegt class _NativeCallGuard public _NativeCallGuard(function_implltFTypegt ampfun) _fun(fun) _funRemovePatch() ~_NativeCallGuard() _funApplyPatch() private function_implltFTypegt amp_fun template lttypenamegt class function define HP_TARG0define HP_TARG1 typename Arg1define HP_TARG2 HP_TARG1 typename Arg2define HP_TARG3 HP_TARG2 typename Arg3define HP_TARG4 HP_TARG3 typename Arg4define HP_TARG5 HP_TARG4 typename Arg5define HP_TARG6 HP_TARG5 typename Arg6define HP_TARG7 HP_TARG6 typename Arg7define HP_TARG8 HP_TARG7 typename Arg8define HP_TARG9 HP_TARG8 typename Arg9define HP_TARG10 HP_TARG9 typename Arg10define HP_FARG0define HP_FARG1 Arg1define HP_FARG2 HP_FARG1 Arg2define HP_FARG3 HP_FARG2 Arg3define HP_FARG4 HP_FARG3 Arg4define HP_FARG5 HP_FARG4 Arg5define HP_FARG6 HP_FARG5 Arg6define HP_FARG7 HP_FARG6 Arg7define HP_FARG8 HP_FARG7 Arg8define HP_FARG9 HP_FARG8 Arg9define HP_FARG10 HP_FARG9 Arg10define HP_ARG0define HP_ARG1 arg1define HP_ARG2 HP_ARG1 arg2define HP_ARG3 HP_ARG2 arg3define HP_ARG4 HP_ARG3 arg4define HP_ARG5 HP_ARG4 arg5define HP_ARG6 HP_ARG5 arg6define HP_ARG7 HP_ARG6 arg7define HP_ARG8 HP_ARG7 arg8define HP_ARG9 HP_ARG8 arg9define HP_ARG10 HP_ARG9 arg10define HP_ARG_DECL0define HP_ARG_DECL1 Arg1 arg1define HP_ARG_DECL2 HP_ARG_DECL1 Arg2 arg2define HP_ARG_DECL3 HP_ARG_DECL2 Arg3 arg3define HP_ARG_DECL4 HP_ARG_DECL3 Arg4 arg4define HP_ARG_DECL5 HP_ARG_DECL4 Arg5 arg5define HP_ARG_DECL6 HP_ARG_DECL5 Arg6 arg6define HP_ARG_DECL7 HP_ARG_DECL6 Arg7 arg7define HP_ARG_DECL8 HP_ARG_DECL7 Arg8 arg8define HP_ARG_DECL9 HP_ARG_DECL8 Arg9 arg9define HP_ARG_DECL10 HP_ARG_DECL9 Arg10 arg10 template partial specialization for functionltreturn_type([arg_types])gtdefine HP_RET_FUNCTION(n callconv) template lttypename _Ret HP_TARGngt class functionlt_Ret callconv(HP_FARGn)gt public function_impllt_Ret callconv(HP_FARGn)gt

Sisteme de Operare - httpelfcspubrosowiki

Function Hooking and Windows Dll Injection 1415 26-11-2011

private typedef _Ret callconv type(HP_FARGn) public ~functionlttypegt() _RestoreProtection() using function_impllttypegtoperator= _Ret operator()(HP_ARG_DECLn) _NativeCallGuardlttypegt CallGuard(this) return (_pFun)(HP_ARGn) protected using function_impllttypegt_pFun declare the 11 templates handling functions in the form _Ret function() _Ret function(Arg1) _Ret function(Arg1 Arg2) _Ret function(Arg1 Arg2 Arg10) HP_RET_FUNCTION(0 __cdecl) HP_RET_FUNCTION(1 __cdecl) HP_RET_FUNCTION(2 __cdecl) HP_RET_FUNCTION(3 __cdecl) HP_RET_FUNCTION(4 __cdecl) HP_RET_FUNCTION(5 __cdecl) HP_RET_FUNCTION(6 __cdecl) HP_RET_FUNCTION(7 __cdecl) HP_RET_FUNCTION(8 __cdecl) HP_RET_FUNCTION(9 __cdecl) HP_RET_FUNCTION(10 __cdecl) ifndef _M_X64 HP_RET_FUNCTION(0 __stdcall) HP_RET_FUNCTION(1 __stdcall) HP_RET_FUNCTION(2 __stdcall) HP_RET_FUNCTION(3 __stdcall) HP_RET_FUNCTION(4 __stdcall) HP_RET_FUNCTION(5 __stdcall) HP_RET_FUNCTION(6 __stdcall) HP_RET_FUNCTION(7 __stdcall) HP_RET_FUNCTION(8 __stdcall) HP_RET_FUNCTION(9 __stdcall) HP_RET_FUNCTION(10 __stdcall)endif namespace HotPatch

What Im doing above is generating 11 partial tempate specializations for class HotPatchfunction The class isinspired by C++2011s stdfunction Its a class that models functions with up to 10 (included) arguments - you cansee the declarations through the HP_RET_FUNCTION macro calls in there Then another set of 11 declarations for x86-64where only calling convention __cdecl exists Do not worry abut understanding the above code its ugly and it sucksFocus on the usage instead it gets things done (for up to 10 arguments that is)

To use this HotPatch mini-lib write something like

HotPatchTestcppinclude ltcstdiogtinclude HotPatchhppusing namespace stdusing namespace HotPatch functionltvoid()gt fooPatch void foo() printf(In foo()n) void bar()

httpelfcspubrosowiki Printed on 20111126 0759

26-11-2011 1515 Function Hooking and Windows Dll Injection

printf(Im hackin ur functionn) if (fooPatchIsPatched()) fooPatch() int main() void (pfoo)() = foo void (pbar)() = bar pfoo() calls foo() pbar() calls bar() fooPatch = foo fooPatchSetPatch(bar) fooPatchApplyPatch() pfoo() calls bar() pbar() calls bar() fooPatchRemovePatch() pfoo() calls foo() pbar() calls bar() return 0

Further Info and Support

Im usually idling under the handle foxx1337 on ircfreenodenet on rosedu1) httpwwwkernelorgdocman-pagesonlinepagesman8ld-linuxso8html LD_PRELOAD2) httpsupportmicrosoftcomkb197571 AppInit_DLLs registry hack3) httpyosefkcomc++fqafunctionhtml4) Fraps5) RivaTuner6) MSI Afterburner7) Sockscap8) foobar20009) AutoHotkey10) Code Project Article on Code Injection11) Media Player Classic Homecinema12) httpcontinuationswordpresscom20110510hot-patching-unconditional-jumps-x86-x86-64 Article on 64 bit hotpatching

Fromhttpelfcspubrosowiki - Sisteme de Operare

Permanent linkhttpelfcspubrosowikilaboratoareresurseinjections

Last update 20111108 0213

Sisteme de Operare - httpelfcspubrosowiki

Page 8: Function Hooking and Windows Dll Injection.pdf

Function Hooking and Windows Dll Injection 815 26-11-2011

if (deflate) rcleft += borderWidth rcright -= borderWidth rctop += captionHeight + borderHeight rcbottom -= borderHeight else rcleft -= borderWidth rcright += borderWidth rctop -= captionHeight + borderHeight rcbottom += borderHeight LONG result = SetWindowLong(hwnd GWL_STYLE styles) if (0 = result) SetWindowPos(hwnd NULL rcleft rctop rcright - rcleft rcbottom - rctop SWP_FRAMECHANGED) char c scanf(c ampc) if (q == c) done = true return 0

A process such as Starcraft 2 owns a window with the WS_THICKFRAME style denoting a sizing border If I change the codeto remove that style from the Starcraft 2 main window (also SM_CTHICKFRAME instead of SM_CDLGFRAME I can onlynotice the mouse hover effect being off - the game catches WM_SIZE messages and adjusts the framebuffer accordingly

Fixing The Mouse Behavior

For the broken mouse hover effect its time to put The Injection to use Among the usual suspects for this problem are thewindow rectangle functions GetWindowRect() and GetClientRect() It would make sense due to the fact that games usuallyobtain mouse events through DirectInput that initially mouse coordinates are expressed in desktop-absolute form and notrelative to the application window Therefore theyd have to employ in one form or another a conversion between screen(absolute) coordinates and window coordinates in a similar manner to the operation of ClientToScreen()Lets take a look at an application window and the GetRect() logic relating to it

What the game does when handling mouse input is obtain some absolute screen coordinates from DirectInput convertthem to window coordinates then compensate for the window title and borders and then figure out what to do next with

httpelfcspubrosowiki Printed on 20111126 0759

26-11-2011 915 Function Hooking and Windows Dll Injection

the event Note that after removing the window decorations both GetWindowRect() and GetClientRect() return thesame coordinates Then the game compensates by subtracting the expected widths and heights of borders resulting inslightly off readings for the events The idea here is to modify at run-time GetWindowRect() so that it returns the oldrectangle with titlebar and borders as if the window style still contained those elements

The basic workflow for detouring GetWindowRect() is

insert exactly at the beginning of the function a jmp to our GetWindowRect() hot patch it1in our GetWindowRect() restore the code of the original function2call the original function and save the result3modify that result so that it fits our agenda4hot patch GetWindowRect() again5return the now modified result6

32 Bit Versus 64 Bit

Special care should be taken when moving to x86-64

Hot Patching

While the previous approach for hot patching a function (via relative jmp) is generally OK even in 64 bit mode there couldbe rare occasions when the distance between the patched function and the original one cant be expressed on only 32 bitsSince the specific form of jmp used expects a 32 bit displacement it would be useless in this case

The suggested solution here is a 64 bit absolute jump which comes by default with x86-6412) The idea here is just slightlydifferent than in the case of plain x86 While jmp accepted there as argument an immediate displacement the x86-64 longjump functions through an indirect register So wed simply load the destination address (not a distance any more for thisinstruction) into a register and pass that register as the operand to the jmp Fortunately x86-64 states that the special64-bit registries r10 and r11 arent preserved between call opcodes so picking r11 is a safe bet and guaranteed not toruin the program flow

Dll Injection

One cant insert an image compiled for 32 bits inside a 64 bit process and cant inject a 64 bit dll inside a 32 bit processThe idea is to have 2 separate programs making the dll injection 2 versions of the dll each of them for 64 bits andrespectively for 32 bits The 32 bit injector should set up the hooks as usual and launch a light weight version of itself thatonly sets up the hook and waits for an end event

Loader

TCHAR path[MAX_PATH] DWORD len = GetModuleFileName(NULL path MAX_PATH) while (path[len - 1] = ) --len MoveMemory(path + len TEXT(Deframe64dat) sizeof(TCHAR) (lstrlen(TEXT(Deframe64dat)) + 1)) STARTUPINFO siDeframe64 = sizeof(STARTUPINFO) PROCESS_INFORMATION piDeframe64 BOOL bRes = CreateProcess(0 path NULL NULL TRUE 0 NULL NULL ampsiDeframe64 amppiDeframe64) if (bRes) WaitForInputIdle(piDeframe64hProcess INFINITE) InstallHook()

Deframe64cppinclude ltwindowshgtinclude DeframeHelperh int WINAPI WinMain(HINSTANCE hInstance HINSTANCE hPrevInstance LPSTR lpCmdLine int nCmdShow) InstallHook() main message loop MSG msg while (GetMessage(ampmsg NULL 0 0) ampamp WM_QUIT = msgmessage) TranslateMessage(ampmsg) DispatchMessage(ampmsg)

Sisteme de Operare - httpelfcspubrosowiki

Function Hooking and Windows Dll Injection 1015 26-11-2011

RemoveHook() return static_castltintgt(msgwParam)

The first fragment of code residing in the normal 32 bit injector process first spawns a 64 bit child our Deframe64datThey both perform the same main function at this stage - calling InstallHook() which is exported by the guest dll Ivemessed with the output of Deframe64 so that it has the extension dat this is only an aesthetic step so that the userdoesnt accidentally launch the useless and with no means of terminating 64 bit process On 32 bit systemsCreateProcess() will fail and I simply ignore everything involving itHeres how the 32 bit injector terminates the 64 bit one

if (bRes) PostThreadMessage(piDeframe64dwThreadId WM_QUIT 0 0)

The Visual Studio 2010 Solution

All the required code can be found here Note that the project files wont work with the Express version of Visual Studiodue to the main program - Deframe being written with MFCFor a binary build see this archiveThe solution uses a C-like approach for the Injection

A C++ Template Library (for the impatient)

This code is not for the faint of heart C++ 2003 (talking about Microsoft Visual C 2010 here variadic template support)template code to simplify the hotpatching Include it and use it as exemplified further below (its not included in the sourcedownload)

HotPatchhpppragma once include ltwindowshgt HotPatch is a thin wrapper on top of the function hot patching layer It encapsulates a way to replace known functions with own functions by means of patching in jmps in both x86and x86-64 The basic workflow is 1 Declare HotPatchfunctionltftypegt thePatch assign target to this object with thePatch = target 2 set a replacement callback with thePatchSetPatch(myTarget) 3 call thePatchApply() to replace the target with the other callback In the replacement procedure

httpelfcspubrosowiki Printed on 20111126 0759

26-11-2011 1115 Function Hooking and Windows Dll Injection

31 do your stuff 32 call thePatch(arguments) 33 do other stuff When done 4 restore the opcodes with thePatchRemovePatch() 5 the destructor or assigning a new function to thePatch will restore the protection status of the memoryreferred by target Limitations wont work with variadic functions (blame C)namespace HotPatch class Exception class MemoryException public Exception class PatchException public Exception template lttypename FTypegt class function_impl public function_impl() _pFun(NULL) _pPatch(NULL) _detoured(false) ~function_impl() _RestoreProtection() res = function_implltFTypegtIsPatched() tells whether a call to the target will run the target or thehook Return value bool res - true if ApplyPatch() has been called without an accompanying RemovePatch() bool IsPatched() return _detoured function_implltFTypegtoperator=(pFun) directs the patch to a target and prepares the target memory forwrites Parameters FType pFun - the function to patch (see Apply()) Throws MemoryException - when changing the protection of the page where pFun points is impossible void operator=(FType pFun) _RestoreProtection() _pFun = pFun if (NULL == _pFun) return BOOL res = VirtualProtect(_pFun _64bit _PATCH_LENGTH64 _PATCH_LENGTH32 PAGE_EXECUTE_READWRITEamp_oldProtection) if (res) throw MemoryException() function_implltFTypegtSetPatch(patch[ alwaysUse32Bit]) prepares internal state for the patch Parameters FType patch - the patch to use instead of pFun (see operator=(FType )) bool alwaysUse32Bit - If true a 32 bit jmp is always inserted Else the best jmp is determined based on necessities (can still be 32 bit if it fits) Throws PatchException - if patch is NULL void SetPatch(FType patch bool alwaysUse32Bit = false) if (NULL == patch) throw PatchException() if (NULL = _pPatch) RemovePatch() _pPatch = patch _64bit = alwaysUse32Bit they havent expressed mandatory 32 bit only path try to guess the best path

Sisteme de Operare - httpelfcspubrosowiki

Function Hooking and Windows Dll Injection 1215 26-11-2011

if (_64bit) LONGLONG jumpDistance = reinterpret_castltLONGLONGgt(_pPatch) - reinterpret_castltLONGLONGgt(_pFun) - _PATCH_LENGTH32 if (abs(jumpDistance) gt 0x7FFFFFFF) the jump is too long to fit a regular 32 bit relative jmp _64bit = true else _64bit = false save the old patch opcodes plain old for is faster DO NOT call any library functions for (SIZE_T i = 0 i lt (_64bit _PATCH_LENGTH64 _PATCH_LENGTH32) ++i) (_backup + i) = (reinterpret_castltPBYTEgt(_pFun) + i) function_implltFTypegtApplyPatch() makes pFun (see operator=(FType )) jmp to patch (seeSetPatch(FType bool)) This is the actual hot patch mechanism at work void ApplyPatch() if (_64bit) movabs reinterpret_castltPBYTEgt(_pFun) = _OP_MOVABS r11 (reinterpret_castltPBYTEgt(_pFun) + 1) = _R11_WRITE _detourProc reinterpret_castltPLONGLONGgt(reinterpret_castltPBYTEgt(_pFun) + 2) =reinterpret_castltLONGLONGgt(_pPatch) jmp reinterpret_castltPWORDgt(reinterpret_castltPBYTEgt(_pFun) + 10) = _OP_JMP64 abs r11 (reinterpret_castltPBYTEgt(_pFun) + 12) = _R11_JMP else jmp reinterpret_castltPBYTEgt(_pFun) = _OP_JMP32 distance left to _detourProc reinterpret_castltPDWORDgt(reinterpret_castltPBYTEgt(_pFun) + 1) = static_castltDWORDgt( reinterpret_castltPBYTEgt(_pPatch) - reinterpret_castltPBYTEgt(_pFun) - static_castltDWORDgt(_PATCH_LENGTH32)) _detoured = true function_implltFTypegtRemovePatch() undoes what ApplyPatch() did pFun (see operator=(FType )) willbe its old self again void RemovePatch() plain old for is faster DO NOT call any library functions for (SIZE_T i = 0 i lt (_64bit _PATCH_LENGTH64 _PATCH_LENGTH32) ++i) (reinterpret_castltPBYTEgt(_pFun) + i) = (_backup + i) _detoured = false protected FType _pFun FType _pPatch bool _64bit bool _detoured BYTE _backup[13] DWORD _oldProtection static const BYTE _OP_JMP32 = 0xE9 static const WORD _OP_JMP64 = 0xFF41 static const BYTE _OP_MOVABS = 0x49 static const BYTE _R11_WRITE = 0xBB static const BYTE _R11_JMP = 0xE3 static const SIZE_T _PATCH_LENGTH32 = 5 jmp detourProc - originalProc = 1 + 4 static const SIZE_T _PATCH_LENGTH64 = 13 movabs R11 detourProc (64 bit) jmp (abs 64) R11 = 1+ 1 + 8 + 2 + 1 template lttypename Tgt static T abs(T val) return val gt 0 val -val

httpelfcspubrosowiki Printed on 20111126 0759

26-11-2011 1315 Function Hooking and Windows Dll Injection

void _RestoreProtection() if (NULL == _pFun) return DWORD unusedOldProtection BOOL res = VirtualProtect(_pFun _64bit _PATCH_LENGTH64 _PATCH_LENGTH32 _oldProtectionampunusedOldProtection) (void) res nothing to do template lttypename FTypegt class _NativeCallGuard public _NativeCallGuard(function_implltFTypegt ampfun) _fun(fun) _funRemovePatch() ~_NativeCallGuard() _funApplyPatch() private function_implltFTypegt amp_fun template lttypenamegt class function define HP_TARG0define HP_TARG1 typename Arg1define HP_TARG2 HP_TARG1 typename Arg2define HP_TARG3 HP_TARG2 typename Arg3define HP_TARG4 HP_TARG3 typename Arg4define HP_TARG5 HP_TARG4 typename Arg5define HP_TARG6 HP_TARG5 typename Arg6define HP_TARG7 HP_TARG6 typename Arg7define HP_TARG8 HP_TARG7 typename Arg8define HP_TARG9 HP_TARG8 typename Arg9define HP_TARG10 HP_TARG9 typename Arg10define HP_FARG0define HP_FARG1 Arg1define HP_FARG2 HP_FARG1 Arg2define HP_FARG3 HP_FARG2 Arg3define HP_FARG4 HP_FARG3 Arg4define HP_FARG5 HP_FARG4 Arg5define HP_FARG6 HP_FARG5 Arg6define HP_FARG7 HP_FARG6 Arg7define HP_FARG8 HP_FARG7 Arg8define HP_FARG9 HP_FARG8 Arg9define HP_FARG10 HP_FARG9 Arg10define HP_ARG0define HP_ARG1 arg1define HP_ARG2 HP_ARG1 arg2define HP_ARG3 HP_ARG2 arg3define HP_ARG4 HP_ARG3 arg4define HP_ARG5 HP_ARG4 arg5define HP_ARG6 HP_ARG5 arg6define HP_ARG7 HP_ARG6 arg7define HP_ARG8 HP_ARG7 arg8define HP_ARG9 HP_ARG8 arg9define HP_ARG10 HP_ARG9 arg10define HP_ARG_DECL0define HP_ARG_DECL1 Arg1 arg1define HP_ARG_DECL2 HP_ARG_DECL1 Arg2 arg2define HP_ARG_DECL3 HP_ARG_DECL2 Arg3 arg3define HP_ARG_DECL4 HP_ARG_DECL3 Arg4 arg4define HP_ARG_DECL5 HP_ARG_DECL4 Arg5 arg5define HP_ARG_DECL6 HP_ARG_DECL5 Arg6 arg6define HP_ARG_DECL7 HP_ARG_DECL6 Arg7 arg7define HP_ARG_DECL8 HP_ARG_DECL7 Arg8 arg8define HP_ARG_DECL9 HP_ARG_DECL8 Arg9 arg9define HP_ARG_DECL10 HP_ARG_DECL9 Arg10 arg10 template partial specialization for functionltreturn_type([arg_types])gtdefine HP_RET_FUNCTION(n callconv) template lttypename _Ret HP_TARGngt class functionlt_Ret callconv(HP_FARGn)gt public function_impllt_Ret callconv(HP_FARGn)gt

Sisteme de Operare - httpelfcspubrosowiki

Function Hooking and Windows Dll Injection 1415 26-11-2011

private typedef _Ret callconv type(HP_FARGn) public ~functionlttypegt() _RestoreProtection() using function_impllttypegtoperator= _Ret operator()(HP_ARG_DECLn) _NativeCallGuardlttypegt CallGuard(this) return (_pFun)(HP_ARGn) protected using function_impllttypegt_pFun declare the 11 templates handling functions in the form _Ret function() _Ret function(Arg1) _Ret function(Arg1 Arg2) _Ret function(Arg1 Arg2 Arg10) HP_RET_FUNCTION(0 __cdecl) HP_RET_FUNCTION(1 __cdecl) HP_RET_FUNCTION(2 __cdecl) HP_RET_FUNCTION(3 __cdecl) HP_RET_FUNCTION(4 __cdecl) HP_RET_FUNCTION(5 __cdecl) HP_RET_FUNCTION(6 __cdecl) HP_RET_FUNCTION(7 __cdecl) HP_RET_FUNCTION(8 __cdecl) HP_RET_FUNCTION(9 __cdecl) HP_RET_FUNCTION(10 __cdecl) ifndef _M_X64 HP_RET_FUNCTION(0 __stdcall) HP_RET_FUNCTION(1 __stdcall) HP_RET_FUNCTION(2 __stdcall) HP_RET_FUNCTION(3 __stdcall) HP_RET_FUNCTION(4 __stdcall) HP_RET_FUNCTION(5 __stdcall) HP_RET_FUNCTION(6 __stdcall) HP_RET_FUNCTION(7 __stdcall) HP_RET_FUNCTION(8 __stdcall) HP_RET_FUNCTION(9 __stdcall) HP_RET_FUNCTION(10 __stdcall)endif namespace HotPatch

What Im doing above is generating 11 partial tempate specializations for class HotPatchfunction The class isinspired by C++2011s stdfunction Its a class that models functions with up to 10 (included) arguments - you cansee the declarations through the HP_RET_FUNCTION macro calls in there Then another set of 11 declarations for x86-64where only calling convention __cdecl exists Do not worry abut understanding the above code its ugly and it sucksFocus on the usage instead it gets things done (for up to 10 arguments that is)

To use this HotPatch mini-lib write something like

HotPatchTestcppinclude ltcstdiogtinclude HotPatchhppusing namespace stdusing namespace HotPatch functionltvoid()gt fooPatch void foo() printf(In foo()n) void bar()

httpelfcspubrosowiki Printed on 20111126 0759

26-11-2011 1515 Function Hooking and Windows Dll Injection

printf(Im hackin ur functionn) if (fooPatchIsPatched()) fooPatch() int main() void (pfoo)() = foo void (pbar)() = bar pfoo() calls foo() pbar() calls bar() fooPatch = foo fooPatchSetPatch(bar) fooPatchApplyPatch() pfoo() calls bar() pbar() calls bar() fooPatchRemovePatch() pfoo() calls foo() pbar() calls bar() return 0

Further Info and Support

Im usually idling under the handle foxx1337 on ircfreenodenet on rosedu1) httpwwwkernelorgdocman-pagesonlinepagesman8ld-linuxso8html LD_PRELOAD2) httpsupportmicrosoftcomkb197571 AppInit_DLLs registry hack3) httpyosefkcomc++fqafunctionhtml4) Fraps5) RivaTuner6) MSI Afterburner7) Sockscap8) foobar20009) AutoHotkey10) Code Project Article on Code Injection11) Media Player Classic Homecinema12) httpcontinuationswordpresscom20110510hot-patching-unconditional-jumps-x86-x86-64 Article on 64 bit hotpatching

Fromhttpelfcspubrosowiki - Sisteme de Operare

Permanent linkhttpelfcspubrosowikilaboratoareresurseinjections

Last update 20111108 0213

Sisteme de Operare - httpelfcspubrosowiki

Page 9: Function Hooking and Windows Dll Injection.pdf

26-11-2011 915 Function Hooking and Windows Dll Injection

the event Note that after removing the window decorations both GetWindowRect() and GetClientRect() return thesame coordinates Then the game compensates by subtracting the expected widths and heights of borders resulting inslightly off readings for the events The idea here is to modify at run-time GetWindowRect() so that it returns the oldrectangle with titlebar and borders as if the window style still contained those elements

The basic workflow for detouring GetWindowRect() is

insert exactly at the beginning of the function a jmp to our GetWindowRect() hot patch it1in our GetWindowRect() restore the code of the original function2call the original function and save the result3modify that result so that it fits our agenda4hot patch GetWindowRect() again5return the now modified result6

32 Bit Versus 64 Bit

Special care should be taken when moving to x86-64

Hot Patching

While the previous approach for hot patching a function (via relative jmp) is generally OK even in 64 bit mode there couldbe rare occasions when the distance between the patched function and the original one cant be expressed on only 32 bitsSince the specific form of jmp used expects a 32 bit displacement it would be useless in this case

The suggested solution here is a 64 bit absolute jump which comes by default with x86-6412) The idea here is just slightlydifferent than in the case of plain x86 While jmp accepted there as argument an immediate displacement the x86-64 longjump functions through an indirect register So wed simply load the destination address (not a distance any more for thisinstruction) into a register and pass that register as the operand to the jmp Fortunately x86-64 states that the special64-bit registries r10 and r11 arent preserved between call opcodes so picking r11 is a safe bet and guaranteed not toruin the program flow

Dll Injection

One cant insert an image compiled for 32 bits inside a 64 bit process and cant inject a 64 bit dll inside a 32 bit processThe idea is to have 2 separate programs making the dll injection 2 versions of the dll each of them for 64 bits andrespectively for 32 bits The 32 bit injector should set up the hooks as usual and launch a light weight version of itself thatonly sets up the hook and waits for an end event

Loader

TCHAR path[MAX_PATH] DWORD len = GetModuleFileName(NULL path MAX_PATH) while (path[len - 1] = ) --len MoveMemory(path + len TEXT(Deframe64dat) sizeof(TCHAR) (lstrlen(TEXT(Deframe64dat)) + 1)) STARTUPINFO siDeframe64 = sizeof(STARTUPINFO) PROCESS_INFORMATION piDeframe64 BOOL bRes = CreateProcess(0 path NULL NULL TRUE 0 NULL NULL ampsiDeframe64 amppiDeframe64) if (bRes) WaitForInputIdle(piDeframe64hProcess INFINITE) InstallHook()

Deframe64cppinclude ltwindowshgtinclude DeframeHelperh int WINAPI WinMain(HINSTANCE hInstance HINSTANCE hPrevInstance LPSTR lpCmdLine int nCmdShow) InstallHook() main message loop MSG msg while (GetMessage(ampmsg NULL 0 0) ampamp WM_QUIT = msgmessage) TranslateMessage(ampmsg) DispatchMessage(ampmsg)

Sisteme de Operare - httpelfcspubrosowiki

Function Hooking and Windows Dll Injection 1015 26-11-2011

RemoveHook() return static_castltintgt(msgwParam)

The first fragment of code residing in the normal 32 bit injector process first spawns a 64 bit child our Deframe64datThey both perform the same main function at this stage - calling InstallHook() which is exported by the guest dll Ivemessed with the output of Deframe64 so that it has the extension dat this is only an aesthetic step so that the userdoesnt accidentally launch the useless and with no means of terminating 64 bit process On 32 bit systemsCreateProcess() will fail and I simply ignore everything involving itHeres how the 32 bit injector terminates the 64 bit one

if (bRes) PostThreadMessage(piDeframe64dwThreadId WM_QUIT 0 0)

The Visual Studio 2010 Solution

All the required code can be found here Note that the project files wont work with the Express version of Visual Studiodue to the main program - Deframe being written with MFCFor a binary build see this archiveThe solution uses a C-like approach for the Injection

A C++ Template Library (for the impatient)

This code is not for the faint of heart C++ 2003 (talking about Microsoft Visual C 2010 here variadic template support)template code to simplify the hotpatching Include it and use it as exemplified further below (its not included in the sourcedownload)

HotPatchhpppragma once include ltwindowshgt HotPatch is a thin wrapper on top of the function hot patching layer It encapsulates a way to replace known functions with own functions by means of patching in jmps in both x86and x86-64 The basic workflow is 1 Declare HotPatchfunctionltftypegt thePatch assign target to this object with thePatch = target 2 set a replacement callback with thePatchSetPatch(myTarget) 3 call thePatchApply() to replace the target with the other callback In the replacement procedure

httpelfcspubrosowiki Printed on 20111126 0759

26-11-2011 1115 Function Hooking and Windows Dll Injection

31 do your stuff 32 call thePatch(arguments) 33 do other stuff When done 4 restore the opcodes with thePatchRemovePatch() 5 the destructor or assigning a new function to thePatch will restore the protection status of the memoryreferred by target Limitations wont work with variadic functions (blame C)namespace HotPatch class Exception class MemoryException public Exception class PatchException public Exception template lttypename FTypegt class function_impl public function_impl() _pFun(NULL) _pPatch(NULL) _detoured(false) ~function_impl() _RestoreProtection() res = function_implltFTypegtIsPatched() tells whether a call to the target will run the target or thehook Return value bool res - true if ApplyPatch() has been called without an accompanying RemovePatch() bool IsPatched() return _detoured function_implltFTypegtoperator=(pFun) directs the patch to a target and prepares the target memory forwrites Parameters FType pFun - the function to patch (see Apply()) Throws MemoryException - when changing the protection of the page where pFun points is impossible void operator=(FType pFun) _RestoreProtection() _pFun = pFun if (NULL == _pFun) return BOOL res = VirtualProtect(_pFun _64bit _PATCH_LENGTH64 _PATCH_LENGTH32 PAGE_EXECUTE_READWRITEamp_oldProtection) if (res) throw MemoryException() function_implltFTypegtSetPatch(patch[ alwaysUse32Bit]) prepares internal state for the patch Parameters FType patch - the patch to use instead of pFun (see operator=(FType )) bool alwaysUse32Bit - If true a 32 bit jmp is always inserted Else the best jmp is determined based on necessities (can still be 32 bit if it fits) Throws PatchException - if patch is NULL void SetPatch(FType patch bool alwaysUse32Bit = false) if (NULL == patch) throw PatchException() if (NULL = _pPatch) RemovePatch() _pPatch = patch _64bit = alwaysUse32Bit they havent expressed mandatory 32 bit only path try to guess the best path

Sisteme de Operare - httpelfcspubrosowiki

Function Hooking and Windows Dll Injection 1215 26-11-2011

if (_64bit) LONGLONG jumpDistance = reinterpret_castltLONGLONGgt(_pPatch) - reinterpret_castltLONGLONGgt(_pFun) - _PATCH_LENGTH32 if (abs(jumpDistance) gt 0x7FFFFFFF) the jump is too long to fit a regular 32 bit relative jmp _64bit = true else _64bit = false save the old patch opcodes plain old for is faster DO NOT call any library functions for (SIZE_T i = 0 i lt (_64bit _PATCH_LENGTH64 _PATCH_LENGTH32) ++i) (_backup + i) = (reinterpret_castltPBYTEgt(_pFun) + i) function_implltFTypegtApplyPatch() makes pFun (see operator=(FType )) jmp to patch (seeSetPatch(FType bool)) This is the actual hot patch mechanism at work void ApplyPatch() if (_64bit) movabs reinterpret_castltPBYTEgt(_pFun) = _OP_MOVABS r11 (reinterpret_castltPBYTEgt(_pFun) + 1) = _R11_WRITE _detourProc reinterpret_castltPLONGLONGgt(reinterpret_castltPBYTEgt(_pFun) + 2) =reinterpret_castltLONGLONGgt(_pPatch) jmp reinterpret_castltPWORDgt(reinterpret_castltPBYTEgt(_pFun) + 10) = _OP_JMP64 abs r11 (reinterpret_castltPBYTEgt(_pFun) + 12) = _R11_JMP else jmp reinterpret_castltPBYTEgt(_pFun) = _OP_JMP32 distance left to _detourProc reinterpret_castltPDWORDgt(reinterpret_castltPBYTEgt(_pFun) + 1) = static_castltDWORDgt( reinterpret_castltPBYTEgt(_pPatch) - reinterpret_castltPBYTEgt(_pFun) - static_castltDWORDgt(_PATCH_LENGTH32)) _detoured = true function_implltFTypegtRemovePatch() undoes what ApplyPatch() did pFun (see operator=(FType )) willbe its old self again void RemovePatch() plain old for is faster DO NOT call any library functions for (SIZE_T i = 0 i lt (_64bit _PATCH_LENGTH64 _PATCH_LENGTH32) ++i) (reinterpret_castltPBYTEgt(_pFun) + i) = (_backup + i) _detoured = false protected FType _pFun FType _pPatch bool _64bit bool _detoured BYTE _backup[13] DWORD _oldProtection static const BYTE _OP_JMP32 = 0xE9 static const WORD _OP_JMP64 = 0xFF41 static const BYTE _OP_MOVABS = 0x49 static const BYTE _R11_WRITE = 0xBB static const BYTE _R11_JMP = 0xE3 static const SIZE_T _PATCH_LENGTH32 = 5 jmp detourProc - originalProc = 1 + 4 static const SIZE_T _PATCH_LENGTH64 = 13 movabs R11 detourProc (64 bit) jmp (abs 64) R11 = 1+ 1 + 8 + 2 + 1 template lttypename Tgt static T abs(T val) return val gt 0 val -val

httpelfcspubrosowiki Printed on 20111126 0759

26-11-2011 1315 Function Hooking and Windows Dll Injection

void _RestoreProtection() if (NULL == _pFun) return DWORD unusedOldProtection BOOL res = VirtualProtect(_pFun _64bit _PATCH_LENGTH64 _PATCH_LENGTH32 _oldProtectionampunusedOldProtection) (void) res nothing to do template lttypename FTypegt class _NativeCallGuard public _NativeCallGuard(function_implltFTypegt ampfun) _fun(fun) _funRemovePatch() ~_NativeCallGuard() _funApplyPatch() private function_implltFTypegt amp_fun template lttypenamegt class function define HP_TARG0define HP_TARG1 typename Arg1define HP_TARG2 HP_TARG1 typename Arg2define HP_TARG3 HP_TARG2 typename Arg3define HP_TARG4 HP_TARG3 typename Arg4define HP_TARG5 HP_TARG4 typename Arg5define HP_TARG6 HP_TARG5 typename Arg6define HP_TARG7 HP_TARG6 typename Arg7define HP_TARG8 HP_TARG7 typename Arg8define HP_TARG9 HP_TARG8 typename Arg9define HP_TARG10 HP_TARG9 typename Arg10define HP_FARG0define HP_FARG1 Arg1define HP_FARG2 HP_FARG1 Arg2define HP_FARG3 HP_FARG2 Arg3define HP_FARG4 HP_FARG3 Arg4define HP_FARG5 HP_FARG4 Arg5define HP_FARG6 HP_FARG5 Arg6define HP_FARG7 HP_FARG6 Arg7define HP_FARG8 HP_FARG7 Arg8define HP_FARG9 HP_FARG8 Arg9define HP_FARG10 HP_FARG9 Arg10define HP_ARG0define HP_ARG1 arg1define HP_ARG2 HP_ARG1 arg2define HP_ARG3 HP_ARG2 arg3define HP_ARG4 HP_ARG3 arg4define HP_ARG5 HP_ARG4 arg5define HP_ARG6 HP_ARG5 arg6define HP_ARG7 HP_ARG6 arg7define HP_ARG8 HP_ARG7 arg8define HP_ARG9 HP_ARG8 arg9define HP_ARG10 HP_ARG9 arg10define HP_ARG_DECL0define HP_ARG_DECL1 Arg1 arg1define HP_ARG_DECL2 HP_ARG_DECL1 Arg2 arg2define HP_ARG_DECL3 HP_ARG_DECL2 Arg3 arg3define HP_ARG_DECL4 HP_ARG_DECL3 Arg4 arg4define HP_ARG_DECL5 HP_ARG_DECL4 Arg5 arg5define HP_ARG_DECL6 HP_ARG_DECL5 Arg6 arg6define HP_ARG_DECL7 HP_ARG_DECL6 Arg7 arg7define HP_ARG_DECL8 HP_ARG_DECL7 Arg8 arg8define HP_ARG_DECL9 HP_ARG_DECL8 Arg9 arg9define HP_ARG_DECL10 HP_ARG_DECL9 Arg10 arg10 template partial specialization for functionltreturn_type([arg_types])gtdefine HP_RET_FUNCTION(n callconv) template lttypename _Ret HP_TARGngt class functionlt_Ret callconv(HP_FARGn)gt public function_impllt_Ret callconv(HP_FARGn)gt

Sisteme de Operare - httpelfcspubrosowiki

Function Hooking and Windows Dll Injection 1415 26-11-2011

private typedef _Ret callconv type(HP_FARGn) public ~functionlttypegt() _RestoreProtection() using function_impllttypegtoperator= _Ret operator()(HP_ARG_DECLn) _NativeCallGuardlttypegt CallGuard(this) return (_pFun)(HP_ARGn) protected using function_impllttypegt_pFun declare the 11 templates handling functions in the form _Ret function() _Ret function(Arg1) _Ret function(Arg1 Arg2) _Ret function(Arg1 Arg2 Arg10) HP_RET_FUNCTION(0 __cdecl) HP_RET_FUNCTION(1 __cdecl) HP_RET_FUNCTION(2 __cdecl) HP_RET_FUNCTION(3 __cdecl) HP_RET_FUNCTION(4 __cdecl) HP_RET_FUNCTION(5 __cdecl) HP_RET_FUNCTION(6 __cdecl) HP_RET_FUNCTION(7 __cdecl) HP_RET_FUNCTION(8 __cdecl) HP_RET_FUNCTION(9 __cdecl) HP_RET_FUNCTION(10 __cdecl) ifndef _M_X64 HP_RET_FUNCTION(0 __stdcall) HP_RET_FUNCTION(1 __stdcall) HP_RET_FUNCTION(2 __stdcall) HP_RET_FUNCTION(3 __stdcall) HP_RET_FUNCTION(4 __stdcall) HP_RET_FUNCTION(5 __stdcall) HP_RET_FUNCTION(6 __stdcall) HP_RET_FUNCTION(7 __stdcall) HP_RET_FUNCTION(8 __stdcall) HP_RET_FUNCTION(9 __stdcall) HP_RET_FUNCTION(10 __stdcall)endif namespace HotPatch

What Im doing above is generating 11 partial tempate specializations for class HotPatchfunction The class isinspired by C++2011s stdfunction Its a class that models functions with up to 10 (included) arguments - you cansee the declarations through the HP_RET_FUNCTION macro calls in there Then another set of 11 declarations for x86-64where only calling convention __cdecl exists Do not worry abut understanding the above code its ugly and it sucksFocus on the usage instead it gets things done (for up to 10 arguments that is)

To use this HotPatch mini-lib write something like

HotPatchTestcppinclude ltcstdiogtinclude HotPatchhppusing namespace stdusing namespace HotPatch functionltvoid()gt fooPatch void foo() printf(In foo()n) void bar()

httpelfcspubrosowiki Printed on 20111126 0759

26-11-2011 1515 Function Hooking and Windows Dll Injection

printf(Im hackin ur functionn) if (fooPatchIsPatched()) fooPatch() int main() void (pfoo)() = foo void (pbar)() = bar pfoo() calls foo() pbar() calls bar() fooPatch = foo fooPatchSetPatch(bar) fooPatchApplyPatch() pfoo() calls bar() pbar() calls bar() fooPatchRemovePatch() pfoo() calls foo() pbar() calls bar() return 0

Further Info and Support

Im usually idling under the handle foxx1337 on ircfreenodenet on rosedu1) httpwwwkernelorgdocman-pagesonlinepagesman8ld-linuxso8html LD_PRELOAD2) httpsupportmicrosoftcomkb197571 AppInit_DLLs registry hack3) httpyosefkcomc++fqafunctionhtml4) Fraps5) RivaTuner6) MSI Afterburner7) Sockscap8) foobar20009) AutoHotkey10) Code Project Article on Code Injection11) Media Player Classic Homecinema12) httpcontinuationswordpresscom20110510hot-patching-unconditional-jumps-x86-x86-64 Article on 64 bit hotpatching

Fromhttpelfcspubrosowiki - Sisteme de Operare

Permanent linkhttpelfcspubrosowikilaboratoareresurseinjections

Last update 20111108 0213

Sisteme de Operare - httpelfcspubrosowiki

Page 10: Function Hooking and Windows Dll Injection.pdf

Function Hooking and Windows Dll Injection 1015 26-11-2011

RemoveHook() return static_castltintgt(msgwParam)

The first fragment of code residing in the normal 32 bit injector process first spawns a 64 bit child our Deframe64datThey both perform the same main function at this stage - calling InstallHook() which is exported by the guest dll Ivemessed with the output of Deframe64 so that it has the extension dat this is only an aesthetic step so that the userdoesnt accidentally launch the useless and with no means of terminating 64 bit process On 32 bit systemsCreateProcess() will fail and I simply ignore everything involving itHeres how the 32 bit injector terminates the 64 bit one

if (bRes) PostThreadMessage(piDeframe64dwThreadId WM_QUIT 0 0)

The Visual Studio 2010 Solution

All the required code can be found here Note that the project files wont work with the Express version of Visual Studiodue to the main program - Deframe being written with MFCFor a binary build see this archiveThe solution uses a C-like approach for the Injection

A C++ Template Library (for the impatient)

This code is not for the faint of heart C++ 2003 (talking about Microsoft Visual C 2010 here variadic template support)template code to simplify the hotpatching Include it and use it as exemplified further below (its not included in the sourcedownload)

HotPatchhpppragma once include ltwindowshgt HotPatch is a thin wrapper on top of the function hot patching layer It encapsulates a way to replace known functions with own functions by means of patching in jmps in both x86and x86-64 The basic workflow is 1 Declare HotPatchfunctionltftypegt thePatch assign target to this object with thePatch = target 2 set a replacement callback with thePatchSetPatch(myTarget) 3 call thePatchApply() to replace the target with the other callback In the replacement procedure

httpelfcspubrosowiki Printed on 20111126 0759

26-11-2011 1115 Function Hooking and Windows Dll Injection

31 do your stuff 32 call thePatch(arguments) 33 do other stuff When done 4 restore the opcodes with thePatchRemovePatch() 5 the destructor or assigning a new function to thePatch will restore the protection status of the memoryreferred by target Limitations wont work with variadic functions (blame C)namespace HotPatch class Exception class MemoryException public Exception class PatchException public Exception template lttypename FTypegt class function_impl public function_impl() _pFun(NULL) _pPatch(NULL) _detoured(false) ~function_impl() _RestoreProtection() res = function_implltFTypegtIsPatched() tells whether a call to the target will run the target or thehook Return value bool res - true if ApplyPatch() has been called without an accompanying RemovePatch() bool IsPatched() return _detoured function_implltFTypegtoperator=(pFun) directs the patch to a target and prepares the target memory forwrites Parameters FType pFun - the function to patch (see Apply()) Throws MemoryException - when changing the protection of the page where pFun points is impossible void operator=(FType pFun) _RestoreProtection() _pFun = pFun if (NULL == _pFun) return BOOL res = VirtualProtect(_pFun _64bit _PATCH_LENGTH64 _PATCH_LENGTH32 PAGE_EXECUTE_READWRITEamp_oldProtection) if (res) throw MemoryException() function_implltFTypegtSetPatch(patch[ alwaysUse32Bit]) prepares internal state for the patch Parameters FType patch - the patch to use instead of pFun (see operator=(FType )) bool alwaysUse32Bit - If true a 32 bit jmp is always inserted Else the best jmp is determined based on necessities (can still be 32 bit if it fits) Throws PatchException - if patch is NULL void SetPatch(FType patch bool alwaysUse32Bit = false) if (NULL == patch) throw PatchException() if (NULL = _pPatch) RemovePatch() _pPatch = patch _64bit = alwaysUse32Bit they havent expressed mandatory 32 bit only path try to guess the best path

Sisteme de Operare - httpelfcspubrosowiki

Function Hooking and Windows Dll Injection 1215 26-11-2011

if (_64bit) LONGLONG jumpDistance = reinterpret_castltLONGLONGgt(_pPatch) - reinterpret_castltLONGLONGgt(_pFun) - _PATCH_LENGTH32 if (abs(jumpDistance) gt 0x7FFFFFFF) the jump is too long to fit a regular 32 bit relative jmp _64bit = true else _64bit = false save the old patch opcodes plain old for is faster DO NOT call any library functions for (SIZE_T i = 0 i lt (_64bit _PATCH_LENGTH64 _PATCH_LENGTH32) ++i) (_backup + i) = (reinterpret_castltPBYTEgt(_pFun) + i) function_implltFTypegtApplyPatch() makes pFun (see operator=(FType )) jmp to patch (seeSetPatch(FType bool)) This is the actual hot patch mechanism at work void ApplyPatch() if (_64bit) movabs reinterpret_castltPBYTEgt(_pFun) = _OP_MOVABS r11 (reinterpret_castltPBYTEgt(_pFun) + 1) = _R11_WRITE _detourProc reinterpret_castltPLONGLONGgt(reinterpret_castltPBYTEgt(_pFun) + 2) =reinterpret_castltLONGLONGgt(_pPatch) jmp reinterpret_castltPWORDgt(reinterpret_castltPBYTEgt(_pFun) + 10) = _OP_JMP64 abs r11 (reinterpret_castltPBYTEgt(_pFun) + 12) = _R11_JMP else jmp reinterpret_castltPBYTEgt(_pFun) = _OP_JMP32 distance left to _detourProc reinterpret_castltPDWORDgt(reinterpret_castltPBYTEgt(_pFun) + 1) = static_castltDWORDgt( reinterpret_castltPBYTEgt(_pPatch) - reinterpret_castltPBYTEgt(_pFun) - static_castltDWORDgt(_PATCH_LENGTH32)) _detoured = true function_implltFTypegtRemovePatch() undoes what ApplyPatch() did pFun (see operator=(FType )) willbe its old self again void RemovePatch() plain old for is faster DO NOT call any library functions for (SIZE_T i = 0 i lt (_64bit _PATCH_LENGTH64 _PATCH_LENGTH32) ++i) (reinterpret_castltPBYTEgt(_pFun) + i) = (_backup + i) _detoured = false protected FType _pFun FType _pPatch bool _64bit bool _detoured BYTE _backup[13] DWORD _oldProtection static const BYTE _OP_JMP32 = 0xE9 static const WORD _OP_JMP64 = 0xFF41 static const BYTE _OP_MOVABS = 0x49 static const BYTE _R11_WRITE = 0xBB static const BYTE _R11_JMP = 0xE3 static const SIZE_T _PATCH_LENGTH32 = 5 jmp detourProc - originalProc = 1 + 4 static const SIZE_T _PATCH_LENGTH64 = 13 movabs R11 detourProc (64 bit) jmp (abs 64) R11 = 1+ 1 + 8 + 2 + 1 template lttypename Tgt static T abs(T val) return val gt 0 val -val

httpelfcspubrosowiki Printed on 20111126 0759

26-11-2011 1315 Function Hooking and Windows Dll Injection

void _RestoreProtection() if (NULL == _pFun) return DWORD unusedOldProtection BOOL res = VirtualProtect(_pFun _64bit _PATCH_LENGTH64 _PATCH_LENGTH32 _oldProtectionampunusedOldProtection) (void) res nothing to do template lttypename FTypegt class _NativeCallGuard public _NativeCallGuard(function_implltFTypegt ampfun) _fun(fun) _funRemovePatch() ~_NativeCallGuard() _funApplyPatch() private function_implltFTypegt amp_fun template lttypenamegt class function define HP_TARG0define HP_TARG1 typename Arg1define HP_TARG2 HP_TARG1 typename Arg2define HP_TARG3 HP_TARG2 typename Arg3define HP_TARG4 HP_TARG3 typename Arg4define HP_TARG5 HP_TARG4 typename Arg5define HP_TARG6 HP_TARG5 typename Arg6define HP_TARG7 HP_TARG6 typename Arg7define HP_TARG8 HP_TARG7 typename Arg8define HP_TARG9 HP_TARG8 typename Arg9define HP_TARG10 HP_TARG9 typename Arg10define HP_FARG0define HP_FARG1 Arg1define HP_FARG2 HP_FARG1 Arg2define HP_FARG3 HP_FARG2 Arg3define HP_FARG4 HP_FARG3 Arg4define HP_FARG5 HP_FARG4 Arg5define HP_FARG6 HP_FARG5 Arg6define HP_FARG7 HP_FARG6 Arg7define HP_FARG8 HP_FARG7 Arg8define HP_FARG9 HP_FARG8 Arg9define HP_FARG10 HP_FARG9 Arg10define HP_ARG0define HP_ARG1 arg1define HP_ARG2 HP_ARG1 arg2define HP_ARG3 HP_ARG2 arg3define HP_ARG4 HP_ARG3 arg4define HP_ARG5 HP_ARG4 arg5define HP_ARG6 HP_ARG5 arg6define HP_ARG7 HP_ARG6 arg7define HP_ARG8 HP_ARG7 arg8define HP_ARG9 HP_ARG8 arg9define HP_ARG10 HP_ARG9 arg10define HP_ARG_DECL0define HP_ARG_DECL1 Arg1 arg1define HP_ARG_DECL2 HP_ARG_DECL1 Arg2 arg2define HP_ARG_DECL3 HP_ARG_DECL2 Arg3 arg3define HP_ARG_DECL4 HP_ARG_DECL3 Arg4 arg4define HP_ARG_DECL5 HP_ARG_DECL4 Arg5 arg5define HP_ARG_DECL6 HP_ARG_DECL5 Arg6 arg6define HP_ARG_DECL7 HP_ARG_DECL6 Arg7 arg7define HP_ARG_DECL8 HP_ARG_DECL7 Arg8 arg8define HP_ARG_DECL9 HP_ARG_DECL8 Arg9 arg9define HP_ARG_DECL10 HP_ARG_DECL9 Arg10 arg10 template partial specialization for functionltreturn_type([arg_types])gtdefine HP_RET_FUNCTION(n callconv) template lttypename _Ret HP_TARGngt class functionlt_Ret callconv(HP_FARGn)gt public function_impllt_Ret callconv(HP_FARGn)gt

Sisteme de Operare - httpelfcspubrosowiki

Function Hooking and Windows Dll Injection 1415 26-11-2011

private typedef _Ret callconv type(HP_FARGn) public ~functionlttypegt() _RestoreProtection() using function_impllttypegtoperator= _Ret operator()(HP_ARG_DECLn) _NativeCallGuardlttypegt CallGuard(this) return (_pFun)(HP_ARGn) protected using function_impllttypegt_pFun declare the 11 templates handling functions in the form _Ret function() _Ret function(Arg1) _Ret function(Arg1 Arg2) _Ret function(Arg1 Arg2 Arg10) HP_RET_FUNCTION(0 __cdecl) HP_RET_FUNCTION(1 __cdecl) HP_RET_FUNCTION(2 __cdecl) HP_RET_FUNCTION(3 __cdecl) HP_RET_FUNCTION(4 __cdecl) HP_RET_FUNCTION(5 __cdecl) HP_RET_FUNCTION(6 __cdecl) HP_RET_FUNCTION(7 __cdecl) HP_RET_FUNCTION(8 __cdecl) HP_RET_FUNCTION(9 __cdecl) HP_RET_FUNCTION(10 __cdecl) ifndef _M_X64 HP_RET_FUNCTION(0 __stdcall) HP_RET_FUNCTION(1 __stdcall) HP_RET_FUNCTION(2 __stdcall) HP_RET_FUNCTION(3 __stdcall) HP_RET_FUNCTION(4 __stdcall) HP_RET_FUNCTION(5 __stdcall) HP_RET_FUNCTION(6 __stdcall) HP_RET_FUNCTION(7 __stdcall) HP_RET_FUNCTION(8 __stdcall) HP_RET_FUNCTION(9 __stdcall) HP_RET_FUNCTION(10 __stdcall)endif namespace HotPatch

What Im doing above is generating 11 partial tempate specializations for class HotPatchfunction The class isinspired by C++2011s stdfunction Its a class that models functions with up to 10 (included) arguments - you cansee the declarations through the HP_RET_FUNCTION macro calls in there Then another set of 11 declarations for x86-64where only calling convention __cdecl exists Do not worry abut understanding the above code its ugly and it sucksFocus on the usage instead it gets things done (for up to 10 arguments that is)

To use this HotPatch mini-lib write something like

HotPatchTestcppinclude ltcstdiogtinclude HotPatchhppusing namespace stdusing namespace HotPatch functionltvoid()gt fooPatch void foo() printf(In foo()n) void bar()

httpelfcspubrosowiki Printed on 20111126 0759

26-11-2011 1515 Function Hooking and Windows Dll Injection

printf(Im hackin ur functionn) if (fooPatchIsPatched()) fooPatch() int main() void (pfoo)() = foo void (pbar)() = bar pfoo() calls foo() pbar() calls bar() fooPatch = foo fooPatchSetPatch(bar) fooPatchApplyPatch() pfoo() calls bar() pbar() calls bar() fooPatchRemovePatch() pfoo() calls foo() pbar() calls bar() return 0

Further Info and Support

Im usually idling under the handle foxx1337 on ircfreenodenet on rosedu1) httpwwwkernelorgdocman-pagesonlinepagesman8ld-linuxso8html LD_PRELOAD2) httpsupportmicrosoftcomkb197571 AppInit_DLLs registry hack3) httpyosefkcomc++fqafunctionhtml4) Fraps5) RivaTuner6) MSI Afterburner7) Sockscap8) foobar20009) AutoHotkey10) Code Project Article on Code Injection11) Media Player Classic Homecinema12) httpcontinuationswordpresscom20110510hot-patching-unconditional-jumps-x86-x86-64 Article on 64 bit hotpatching

Fromhttpelfcspubrosowiki - Sisteme de Operare

Permanent linkhttpelfcspubrosowikilaboratoareresurseinjections

Last update 20111108 0213

Sisteme de Operare - httpelfcspubrosowiki

Page 11: Function Hooking and Windows Dll Injection.pdf

26-11-2011 1115 Function Hooking and Windows Dll Injection

31 do your stuff 32 call thePatch(arguments) 33 do other stuff When done 4 restore the opcodes with thePatchRemovePatch() 5 the destructor or assigning a new function to thePatch will restore the protection status of the memoryreferred by target Limitations wont work with variadic functions (blame C)namespace HotPatch class Exception class MemoryException public Exception class PatchException public Exception template lttypename FTypegt class function_impl public function_impl() _pFun(NULL) _pPatch(NULL) _detoured(false) ~function_impl() _RestoreProtection() res = function_implltFTypegtIsPatched() tells whether a call to the target will run the target or thehook Return value bool res - true if ApplyPatch() has been called without an accompanying RemovePatch() bool IsPatched() return _detoured function_implltFTypegtoperator=(pFun) directs the patch to a target and prepares the target memory forwrites Parameters FType pFun - the function to patch (see Apply()) Throws MemoryException - when changing the protection of the page where pFun points is impossible void operator=(FType pFun) _RestoreProtection() _pFun = pFun if (NULL == _pFun) return BOOL res = VirtualProtect(_pFun _64bit _PATCH_LENGTH64 _PATCH_LENGTH32 PAGE_EXECUTE_READWRITEamp_oldProtection) if (res) throw MemoryException() function_implltFTypegtSetPatch(patch[ alwaysUse32Bit]) prepares internal state for the patch Parameters FType patch - the patch to use instead of pFun (see operator=(FType )) bool alwaysUse32Bit - If true a 32 bit jmp is always inserted Else the best jmp is determined based on necessities (can still be 32 bit if it fits) Throws PatchException - if patch is NULL void SetPatch(FType patch bool alwaysUse32Bit = false) if (NULL == patch) throw PatchException() if (NULL = _pPatch) RemovePatch() _pPatch = patch _64bit = alwaysUse32Bit they havent expressed mandatory 32 bit only path try to guess the best path

Sisteme de Operare - httpelfcspubrosowiki

Function Hooking and Windows Dll Injection 1215 26-11-2011

if (_64bit) LONGLONG jumpDistance = reinterpret_castltLONGLONGgt(_pPatch) - reinterpret_castltLONGLONGgt(_pFun) - _PATCH_LENGTH32 if (abs(jumpDistance) gt 0x7FFFFFFF) the jump is too long to fit a regular 32 bit relative jmp _64bit = true else _64bit = false save the old patch opcodes plain old for is faster DO NOT call any library functions for (SIZE_T i = 0 i lt (_64bit _PATCH_LENGTH64 _PATCH_LENGTH32) ++i) (_backup + i) = (reinterpret_castltPBYTEgt(_pFun) + i) function_implltFTypegtApplyPatch() makes pFun (see operator=(FType )) jmp to patch (seeSetPatch(FType bool)) This is the actual hot patch mechanism at work void ApplyPatch() if (_64bit) movabs reinterpret_castltPBYTEgt(_pFun) = _OP_MOVABS r11 (reinterpret_castltPBYTEgt(_pFun) + 1) = _R11_WRITE _detourProc reinterpret_castltPLONGLONGgt(reinterpret_castltPBYTEgt(_pFun) + 2) =reinterpret_castltLONGLONGgt(_pPatch) jmp reinterpret_castltPWORDgt(reinterpret_castltPBYTEgt(_pFun) + 10) = _OP_JMP64 abs r11 (reinterpret_castltPBYTEgt(_pFun) + 12) = _R11_JMP else jmp reinterpret_castltPBYTEgt(_pFun) = _OP_JMP32 distance left to _detourProc reinterpret_castltPDWORDgt(reinterpret_castltPBYTEgt(_pFun) + 1) = static_castltDWORDgt( reinterpret_castltPBYTEgt(_pPatch) - reinterpret_castltPBYTEgt(_pFun) - static_castltDWORDgt(_PATCH_LENGTH32)) _detoured = true function_implltFTypegtRemovePatch() undoes what ApplyPatch() did pFun (see operator=(FType )) willbe its old self again void RemovePatch() plain old for is faster DO NOT call any library functions for (SIZE_T i = 0 i lt (_64bit _PATCH_LENGTH64 _PATCH_LENGTH32) ++i) (reinterpret_castltPBYTEgt(_pFun) + i) = (_backup + i) _detoured = false protected FType _pFun FType _pPatch bool _64bit bool _detoured BYTE _backup[13] DWORD _oldProtection static const BYTE _OP_JMP32 = 0xE9 static const WORD _OP_JMP64 = 0xFF41 static const BYTE _OP_MOVABS = 0x49 static const BYTE _R11_WRITE = 0xBB static const BYTE _R11_JMP = 0xE3 static const SIZE_T _PATCH_LENGTH32 = 5 jmp detourProc - originalProc = 1 + 4 static const SIZE_T _PATCH_LENGTH64 = 13 movabs R11 detourProc (64 bit) jmp (abs 64) R11 = 1+ 1 + 8 + 2 + 1 template lttypename Tgt static T abs(T val) return val gt 0 val -val

httpelfcspubrosowiki Printed on 20111126 0759

26-11-2011 1315 Function Hooking and Windows Dll Injection

void _RestoreProtection() if (NULL == _pFun) return DWORD unusedOldProtection BOOL res = VirtualProtect(_pFun _64bit _PATCH_LENGTH64 _PATCH_LENGTH32 _oldProtectionampunusedOldProtection) (void) res nothing to do template lttypename FTypegt class _NativeCallGuard public _NativeCallGuard(function_implltFTypegt ampfun) _fun(fun) _funRemovePatch() ~_NativeCallGuard() _funApplyPatch() private function_implltFTypegt amp_fun template lttypenamegt class function define HP_TARG0define HP_TARG1 typename Arg1define HP_TARG2 HP_TARG1 typename Arg2define HP_TARG3 HP_TARG2 typename Arg3define HP_TARG4 HP_TARG3 typename Arg4define HP_TARG5 HP_TARG4 typename Arg5define HP_TARG6 HP_TARG5 typename Arg6define HP_TARG7 HP_TARG6 typename Arg7define HP_TARG8 HP_TARG7 typename Arg8define HP_TARG9 HP_TARG8 typename Arg9define HP_TARG10 HP_TARG9 typename Arg10define HP_FARG0define HP_FARG1 Arg1define HP_FARG2 HP_FARG1 Arg2define HP_FARG3 HP_FARG2 Arg3define HP_FARG4 HP_FARG3 Arg4define HP_FARG5 HP_FARG4 Arg5define HP_FARG6 HP_FARG5 Arg6define HP_FARG7 HP_FARG6 Arg7define HP_FARG8 HP_FARG7 Arg8define HP_FARG9 HP_FARG8 Arg9define HP_FARG10 HP_FARG9 Arg10define HP_ARG0define HP_ARG1 arg1define HP_ARG2 HP_ARG1 arg2define HP_ARG3 HP_ARG2 arg3define HP_ARG4 HP_ARG3 arg4define HP_ARG5 HP_ARG4 arg5define HP_ARG6 HP_ARG5 arg6define HP_ARG7 HP_ARG6 arg7define HP_ARG8 HP_ARG7 arg8define HP_ARG9 HP_ARG8 arg9define HP_ARG10 HP_ARG9 arg10define HP_ARG_DECL0define HP_ARG_DECL1 Arg1 arg1define HP_ARG_DECL2 HP_ARG_DECL1 Arg2 arg2define HP_ARG_DECL3 HP_ARG_DECL2 Arg3 arg3define HP_ARG_DECL4 HP_ARG_DECL3 Arg4 arg4define HP_ARG_DECL5 HP_ARG_DECL4 Arg5 arg5define HP_ARG_DECL6 HP_ARG_DECL5 Arg6 arg6define HP_ARG_DECL7 HP_ARG_DECL6 Arg7 arg7define HP_ARG_DECL8 HP_ARG_DECL7 Arg8 arg8define HP_ARG_DECL9 HP_ARG_DECL8 Arg9 arg9define HP_ARG_DECL10 HP_ARG_DECL9 Arg10 arg10 template partial specialization for functionltreturn_type([arg_types])gtdefine HP_RET_FUNCTION(n callconv) template lttypename _Ret HP_TARGngt class functionlt_Ret callconv(HP_FARGn)gt public function_impllt_Ret callconv(HP_FARGn)gt

Sisteme de Operare - httpelfcspubrosowiki

Function Hooking and Windows Dll Injection 1415 26-11-2011

private typedef _Ret callconv type(HP_FARGn) public ~functionlttypegt() _RestoreProtection() using function_impllttypegtoperator= _Ret operator()(HP_ARG_DECLn) _NativeCallGuardlttypegt CallGuard(this) return (_pFun)(HP_ARGn) protected using function_impllttypegt_pFun declare the 11 templates handling functions in the form _Ret function() _Ret function(Arg1) _Ret function(Arg1 Arg2) _Ret function(Arg1 Arg2 Arg10) HP_RET_FUNCTION(0 __cdecl) HP_RET_FUNCTION(1 __cdecl) HP_RET_FUNCTION(2 __cdecl) HP_RET_FUNCTION(3 __cdecl) HP_RET_FUNCTION(4 __cdecl) HP_RET_FUNCTION(5 __cdecl) HP_RET_FUNCTION(6 __cdecl) HP_RET_FUNCTION(7 __cdecl) HP_RET_FUNCTION(8 __cdecl) HP_RET_FUNCTION(9 __cdecl) HP_RET_FUNCTION(10 __cdecl) ifndef _M_X64 HP_RET_FUNCTION(0 __stdcall) HP_RET_FUNCTION(1 __stdcall) HP_RET_FUNCTION(2 __stdcall) HP_RET_FUNCTION(3 __stdcall) HP_RET_FUNCTION(4 __stdcall) HP_RET_FUNCTION(5 __stdcall) HP_RET_FUNCTION(6 __stdcall) HP_RET_FUNCTION(7 __stdcall) HP_RET_FUNCTION(8 __stdcall) HP_RET_FUNCTION(9 __stdcall) HP_RET_FUNCTION(10 __stdcall)endif namespace HotPatch

What Im doing above is generating 11 partial tempate specializations for class HotPatchfunction The class isinspired by C++2011s stdfunction Its a class that models functions with up to 10 (included) arguments - you cansee the declarations through the HP_RET_FUNCTION macro calls in there Then another set of 11 declarations for x86-64where only calling convention __cdecl exists Do not worry abut understanding the above code its ugly and it sucksFocus on the usage instead it gets things done (for up to 10 arguments that is)

To use this HotPatch mini-lib write something like

HotPatchTestcppinclude ltcstdiogtinclude HotPatchhppusing namespace stdusing namespace HotPatch functionltvoid()gt fooPatch void foo() printf(In foo()n) void bar()

httpelfcspubrosowiki Printed on 20111126 0759

26-11-2011 1515 Function Hooking and Windows Dll Injection

printf(Im hackin ur functionn) if (fooPatchIsPatched()) fooPatch() int main() void (pfoo)() = foo void (pbar)() = bar pfoo() calls foo() pbar() calls bar() fooPatch = foo fooPatchSetPatch(bar) fooPatchApplyPatch() pfoo() calls bar() pbar() calls bar() fooPatchRemovePatch() pfoo() calls foo() pbar() calls bar() return 0

Further Info and Support

Im usually idling under the handle foxx1337 on ircfreenodenet on rosedu1) httpwwwkernelorgdocman-pagesonlinepagesman8ld-linuxso8html LD_PRELOAD2) httpsupportmicrosoftcomkb197571 AppInit_DLLs registry hack3) httpyosefkcomc++fqafunctionhtml4) Fraps5) RivaTuner6) MSI Afterburner7) Sockscap8) foobar20009) AutoHotkey10) Code Project Article on Code Injection11) Media Player Classic Homecinema12) httpcontinuationswordpresscom20110510hot-patching-unconditional-jumps-x86-x86-64 Article on 64 bit hotpatching

Fromhttpelfcspubrosowiki - Sisteme de Operare

Permanent linkhttpelfcspubrosowikilaboratoareresurseinjections

Last update 20111108 0213

Sisteme de Operare - httpelfcspubrosowiki

Page 12: Function Hooking and Windows Dll Injection.pdf

Function Hooking and Windows Dll Injection 1215 26-11-2011

if (_64bit) LONGLONG jumpDistance = reinterpret_castltLONGLONGgt(_pPatch) - reinterpret_castltLONGLONGgt(_pFun) - _PATCH_LENGTH32 if (abs(jumpDistance) gt 0x7FFFFFFF) the jump is too long to fit a regular 32 bit relative jmp _64bit = true else _64bit = false save the old patch opcodes plain old for is faster DO NOT call any library functions for (SIZE_T i = 0 i lt (_64bit _PATCH_LENGTH64 _PATCH_LENGTH32) ++i) (_backup + i) = (reinterpret_castltPBYTEgt(_pFun) + i) function_implltFTypegtApplyPatch() makes pFun (see operator=(FType )) jmp to patch (seeSetPatch(FType bool)) This is the actual hot patch mechanism at work void ApplyPatch() if (_64bit) movabs reinterpret_castltPBYTEgt(_pFun) = _OP_MOVABS r11 (reinterpret_castltPBYTEgt(_pFun) + 1) = _R11_WRITE _detourProc reinterpret_castltPLONGLONGgt(reinterpret_castltPBYTEgt(_pFun) + 2) =reinterpret_castltLONGLONGgt(_pPatch) jmp reinterpret_castltPWORDgt(reinterpret_castltPBYTEgt(_pFun) + 10) = _OP_JMP64 abs r11 (reinterpret_castltPBYTEgt(_pFun) + 12) = _R11_JMP else jmp reinterpret_castltPBYTEgt(_pFun) = _OP_JMP32 distance left to _detourProc reinterpret_castltPDWORDgt(reinterpret_castltPBYTEgt(_pFun) + 1) = static_castltDWORDgt( reinterpret_castltPBYTEgt(_pPatch) - reinterpret_castltPBYTEgt(_pFun) - static_castltDWORDgt(_PATCH_LENGTH32)) _detoured = true function_implltFTypegtRemovePatch() undoes what ApplyPatch() did pFun (see operator=(FType )) willbe its old self again void RemovePatch() plain old for is faster DO NOT call any library functions for (SIZE_T i = 0 i lt (_64bit _PATCH_LENGTH64 _PATCH_LENGTH32) ++i) (reinterpret_castltPBYTEgt(_pFun) + i) = (_backup + i) _detoured = false protected FType _pFun FType _pPatch bool _64bit bool _detoured BYTE _backup[13] DWORD _oldProtection static const BYTE _OP_JMP32 = 0xE9 static const WORD _OP_JMP64 = 0xFF41 static const BYTE _OP_MOVABS = 0x49 static const BYTE _R11_WRITE = 0xBB static const BYTE _R11_JMP = 0xE3 static const SIZE_T _PATCH_LENGTH32 = 5 jmp detourProc - originalProc = 1 + 4 static const SIZE_T _PATCH_LENGTH64 = 13 movabs R11 detourProc (64 bit) jmp (abs 64) R11 = 1+ 1 + 8 + 2 + 1 template lttypename Tgt static T abs(T val) return val gt 0 val -val

httpelfcspubrosowiki Printed on 20111126 0759

26-11-2011 1315 Function Hooking and Windows Dll Injection

void _RestoreProtection() if (NULL == _pFun) return DWORD unusedOldProtection BOOL res = VirtualProtect(_pFun _64bit _PATCH_LENGTH64 _PATCH_LENGTH32 _oldProtectionampunusedOldProtection) (void) res nothing to do template lttypename FTypegt class _NativeCallGuard public _NativeCallGuard(function_implltFTypegt ampfun) _fun(fun) _funRemovePatch() ~_NativeCallGuard() _funApplyPatch() private function_implltFTypegt amp_fun template lttypenamegt class function define HP_TARG0define HP_TARG1 typename Arg1define HP_TARG2 HP_TARG1 typename Arg2define HP_TARG3 HP_TARG2 typename Arg3define HP_TARG4 HP_TARG3 typename Arg4define HP_TARG5 HP_TARG4 typename Arg5define HP_TARG6 HP_TARG5 typename Arg6define HP_TARG7 HP_TARG6 typename Arg7define HP_TARG8 HP_TARG7 typename Arg8define HP_TARG9 HP_TARG8 typename Arg9define HP_TARG10 HP_TARG9 typename Arg10define HP_FARG0define HP_FARG1 Arg1define HP_FARG2 HP_FARG1 Arg2define HP_FARG3 HP_FARG2 Arg3define HP_FARG4 HP_FARG3 Arg4define HP_FARG5 HP_FARG4 Arg5define HP_FARG6 HP_FARG5 Arg6define HP_FARG7 HP_FARG6 Arg7define HP_FARG8 HP_FARG7 Arg8define HP_FARG9 HP_FARG8 Arg9define HP_FARG10 HP_FARG9 Arg10define HP_ARG0define HP_ARG1 arg1define HP_ARG2 HP_ARG1 arg2define HP_ARG3 HP_ARG2 arg3define HP_ARG4 HP_ARG3 arg4define HP_ARG5 HP_ARG4 arg5define HP_ARG6 HP_ARG5 arg6define HP_ARG7 HP_ARG6 arg7define HP_ARG8 HP_ARG7 arg8define HP_ARG9 HP_ARG8 arg9define HP_ARG10 HP_ARG9 arg10define HP_ARG_DECL0define HP_ARG_DECL1 Arg1 arg1define HP_ARG_DECL2 HP_ARG_DECL1 Arg2 arg2define HP_ARG_DECL3 HP_ARG_DECL2 Arg3 arg3define HP_ARG_DECL4 HP_ARG_DECL3 Arg4 arg4define HP_ARG_DECL5 HP_ARG_DECL4 Arg5 arg5define HP_ARG_DECL6 HP_ARG_DECL5 Arg6 arg6define HP_ARG_DECL7 HP_ARG_DECL6 Arg7 arg7define HP_ARG_DECL8 HP_ARG_DECL7 Arg8 arg8define HP_ARG_DECL9 HP_ARG_DECL8 Arg9 arg9define HP_ARG_DECL10 HP_ARG_DECL9 Arg10 arg10 template partial specialization for functionltreturn_type([arg_types])gtdefine HP_RET_FUNCTION(n callconv) template lttypename _Ret HP_TARGngt class functionlt_Ret callconv(HP_FARGn)gt public function_impllt_Ret callconv(HP_FARGn)gt

Sisteme de Operare - httpelfcspubrosowiki

Function Hooking and Windows Dll Injection 1415 26-11-2011

private typedef _Ret callconv type(HP_FARGn) public ~functionlttypegt() _RestoreProtection() using function_impllttypegtoperator= _Ret operator()(HP_ARG_DECLn) _NativeCallGuardlttypegt CallGuard(this) return (_pFun)(HP_ARGn) protected using function_impllttypegt_pFun declare the 11 templates handling functions in the form _Ret function() _Ret function(Arg1) _Ret function(Arg1 Arg2) _Ret function(Arg1 Arg2 Arg10) HP_RET_FUNCTION(0 __cdecl) HP_RET_FUNCTION(1 __cdecl) HP_RET_FUNCTION(2 __cdecl) HP_RET_FUNCTION(3 __cdecl) HP_RET_FUNCTION(4 __cdecl) HP_RET_FUNCTION(5 __cdecl) HP_RET_FUNCTION(6 __cdecl) HP_RET_FUNCTION(7 __cdecl) HP_RET_FUNCTION(8 __cdecl) HP_RET_FUNCTION(9 __cdecl) HP_RET_FUNCTION(10 __cdecl) ifndef _M_X64 HP_RET_FUNCTION(0 __stdcall) HP_RET_FUNCTION(1 __stdcall) HP_RET_FUNCTION(2 __stdcall) HP_RET_FUNCTION(3 __stdcall) HP_RET_FUNCTION(4 __stdcall) HP_RET_FUNCTION(5 __stdcall) HP_RET_FUNCTION(6 __stdcall) HP_RET_FUNCTION(7 __stdcall) HP_RET_FUNCTION(8 __stdcall) HP_RET_FUNCTION(9 __stdcall) HP_RET_FUNCTION(10 __stdcall)endif namespace HotPatch

What Im doing above is generating 11 partial tempate specializations for class HotPatchfunction The class isinspired by C++2011s stdfunction Its a class that models functions with up to 10 (included) arguments - you cansee the declarations through the HP_RET_FUNCTION macro calls in there Then another set of 11 declarations for x86-64where only calling convention __cdecl exists Do not worry abut understanding the above code its ugly and it sucksFocus on the usage instead it gets things done (for up to 10 arguments that is)

To use this HotPatch mini-lib write something like

HotPatchTestcppinclude ltcstdiogtinclude HotPatchhppusing namespace stdusing namespace HotPatch functionltvoid()gt fooPatch void foo() printf(In foo()n) void bar()

httpelfcspubrosowiki Printed on 20111126 0759

26-11-2011 1515 Function Hooking and Windows Dll Injection

printf(Im hackin ur functionn) if (fooPatchIsPatched()) fooPatch() int main() void (pfoo)() = foo void (pbar)() = bar pfoo() calls foo() pbar() calls bar() fooPatch = foo fooPatchSetPatch(bar) fooPatchApplyPatch() pfoo() calls bar() pbar() calls bar() fooPatchRemovePatch() pfoo() calls foo() pbar() calls bar() return 0

Further Info and Support

Im usually idling under the handle foxx1337 on ircfreenodenet on rosedu1) httpwwwkernelorgdocman-pagesonlinepagesman8ld-linuxso8html LD_PRELOAD2) httpsupportmicrosoftcomkb197571 AppInit_DLLs registry hack3) httpyosefkcomc++fqafunctionhtml4) Fraps5) RivaTuner6) MSI Afterburner7) Sockscap8) foobar20009) AutoHotkey10) Code Project Article on Code Injection11) Media Player Classic Homecinema12) httpcontinuationswordpresscom20110510hot-patching-unconditional-jumps-x86-x86-64 Article on 64 bit hotpatching

Fromhttpelfcspubrosowiki - Sisteme de Operare

Permanent linkhttpelfcspubrosowikilaboratoareresurseinjections

Last update 20111108 0213

Sisteme de Operare - httpelfcspubrosowiki

Page 13: Function Hooking and Windows Dll Injection.pdf

26-11-2011 1315 Function Hooking and Windows Dll Injection

void _RestoreProtection() if (NULL == _pFun) return DWORD unusedOldProtection BOOL res = VirtualProtect(_pFun _64bit _PATCH_LENGTH64 _PATCH_LENGTH32 _oldProtectionampunusedOldProtection) (void) res nothing to do template lttypename FTypegt class _NativeCallGuard public _NativeCallGuard(function_implltFTypegt ampfun) _fun(fun) _funRemovePatch() ~_NativeCallGuard() _funApplyPatch() private function_implltFTypegt amp_fun template lttypenamegt class function define HP_TARG0define HP_TARG1 typename Arg1define HP_TARG2 HP_TARG1 typename Arg2define HP_TARG3 HP_TARG2 typename Arg3define HP_TARG4 HP_TARG3 typename Arg4define HP_TARG5 HP_TARG4 typename Arg5define HP_TARG6 HP_TARG5 typename Arg6define HP_TARG7 HP_TARG6 typename Arg7define HP_TARG8 HP_TARG7 typename Arg8define HP_TARG9 HP_TARG8 typename Arg9define HP_TARG10 HP_TARG9 typename Arg10define HP_FARG0define HP_FARG1 Arg1define HP_FARG2 HP_FARG1 Arg2define HP_FARG3 HP_FARG2 Arg3define HP_FARG4 HP_FARG3 Arg4define HP_FARG5 HP_FARG4 Arg5define HP_FARG6 HP_FARG5 Arg6define HP_FARG7 HP_FARG6 Arg7define HP_FARG8 HP_FARG7 Arg8define HP_FARG9 HP_FARG8 Arg9define HP_FARG10 HP_FARG9 Arg10define HP_ARG0define HP_ARG1 arg1define HP_ARG2 HP_ARG1 arg2define HP_ARG3 HP_ARG2 arg3define HP_ARG4 HP_ARG3 arg4define HP_ARG5 HP_ARG4 arg5define HP_ARG6 HP_ARG5 arg6define HP_ARG7 HP_ARG6 arg7define HP_ARG8 HP_ARG7 arg8define HP_ARG9 HP_ARG8 arg9define HP_ARG10 HP_ARG9 arg10define HP_ARG_DECL0define HP_ARG_DECL1 Arg1 arg1define HP_ARG_DECL2 HP_ARG_DECL1 Arg2 arg2define HP_ARG_DECL3 HP_ARG_DECL2 Arg3 arg3define HP_ARG_DECL4 HP_ARG_DECL3 Arg4 arg4define HP_ARG_DECL5 HP_ARG_DECL4 Arg5 arg5define HP_ARG_DECL6 HP_ARG_DECL5 Arg6 arg6define HP_ARG_DECL7 HP_ARG_DECL6 Arg7 arg7define HP_ARG_DECL8 HP_ARG_DECL7 Arg8 arg8define HP_ARG_DECL9 HP_ARG_DECL8 Arg9 arg9define HP_ARG_DECL10 HP_ARG_DECL9 Arg10 arg10 template partial specialization for functionltreturn_type([arg_types])gtdefine HP_RET_FUNCTION(n callconv) template lttypename _Ret HP_TARGngt class functionlt_Ret callconv(HP_FARGn)gt public function_impllt_Ret callconv(HP_FARGn)gt

Sisteme de Operare - httpelfcspubrosowiki

Function Hooking and Windows Dll Injection 1415 26-11-2011

private typedef _Ret callconv type(HP_FARGn) public ~functionlttypegt() _RestoreProtection() using function_impllttypegtoperator= _Ret operator()(HP_ARG_DECLn) _NativeCallGuardlttypegt CallGuard(this) return (_pFun)(HP_ARGn) protected using function_impllttypegt_pFun declare the 11 templates handling functions in the form _Ret function() _Ret function(Arg1) _Ret function(Arg1 Arg2) _Ret function(Arg1 Arg2 Arg10) HP_RET_FUNCTION(0 __cdecl) HP_RET_FUNCTION(1 __cdecl) HP_RET_FUNCTION(2 __cdecl) HP_RET_FUNCTION(3 __cdecl) HP_RET_FUNCTION(4 __cdecl) HP_RET_FUNCTION(5 __cdecl) HP_RET_FUNCTION(6 __cdecl) HP_RET_FUNCTION(7 __cdecl) HP_RET_FUNCTION(8 __cdecl) HP_RET_FUNCTION(9 __cdecl) HP_RET_FUNCTION(10 __cdecl) ifndef _M_X64 HP_RET_FUNCTION(0 __stdcall) HP_RET_FUNCTION(1 __stdcall) HP_RET_FUNCTION(2 __stdcall) HP_RET_FUNCTION(3 __stdcall) HP_RET_FUNCTION(4 __stdcall) HP_RET_FUNCTION(5 __stdcall) HP_RET_FUNCTION(6 __stdcall) HP_RET_FUNCTION(7 __stdcall) HP_RET_FUNCTION(8 __stdcall) HP_RET_FUNCTION(9 __stdcall) HP_RET_FUNCTION(10 __stdcall)endif namespace HotPatch

What Im doing above is generating 11 partial tempate specializations for class HotPatchfunction The class isinspired by C++2011s stdfunction Its a class that models functions with up to 10 (included) arguments - you cansee the declarations through the HP_RET_FUNCTION macro calls in there Then another set of 11 declarations for x86-64where only calling convention __cdecl exists Do not worry abut understanding the above code its ugly and it sucksFocus on the usage instead it gets things done (for up to 10 arguments that is)

To use this HotPatch mini-lib write something like

HotPatchTestcppinclude ltcstdiogtinclude HotPatchhppusing namespace stdusing namespace HotPatch functionltvoid()gt fooPatch void foo() printf(In foo()n) void bar()

httpelfcspubrosowiki Printed on 20111126 0759

26-11-2011 1515 Function Hooking and Windows Dll Injection

printf(Im hackin ur functionn) if (fooPatchIsPatched()) fooPatch() int main() void (pfoo)() = foo void (pbar)() = bar pfoo() calls foo() pbar() calls bar() fooPatch = foo fooPatchSetPatch(bar) fooPatchApplyPatch() pfoo() calls bar() pbar() calls bar() fooPatchRemovePatch() pfoo() calls foo() pbar() calls bar() return 0

Further Info and Support

Im usually idling under the handle foxx1337 on ircfreenodenet on rosedu1) httpwwwkernelorgdocman-pagesonlinepagesman8ld-linuxso8html LD_PRELOAD2) httpsupportmicrosoftcomkb197571 AppInit_DLLs registry hack3) httpyosefkcomc++fqafunctionhtml4) Fraps5) RivaTuner6) MSI Afterburner7) Sockscap8) foobar20009) AutoHotkey10) Code Project Article on Code Injection11) Media Player Classic Homecinema12) httpcontinuationswordpresscom20110510hot-patching-unconditional-jumps-x86-x86-64 Article on 64 bit hotpatching

Fromhttpelfcspubrosowiki - Sisteme de Operare

Permanent linkhttpelfcspubrosowikilaboratoareresurseinjections

Last update 20111108 0213

Sisteme de Operare - httpelfcspubrosowiki

Page 14: Function Hooking and Windows Dll Injection.pdf

Function Hooking and Windows Dll Injection 1415 26-11-2011

private typedef _Ret callconv type(HP_FARGn) public ~functionlttypegt() _RestoreProtection() using function_impllttypegtoperator= _Ret operator()(HP_ARG_DECLn) _NativeCallGuardlttypegt CallGuard(this) return (_pFun)(HP_ARGn) protected using function_impllttypegt_pFun declare the 11 templates handling functions in the form _Ret function() _Ret function(Arg1) _Ret function(Arg1 Arg2) _Ret function(Arg1 Arg2 Arg10) HP_RET_FUNCTION(0 __cdecl) HP_RET_FUNCTION(1 __cdecl) HP_RET_FUNCTION(2 __cdecl) HP_RET_FUNCTION(3 __cdecl) HP_RET_FUNCTION(4 __cdecl) HP_RET_FUNCTION(5 __cdecl) HP_RET_FUNCTION(6 __cdecl) HP_RET_FUNCTION(7 __cdecl) HP_RET_FUNCTION(8 __cdecl) HP_RET_FUNCTION(9 __cdecl) HP_RET_FUNCTION(10 __cdecl) ifndef _M_X64 HP_RET_FUNCTION(0 __stdcall) HP_RET_FUNCTION(1 __stdcall) HP_RET_FUNCTION(2 __stdcall) HP_RET_FUNCTION(3 __stdcall) HP_RET_FUNCTION(4 __stdcall) HP_RET_FUNCTION(5 __stdcall) HP_RET_FUNCTION(6 __stdcall) HP_RET_FUNCTION(7 __stdcall) HP_RET_FUNCTION(8 __stdcall) HP_RET_FUNCTION(9 __stdcall) HP_RET_FUNCTION(10 __stdcall)endif namespace HotPatch

What Im doing above is generating 11 partial tempate specializations for class HotPatchfunction The class isinspired by C++2011s stdfunction Its a class that models functions with up to 10 (included) arguments - you cansee the declarations through the HP_RET_FUNCTION macro calls in there Then another set of 11 declarations for x86-64where only calling convention __cdecl exists Do not worry abut understanding the above code its ugly and it sucksFocus on the usage instead it gets things done (for up to 10 arguments that is)

To use this HotPatch mini-lib write something like

HotPatchTestcppinclude ltcstdiogtinclude HotPatchhppusing namespace stdusing namespace HotPatch functionltvoid()gt fooPatch void foo() printf(In foo()n) void bar()

httpelfcspubrosowiki Printed on 20111126 0759

26-11-2011 1515 Function Hooking and Windows Dll Injection

printf(Im hackin ur functionn) if (fooPatchIsPatched()) fooPatch() int main() void (pfoo)() = foo void (pbar)() = bar pfoo() calls foo() pbar() calls bar() fooPatch = foo fooPatchSetPatch(bar) fooPatchApplyPatch() pfoo() calls bar() pbar() calls bar() fooPatchRemovePatch() pfoo() calls foo() pbar() calls bar() return 0

Further Info and Support

Im usually idling under the handle foxx1337 on ircfreenodenet on rosedu1) httpwwwkernelorgdocman-pagesonlinepagesman8ld-linuxso8html LD_PRELOAD2) httpsupportmicrosoftcomkb197571 AppInit_DLLs registry hack3) httpyosefkcomc++fqafunctionhtml4) Fraps5) RivaTuner6) MSI Afterburner7) Sockscap8) foobar20009) AutoHotkey10) Code Project Article on Code Injection11) Media Player Classic Homecinema12) httpcontinuationswordpresscom20110510hot-patching-unconditional-jumps-x86-x86-64 Article on 64 bit hotpatching

Fromhttpelfcspubrosowiki - Sisteme de Operare

Permanent linkhttpelfcspubrosowikilaboratoareresurseinjections

Last update 20111108 0213

Sisteme de Operare - httpelfcspubrosowiki

Page 15: Function Hooking and Windows Dll Injection.pdf

26-11-2011 1515 Function Hooking and Windows Dll Injection

printf(Im hackin ur functionn) if (fooPatchIsPatched()) fooPatch() int main() void (pfoo)() = foo void (pbar)() = bar pfoo() calls foo() pbar() calls bar() fooPatch = foo fooPatchSetPatch(bar) fooPatchApplyPatch() pfoo() calls bar() pbar() calls bar() fooPatchRemovePatch() pfoo() calls foo() pbar() calls bar() return 0

Further Info and Support

Im usually idling under the handle foxx1337 on ircfreenodenet on rosedu1) httpwwwkernelorgdocman-pagesonlinepagesman8ld-linuxso8html LD_PRELOAD2) httpsupportmicrosoftcomkb197571 AppInit_DLLs registry hack3) httpyosefkcomc++fqafunctionhtml4) Fraps5) RivaTuner6) MSI Afterburner7) Sockscap8) foobar20009) AutoHotkey10) Code Project Article on Code Injection11) Media Player Classic Homecinema12) httpcontinuationswordpresscom20110510hot-patching-unconditional-jumps-x86-x86-64 Article on 64 bit hotpatching

Fromhttpelfcspubrosowiki - Sisteme de Operare

Permanent linkhttpelfcspubrosowikilaboratoareresurseinjections

Last update 20111108 0213

Sisteme de Operare - httpelfcspubrosowiki