Differences

This shows you the differences between two versions of the page.

Link to this comparison view

so:laboratoare:resurse:injections [2013/01/31 21:57]
127.0.0.1 external edit
so:laboratoare:resurse:injections [2016/03/09 12:34] (current)
dennis.plosceanu [Function Hooking and Windows Dll Injection] Ordinea cuvintelor in engleza
Line 1: Line 1:
 ====== 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.+In this tutorial I'll show you how to modify the behavior of Windows programs ​at runtime.
  
 ===== Function Hot Patching ===== ===== Function Hot Patching =====
  
-    ​*roblem**: we have a function, ''​foo()''​ and we want ''​bar()''​ to be called instead. +**Problem**: we have a function, ''​foo()''​ and we want ''​bar()''​ to be called instead. 
-    *olutions**: + 
-modify the code, replace ''​foo()''​ with ''​bar()'',​ doh!. Works when the source is available. +**Solutions**: 
-write a library that exports a function with the same signature as ''​foo()'',​ which internally calls ''​bar()''​. On Unix based systems use the ''​LD_PRELOAD''​ trick(([[http://​www.kernel.org/​doc/​man-pages/​online/​pages/​man8/​ld-linux.so.8.html]] LD_PRELOAD)) 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(([[http://​support.microsoft.com/​kb/​197571]] AppInit_DLLs registry hack)) to have it load instead. If ''​foo()''​ isn't available through a shared library, you're out of luck.+  ​* ​modify the code, replace ''​foo()''​ with ''​bar()'',​ doh!. Works when the source is available. 
 +  ​* ​write a library that exports a function with the same signature as ''​foo()'',​ which internally calls ''​bar()''​. On Unix based systems use the ''​LD_PRELOAD''​ trick(([[http://​www.kernel.org/​doc/​man-pages/​online/​pages/​man8/​ld-linux.so.8.html]] LD_PRELOAD)) 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(([[http://​support.microsoft.com/​kb/​197571]] AppInit_DLLs registry hack)) 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! Here's a better solution: modify ''​foo()''​ at runtime by writing your code inside it!
  
-<spoiler|asm break>+<​spoiler>​
  
 Strictly speaking, you call a function by ''​push''​-ing some stuff like the arguments into the stack and then by executing ''​call //function address//''​. Since we're discussing C, when the function returns, you ''​pop''​ those arguments from the stack to keep it from thrashing. For example (this is debug code, notice the sanity check at ''​00F9145E''​):​ Strictly speaking, you call a function by ''​push''​-ing some stuff like the arguments into the stack and then by executing ''​call //function address//''​. Since we're discussing C, when the function returns, you ''​pop''​ those arguments from the stack to keep it from thrashing. For example (this is debug code, notice the sanity check at ''​00F9145E''​):​
Line 146: Line 147:
  
 The following image is an attempt at showing a map of the code from ''​hotpatch.cpp''​. Keep in mind that the memory addresses from the left side are fictional. The following image is an attempt at showing a map of the code from ''​hotpatch.cpp''​. Keep in mind that the memory addresses from the left side are fictional.
-{{ :​laboratoare:​resurse:​home:​hotpatch.png |Hot patch memory schematic}}+{{ so:​laboratoare:​resurse:​home:​hotpatch.png |Hot patch memory schematic}}
  
   - ''​foo()''​ is ''​02114B05 - 011A3518 = 00F715ED''​ bytes long, fits an ''​unsigned char[16193005]''​. ''​bar()''​ is ''​0852AB24 - 0852AA02 = 00000122''​ bytes long, fits an ''​unsigned char[290]''​.   - ''​foo()''​ is ''​02114B05 - 011A3518 = 00F715ED''​ bytes long, fits an ''​unsigned char[16193005]''​. ''​bar()''​ is ''​0852AB24 - 0852AA02 = 00000122''​ bytes long, fits an ''​unsigned char[290]''​.
Line 177: Line 178:
  
 Watch the following picture if you don't believe: Watch the following picture if you don't believe:
-{{ :​laboratoare:​resurse:​home:​hook.png |WH_SHELL diagram}}+{{ so:​laboratoare:​resurse:​home:​hook.png |WH_SHELL diagram}}
   - normally, an event is dispatched to the message loop of the receiving thread, and the message loop further sends that message within the thread to a "​proper"​ handler   - normally, an event is dispatched to the message loop of the receiving thread, and the message loop further sends that message within the thread to a "​proper"​ handler
   - ''​myhook.dll''​ registers, system-wide,​ ''​ShellProc()''​ as an interceptor of shell events (out of which ''​WM_CREATE''​). Now the message goes through the code from ''​ShellProc()''​ and only after processing it's (not even necessary, only because I'm too kind) forwarded to the shell handler in the original event loop.   - ''​myhook.dll''​ registers, system-wide,​ ''​ShellProc()''​ as an interceptor of shell events (out of which ''​WM_CREATE''​). Now the message goes through the code from ''​ShellProc()''​ and only after processing it's (not even necessary, only because I'm too kind) forwarded to the shell handler in the original event loop.
Line 189: Line 190:
 As a first attempt I created a simple one-shot console application that targeted the Heroes of Newerth window, removing the ''​WS_CAPTION''​ style, as reported by Spy++. As a first attempt I created a simple one-shot console application that targeted the Heroes of Newerth window, removing the ''​WS_CAPTION''​ style, as reported by Spy++.
  
-{{ :​laboratoare:​resurse:​home:​hon01.png?​640 |Heroes of Newerth window styles}}+{{ so:​laboratoare:​resurse:​home:​hon01.png?​640 |Heroes of Newerth window styles}}
  
 <file cpp Borderless1.cpp>​ <file cpp Borderless1.cpp>​
Line 218: Line 219:
 </​file>​ </​file>​
  
-{{ :​laboratoare:​resurse:​home:​hon02.png?​640 |Heroes of Newerth borderless}}+{{ so:​laboratoare:​resurse:​home:​hon02.png?​640 |Heroes of Newerth borderless}}
  
 You can observe 2 problems in the current approach: You can observe 2 problems in the current approach:
Line 291: Line 292:
 For the broken mouse hover effect it's time to put The Injection to use! Among the usual suspects for this problem are the window rectangle functions [[http://​msdn.microsoft.com/​en-us/​library/​ms633519%28VS.85%29.aspx|GetWindowRect()]] and [[http://​msdn.microsoft.com/​en-us/​library/​ms633503%28VS.85%29.aspx|GetClientRect()]]. It would make sense, due to the fact that games usually obtain mouse events through DirectInput,​ that initially mouse coordinates are expressed in desktop-absolute form, and not relative to the application window. Therefore they'd 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 [[http://​msdn.microsoft.com/​en-us/​library/​aa931003.aspx|ClientToScreen()]]. For the broken mouse hover effect it's time to put The Injection to use! Among the usual suspects for this problem are the window rectangle functions [[http://​msdn.microsoft.com/​en-us/​library/​ms633519%28VS.85%29.aspx|GetWindowRect()]] and [[http://​msdn.microsoft.com/​en-us/​library/​ms633503%28VS.85%29.aspx|GetClientRect()]]. It would make sense, due to the fact that games usually obtain mouse events through DirectInput,​ that initially mouse coordinates are expressed in desktop-absolute form, and not relative to the application window. Therefore they'd 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 [[http://​msdn.microsoft.com/​en-us/​library/​aa931003.aspx|ClientToScreen()]].
 Let's take a look at an application window and the ''​Get?​Rect()''​ logic relating to it: Let's take a look at an application window and the ''​Get?​Rect()''​ logic relating to it:
-{{ :​laboratoare:​resurse:​home:​sc201.png?​w640 |Window rectangles}}+{{ so:​laboratoare:​resurse:​home:​sc201.png?​w640 |Window rectangles}}
  
 What the game does when handling mouse input is obtain some absolute screen coordinates from DirectInput,​ convert them to window coordinates,​ then **compensate** for the window title and borders and then figure out what to do next with the event. Note that after removing the window decorations,​ both ''​GetWindowRect()''​ and ''​GetClientRect()''​ return the same coordinates. Then the game compensates by subtracting the expected widths and heights of borders, resulting in slightly off readings for the events. The idea here is to modify at run-time ''​GetWindowRect()''​ so that it returns the old rectangle, with titlebar and borders, as if the window style still contained those elements. What the game does when handling mouse input is obtain some absolute screen coordinates from DirectInput,​ convert them to window coordinates,​ then **compensate** for the window title and borders and then figure out what to do next with the event. Note that after removing the window decorations,​ both ''​GetWindowRect()''​ and ''​GetClientRect()''​ return the same coordinates. Then the game compensates by subtracting the expected widths and heights of borders, resulting in slightly off readings for the events. The idea here is to modify at run-time ''​GetWindowRect()''​ so that it returns the old rectangle, with titlebar and borders, as if the window style still contained those elements.
Line 355: Line 356:
 </​code>​ </​code>​
  
-{{ :​laboratoare:​resurse:​home:​guest3264.png?​w=512 |32 bit guest and 64 bit stub}}+{{ so:​laboratoare:​resurse:​home:​guest3264.png?​w=512 |32 bit guest and 64 bit stub}}
  
 ====== Download ====== ====== Download ======
  
-All the required code can be found {{:​laboratoare:​resurse:​injections.7z|here}}. Note that the project files won't work with the Express version of Visual Studio, due to the main program - ''​Deframe''​ being written with ''​MFC''​. +All the required code can be found {{so:​laboratoare:​resurse:​injections.7z|here}}. Note that the project files won't work with the Express version of Visual Studio, due to the main program - ''​Deframe''​ being written with ''​MFC''​. 
-For a binary build, see {{:​laboratoare:​resurse:​deframe-5-no-mfc.7z|this archive}}.+For a binary build, see {{so:​laboratoare:​resurse:​deframe-5-no-mfc.7z|this archive}}.
 The solution uses a C-like approach for the Injection. The workflow is: The solution uses a C-like approach for the Injection. The workflow is:
   - start Deframe.exe   - start Deframe.exe
Line 367: Line 368:
   - select either of the 2 available options ''​On top''​ or ''​No borders''​   - select either of the 2 available options ''​On top''​ or ''​No borders''​
  
-{{ :​laboratoare:​resurse:​home:​system_menu.png?​w640 |The system menu in Diablo III}}+{{ so:​laboratoare:​resurse:​home:​system_menu.png?​w640 |The system menu in Diablo III}}
 ===== A C++ Template Library (for the impatient) ===== ===== A C++ Template Library (for the impatient) =====
  
so/laboratoare/resurse/injections.1359662221.txt.gz · Last modified: 2013/02/19 09:01 (external edit)
CC Attribution-Share Alike 3.0 Unported
www.chimeric.de Valid CSS Driven by DokuWiki do yourself a favour and use a real browser - get firefox!! Recent changes RSS feed Valid XHTML 1.0