DLL hijacking for privesc
TL;DR: A privileged process loads a DLL by name without a fully-qualified path; drop a malicious DLL earlier in the search order (writable directory on
%PATH%, app dir, side-by-side manifest) and it executes in the high-priv context on next launch.
What it is
Windows resolves DLL imports following a documented search order. If a process loads foo.dll without specifying a full path and the DLL is not in the Known DLLs list, Windows walks: application directory, system directories, current directory, then %PATH%. When a SYSTEM-run or admin-launched binary references a missing or non-Known DLL and any earlier search-order directory is attacker-writable, you get code execution in the privileged process.
Preconditions / where it applies
- A process that runs at higher integrity (SYSTEM service, scheduled task as admin, auto-elevated MS binary).
- One of: writable application directory, a writable directory earlier on
%PATH%than the legit DLL, a missing dependency the loader keeps searching for, or an app SxS manifest that pulls an attacker-controlled assembly. - DLL not protected by KnownDLLs (
HKLM\SYSTEM\CurrentControlSet\Control\Session Manager\KnownDLLs). - Common on third-party services installed under
C:\Program Files\<vendor>\with weak ACLs, or vendor MSI installers that drop binaries into writable directories.
Technique
- Find candidate targets. With Process Monitor, run a filter:
1
2
3
Process Name = <target.exe>
Result = NAME NOT FOUND
Path ends with .dll
Each NAME NOT FOUND on a .dll lookup is a hijack candidate. The lower in the search list it appears, the more directories you can plant in. winPEAS and PowerSploit’s Find-PathDLLHijack automate the writable-%PATH% and writable-app-dir cases.
- Generate a payload DLL that exports the same symbols, or just runs in
DllMain:
1
msfvenom -p windows/x64/exec CMD='cmd.exe /c net user pwn P@ss1 /add && net localgroup administrators pwn /add' -f dll -o legit.dll
For proxy-style hijacks where the host expects real exports, use a forwarder (#pragma comment(linker, "/export:OriginalFn=real.OriginalFn")) or tools like Spartacus / Koppeling to auto-clone exports.
-
Plant the DLL in the first writable directory in the search order — typically the service’s install directory if its ACL is loose, or a writable
%PATH%entry such asC:\Python27\left from a prior install. -
Trigger: restart the service (
sc start <svc>), wait for a scheduled task, or reboot. The DLL loads with the service’s token.
Side-by-side (SxS) variant: drop an app.exe.manifest next to the binary that references an attacker-controlled assembly under C:\Users\<u>\AppData\Local\Microsoft\WindowsApps\ — the SxS loader is even more permissive than the standard search order.
Detection and defence
- Sysmon Event ID 7 (Image Loaded) showing a high-priv process loading a DLL from a user-writable path (
C:\Users\,C:\ProgramData\, app dirs with weak ACLs) is the classic IOC. Correlate with EID 11 (FileCreate) of.dllin those paths. - Defence: call
SetDefaultDllDirectories(LOAD_LIBRARY_SEARCH_SYSTEM32)and useLoadLibraryExwithLOAD_LIBRARY_SEARCH_*flags; ship DLLs inSystem32or use fully-qualified paths. - Harden ACLs on
Program Files\<vendor>install directories — removeUsers:(M)andAuthenticated Users:(W). - Enable
SafeDllSearchMode(default on modern Windows) and add critical DLLs toKnownDLLs. WDAC in DLL-enforcement mode blocks unsigned DLL loads entirely. - Related: weak-service-permissions, unquoted-service-paths, always-install-elevated.
References
- Microsoft — Dynamic-Link Library Search Order — Canonical search-order documentation.
- HackTricks — DLL Hijacking — Enumeration, planting, and proxy DLL techniques.
- ired.team — DLL hijacking — Practical examples with Process Monitor and payload generation.
- Spartacus — Procmon-driven DLL hijack discovery and proxy DLL generation.