In this article, I am going to list half a dozen DLL injection techniques that can be used by a user mode process running on MS Windows. There could be more techniques but I am sharing with you the techniques that I had first hand experience with.
People used to rely on the AppInit_DLLs
registry key. The OS loader queries this value and loads the DLLs specified there when a process is created. I have not used this technique in a long while (last time I used it was on Windows XP) and I heard it is now restricted or discontinued because it was widely used by malware.
2. SetWindowsHookEx API
The SetWindowsHookEx API installs an application-defined hook procedure into a given hook chain. There are various supported hook chains (CBT, Journal, Window messages, keyboard, mouse, etc).
When using the SetWindowsHookEx API, you are instructing the operating system to inject your custom hook DLL into other process where it is relevant. The Windows hooks work when the other processes import / use functionality from USER32.dll.
3. The Image File Execution Options (IFEO) key
registry key is very handy. It allows you to instruct the OS loader to invoke a debugger when a given process is create, launch a given AppVerifier plugin, change process heap options, etc.
Back in the days, I have made a small experiment on top of the IFEO key by creating an AppVerifier plugin that gets injected into processes of my choice.
Do you want to master Batch Files programming? Look no further, the Batchography is the best book on the topic and the most up to date one!
Available in print or e-book editions from Amazon.
4. Remote threads
This technique relies on creating remote threads into the desired process that you want to inject to. The remote thread’s code would simply call LoadLibrary in that target process’ context. Note that many Antivirus software flag an attempt to create remote threads as a malicious activity.
5. Implicitly tracking all processes
This method relies on hook the process creation APIs such as: kernel32.CreateProcess[Internal] or lower APIs. By tracking the creation of other processes, you have a chance to inject your DLL into the new processes.
Here’s the basic idea behind this technique:
- Enum all existing processes
- Inject your DLL hook into all of running processes. This is important so that your injector gets up to speed with processes that executed before your injector was executed.
- Hook k32!CreateProcessInternalW in each process. If you can hook deeper all the better. For instance in ntdll!NtCreateProcess*
- Your injected DLL has to explicitly hook the process create API and do the following when invoked:
- Create the child process suspended
- Inject your hook. This is essentially the “tracking”
- Resume the process. Now this child process will now also hook any new processes
This technique gives the illusion that you are tracking all processes. It is effective and I have seen it being used in security products and I used it myself too. By hooking Explorer.exe (the shell), you get to track all processes that are launched from the “Start Menu”.
Of course this technique is limited and can be evaded, but it useful when you only have user mode access.
6. AppCompat shimming layer
The essence of it is that there’s a system DLL called AppPatch.dll that reads a shimming database (aka the SDB). This database is custom format and it can describe various application compatibility shimming / patching capabilities:
- Memory search / replace -> patch code inside a given module when that module gets loaded
- Load/inject a DLL when a given process is loaded. One can use Wildcards, etc..
- Fake API returns, etc..
security tool uses method #2 to inject DLLs into the desired processes. The basic idea was to generate an SDB on the fly each time EMET is reconfigured. EMET embeds code that knows how to generate the SDB and then it registers that SDB in the system.
Please note that the AppPatch mechanism is baked into the operating system’s process loader (inside ntdll.dll). Hence, it is not really “injection” it is more like a part of the loading process.
7. Kernel drivers
Last but not least and while not purely a user mode method, using a kernel driver is another sure way to inject code into all running processes. As far as I know, this is what reputable A/V software
use these days. They register for image creation notification
and then queue some APCs that will execute in user mode and do the injection.
In conclusion, DLL injection is a fascinating topic and having various injection techniques to choose from is really helpful for system developers. Base your injection choice on how resilient your injection should be, how safe it is (not to be caught by the A/V) and how persistent,
You might also like: