DLL Search Order Hijacking
Malware places a trojan DLL in a directory searched before the legitimate library location, causing Windows to load the malicious version when the target application starts.
Windows resolves DLL names using a fixed search order. By default (with SafeDllSearchMode enabled), the order is:
- The directory containing the loading executable
- The system directory (
System32) - The 16-bit system directory
- The Windows directory
- The current working directory
- Directories listed in the
PATHenvironment variable
If an application tries to load a DLL that does not exist in System32 (or loads it by relative name), any DLL with the correct name placed in the application's own directory — or anywhere earlier in the search path — will be loaded instead.
Attackers use this to achieve persistence (the trojan DLL runs every time the application starts) or privilege escalation (when the vulnerable application runs as a higher-privilege account).
How it works
A trojan DNSAPI.dll placed alongside a target binary that dynamically loads DNSAPI.dll by relative name:
// trojan_dnsapi.c — compiled as DNSAPI.dll
#include <windows.h>
// Forward all real exports to the legitimate DLL (DLL proxying)
#pragma comment(linker, "/export:DnsQuery_A=C:\\Windows\\System32\\DNSAPI.DnsQuery_A,@1")
// ... additional exports ...
BOOL APIENTRY DllMain(HMODULE hModule, DWORD fdwReason, LPVOID lpReserved)
{
if (fdwReason == DLL_PROCESS_ATTACH) {
// Malicious payload — runs with the privileges of the loading application
CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)payload, NULL, 0, NULL);
}
return TRUE;
}Discovery tools such as DLLirant and Procmon (filter on NAME NOT FOUND + *.dll) automate identification of vulnerable load paths.
Procmon filter:
Operation is CreateFile
Path ends with .dll
Result is NAME NOT FOUNDDetection & analysis
During analysis:
- Run the target application under Procmon/API Monitor: a
LoadLibrarycall that results inNAME NOT FOUNDinSystem32butSUCCESSin the application directory is proof of a hijack opportunity. - Check the target binary's import table for DLLs absent from
System32; also checkLoadLibrary/LoadLibraryExcalls with relative paths.
Static / automated detection:
- YARA rule: DLL with
DLL_PROCESS_ATTACHhandler +CreateThread+ an exported name matching a known system DLL export — especially when the DLL is not signed. - MITRE ATT&CK T1574.001; Unprotect code snippet U1574.
- Application control (WDAC/AppLocker): restrict DLL loading to trusted, signed binaries; enforce
PreferSystem32Imagesin the process mitigation policy.