Wednesday, January 25, 2012

10 User-Mode Methods of Code Execution/Injection


So before I even start writing any terrible code (which it totally will be, as I haven't written C++ in years) I need to investigate all the ways that one can actually inject code into another process. That, obviously, is the point of this post, to highlight the ten ways that appear to be popular for injecting code into a process and a brief explanation of the method. My goal is to develop at least simple examples of each routine (Maybe not to start, but eventually). I'm going to at least attempt to build a library of the methods so it will be easy to select a method. Anyways, here's the list I came up with, if anyone has any other methods *please* email me or let me know (@_wirepair on twitter) and I'll happily add it to the list and give credit!

AppInit_DLLs Injection 
Description: Using this technique allows you to inject a single, or multiple DLLs into all user-mode processes. This is ridiculously powerful as it allows you to basically inject your code into everything that the user runs. It works by you specifying a list of DLL's separated by a comma or space you wish to load in the following registry key:

HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Windows\AppInit_DLLs

There's a great excerpt from the Microsoft documentation (referenced below) regarding AppInit_DLLs:
 "Today, only a small set of legitimate applications use this mechanism. Unfortunately, a larger set of malware use this mechanism. Applications and malicious software both use AppInit DLLs for the same basic reason, which is to hook APIs"
Due to the abuse, Microsoft built in some code-signing requirements but I don't understand the point as they can just be disabled by setting the RequireSignedAppInit_DLLs key to 0x0.
Required Work: Build a safe DLL that can be loaded into any process without crashing it, hook various API calls.
References: A 30 page Word Document explaining AppInit_DLLs.
References: Simple explanation with registry key information.

SetWindowsHookEx
Description: I'd basically describe this as the 'polite way' to inject your code into a process and hook a function or API call. While this can be used to install a global hook for all processes, you can also use it for hooking a single thread. Much like AppInit_DLLs this also injects a DLL into a remote process. To remove the hook you simply call UnhookWindowsHookEx (keep in mind this won't remove the DLL from the process).
Required Work: Probably the same amount as AppInit_DLLs.
References: A nice write up from CodeProject.
References: Using Hooks (MSDN)
References: SetWindowsHookEx API from MSDN

CreateRemoteThread & LoadLibrary
Description: This method is starting to look a bit better. Again we're loading a DLL but this time using CreateRemoteThread to force the remote process to do it. This will however require come up with our own method to hook, or modify our target functions/code as well as potentially code for handling inter process communication between the injector and the injected. Also dependent on LoadLibrary to find function names, which may or may not be modified by anti-cheating systems.
Required Work: Quite a bit more work than SetWindowsHookEx, due to custom hooking (and possibly IPC code) required.
References: A nice write up from CodeProject
References: CreateRemoteThread API Call and LoadLibrary API Call from MSDN.

CreateRemoteThread & WriteProcessMemory
Description: So far, this one is my favorite (few left to go though!). Mainly because in this method you're not even injecting a separate DLL but just the code you need. However, you still end up relying on LoadLibrary to find your functions which some anti-cheating systems may have hooked/modified.
Required Work: Depends on code that I create, it appears to be some restrictions when using this technique (with regards to variable count/size). Also may or may not require some IPC code.
References: A nice write up from CodeProject
References: CreateRemoteThread API Call, LoadLibrary API Call and WriteProcessMemory API Call from MSDN.

Exploit Memory Corruption Bug :>
Description: My good ol' friend, Memory Corruption. The idea being that you exploit a buffer overflow/ptr overwrite or something else that allows you to gain control of the program. I'm far more familiar with using techniques like these, but it's kinda silly to go down this route for a local application.
Required Work: Unnecessary
References: The internet

Code Cave
Description: OK now this one is my favorite. Very similiar to CreateRemoteThread & WriteProcessMemory, except you use a different technique for getting your code to execute after injection. The basic flow is: OpenProcess -> VirtualAlloc -> WriteProcessMemory -> Pause Thread -> Get Context -> SetThreadContext -> ResumeThread (starts your code).
Required Work: About the same as CreateRemoteThread & WriteProcessMemory except requires inline'd x86 asm.
References: Nice write up on a forum post from Blizzhackers

IAT Hooks
Description: This method requires overwriting target addresses in the Import Address Table (IAT). I assume this method is pretty easy to detect for anti-cheat systems. But it remains popular in malware at least. Also depending on the application, some calls may be using LoadLibrary and GetProcAddress (i.e. calling functions dynamically) which would completely bypass the IAT hook.
Required Work: DC,NGDI (Don't Care, Not Gonna Do It.)
References: A newer approach to IAT Hooking, looks interesting... along with source.
References: PE & COFF Specification
References: Nice blog post on using IAT Hooks for mock apps.


Inline Function Hooking (aka Detours)
Description: The most famous version of this is the Detours library from Microsoft. Only supports 32-bit, unless you feel like dropping $10,000 for 64-bit support. It's a pretty simple approach due to the fact that functions have stub code which can be rewritten without causing problems. For a quick summary on how it works check this excellent post from, no less, a game hacking site!
Required Work: Probably the same as CreateRemoteThread/WriteProcessMemory with a little bit more asm involved.
References: Microsoft Detours Page and a old but good document from MS on how Detours works.

DLL Replacement
Description: Due to the way that windows searches for libraries, it will load any .dll we put in the same path as the executable. This, obviously, can be taken advantage of to load a dll (say d3d9.dll) instead of the one in the system directory. Or we simply rename the one in the system directory. The problem here is that you'd either have to wrap every function or figure out a way to proxy function calls to the real dll. If you think this is crazy, check out what this guy did: http://graphics.stanford.edu/~mdfisher/D3D9Interceptor.html. He's basically already written a lot of what I'm going to do but I need to learn, not copy & paste so I'm going to go about this my own way. (I still can't get over the awesomeness of his work, even though I've known about it for a few weeks now!)
Required Work: Quite a bit, need to wrap pretty much every function, or figure out a way to proxy function calls to the real DLL.
References: Windows Library Load Order ( >= Win7)


Custom Debugger
Description: Finally, I can create my own debugger by wrapping dbgeng.dll and using various debugger commands and methods to gain execution and inject data/code.
Required Work: Need to learn internals of dbgeng and wrap the necessary interfaces/methods to do what I want. So, a lot of work. Probably no time soon :>.
References: Un-friggen-real list of everything you need to 'Create your own Debugger', seriously awesome list.
References: Using the Debugger Engine (MSDN)
References: Awesome PDF with everything you need to know about WinDBG / dbgeng


Some other things of note; not really an injection 'technique' but for getting managed assembly's into a process: (check out 'how to inject a managed assembly', and CreateRemoteThread, managed style.

Anyways, I think i'm going to play around with some code now, so I may not have any more posts until after the weekend. Stay tuned though!


1 comment: