# DLL Injection

By [phasewalk](https://paragraph.com/@phasewalk-2) · 2025-11-11

---

**DLL Injection** is an exploit technique that can be used for anything from harmless game mods to sophisticated malware campaigns. _At its core, DLL Injection is about convincing a running process to execute code it never intended to run_ - whether that's adding custom features to your favorite game, or establishing persistence in a compromised system.

As part of my [100 day Infosec challenge](https://x.com/phasewalk1/status/1987464837342056777), I decided I would spend today diving deeper into DLL injection. I wanted to understand how this technique works under the hood. Here are some of my key takeaways.

The Windows PE Format and Dynamic Linking
-----------------------------------------

Before we can understand what DLL injection is and how it works, we need to know what a DLL is!

A **DLL (Dynamic Link Library)** is a Windows binary in the **Portable Executable (PE)** format. Every PE file contains several important components which we will touch on briefly:

*   **Sections** organize the file into logical chunks: `.text` holds executable code, `.data` stores initialized global variables, `.rdata` contains read-only data like string literals, and `.reloc` contains relocation information for address adjustments.
    
*   **Import Address Table (IAT):** Lists the functions that the DLL depends on from other DLLs. During loading, the Windows loader resolves these symbolic names and writes function pointers into the IAT.
    
*   **Export Table:** Lists the functions that the DLL exposes to other programs (its public API).
    
*   **Image Base:** The preferred virtual memory address where the loader should map the DLL. The loader tries to honor it, but if that memory space is occupied, it has to relocate.
    
*   **Base Relocations:** Adjustment instructions used when the DLL can't load at its preferred address (Image Base). Every absolute address reference in the code needs to be patched with the offset between the preferred and actual load addresses.
    
*   `DllMain`**:** An optional entry point called by the loader during process/thread attach/detach events. It allows the DLL to execute initialization code.
    

The DLL Loading Process
-----------------------

For the sake of this article we’ll use the term _“Windows Loader”_ to describe the cooperation between user-mode components (like `ntdll.dll`) and kernel-mode components (like the PE loader in `ntoskrnl.exe`) that make loading DLLs possible. So when we say “_the loader_” just know that it’s a system of multiple components working together, not a single program.

When a process needs a DLL, the Windows loader performs a carefully choreographed sequence:

1.  Map the PE file from disk into the process's virtual address space.
    
2.  Apply relocations if needed (adjust addresses if not at preferred base).
    
3.  Walk the import table and resolve all external function references.
    
4.  Execute Thread Local Storage (TLS) callbacks if present.
    
5.  Call `DllMain` with `DLL_PROCESS_ATTACH` to allow the DLL to initialize.
    
6.  The DLL is now ready for use by the process.
    

What is DLL Injection?
----------------------

> **The key idea behind DLL injection is to subvert or otherwise manipulate this loading sequence to execute arbitrary code inside the target process.**

So DLL injection is any technique that allows arbitrary code execution inside another process’s address space without that process’s explicit cooperation. It’s the difference between inviting someone into your home versus them finding a way in through the basement window.

### Classic Injection Method

The traditional approach to achieving DLL injection follows this pattern:

1.  **Get a handle** to the target process (`OpenProcess` with appropriate privileges)
    
2.  **Allocate memory** in the target’s address space (`VirtualAllocEx`)
    
3.  **Write the DLL path** into that memory (`WriteProcessMemory`)
    
4.  **Create a remote thread** that calls `LoadLibrary` on that path (`CreateRemoteThread`)
    

`LoadLibrary` does all the heavy lifting. The normal Windows loader takes over and performs all the steps we described earlier. The catch with this approach though is that it’s noisy. Modern Endpoint Detection and Response (EDR) solutions watch for exactly this pattern: `OpenProcess` → `VirtualAllocEx` → `WriteProcessMemory` → `CreateRemoteThread` is practically a neon sign saying “malicious activity over here”.

### Reflective DLL Injection

The weakness in the classic injection method above (the ease in which it can be detected) is due to the traces left behind by the loading process. _Reflective DLL injection_, on the other hand, **contains its own custom loader code**, allowing it to better evade EDR and forensics.

> This is how [Meterpreter](https://www.offsec.com/metasploit-unleashed/about-meterpreter/#how-meterpreter-works) works for example.

Because the reflective DLL contains its own loader code, it can bypass standard security mechanisms like DLL load logging, and leave a minimal forensic footprint. Because it bypasses `LoadLibrary` and the Windows loader, a reflective DLL must include a special function (the “reflective loader”) that manually implements everything the OS loader would normally do (Steps 1-6 of the DLL loading process).

The DLL never exists as a file on disk! The stager receives it over the network, writes it directly into memory, and jumps to the reflective loader. No file creation events, no scanning by AV, no forensic artifacts. You never call `LoadLibrary`\-which is heavily monitored. The only suspicious calls are the initial `VirtualAlloc/WriteProcessMemory`to get the image into memory.

### Meterpreter

Metasploit’s Meterpreter payload is a great example of reflective DLL injection in practice. When you get a Meterpreter shell:

1.  The initial stager (tiny piece of shellcode) establishes a connection.
    
2.  The full Meterpreter DLL is downloaded from the attacking machine.
    
3.  The stager allocates memory and writes the reflective DLL.
    
4.  Execution transfers to the reflective loader stub.
    
5.  The loader performs all the PE loading tasks manually.
    
6.  `DllMain` executes and Meterpreter establishes its full C2 channel.
    

The entire payload lives in memory. If the compromised system reboots, Meterpreter disappears (unless persistence mechanisms are used). This makes incident response and forensics significantly harder -- there’s no malicious binary to find on disk, and memory analysis requires knowing what to look for.

Differentiating Other DLL Attacks
---------------------------------

I often get confused about related but distinct DDL exploit techniques that are not considered injection attacks. I’ll attempt to make distinctions between them here.

**Disk-based DLL loading**, for example, involves placing a malicious DLL where a process will naturally load it. Two methods of doing this are:

*   **DLL search-order hijacking**: Exploits the DLL search path when calling `LoadLibrary` to load a malicious DLL instead of the legitimate one
    
*   **DLL sideloading**: placing a malicious DLL with the right name next to a legitimate executable that will load it. The following article goes more in-depth on this\*:\* [Bitdefender - What is DLL Sideloading](https://techzone.bitdefender.com/en/tech-explainers/what-is-dll-sideloading.html).
    

Process replacement techniques like [process hollowing](https://attack.mitre.org/techniques/T1055/012/) or [process doppelgänging](https://attack.mitre.org/techniques/T1055/013/) create what looks like a benign process but replace its code entirely. These are all related but distinct from DLL injection; the main distinction is that they’re _not adding code to a running process._

> **They key difference between DLL injection and process doppelgänging, for example, is that DLL injection involves forcefully loading a malicious DLL into an _already running_ legitimate process, while process doppelgänging involves creating a _new_, _hidden_, malicious process that masquerades as a legitimate one using file transactions.**

Conclusion
----------

DLL injection is a fundamental technique in offensive security. From dropping a Meterpreter shell in a CTF to advanced persistent threats, the ability to run code in another process’s context remains valuable across the threat spectrum. Reflective DLL injection specifically demonstrates how adversaries evolve techniques to evade detection -- by removing disk artifacts and implementing their own custom loaders, they operate in the gaps of traditional security mechanisms.

For security practitioners, understanding these techniques isn’t only about learning to attack systems, but about comprehending how modern malware operates so we can build better defenses, hunt more effectively, and respond to incidents with full knowledge of what adversaries are capable of.

### References

MITRE ATT&CK [Process Injection: Dynamic-link Library Injection](https://attack.mitre.org/techniques/T1055/001/)

Cobalt Strike [Delivering Custom Payloads With Metasploit Using DLL Injection](https://www.cobaltstrike.com/blog/delivering-custom-payloads-with-metasploit-using-dll-injection)

IBM [Defining the Cobalt Strike Reflective Loader](https://www.ibm.com/think/x-force/defining-cobalt-strike-reflective-loader)

---

*Originally published on [phasewalk](https://paragraph.com/@phasewalk-2/dll-injection)*
