DEFENSE

Detecting DLL Side-Loading via Process Load-Path Anomalies

Advertisement

DLL side-loading remains one of the most reliable execution and evasion techniques used by adversary groups and ransomware operators. By placing a malicious DLL with a known, benign name (such as version.dll, dbghelp.dll, or uxtheme.dll) into the same directory as a legitimately signed executable, the attacker forces the program to load their payload instead of the official Windows library.

Because the host binary carries a valid digital signature from a trusted vendor, traditional endpoint controls that only inspect executable signatures often fail to raise an alert. To catch this technique reliably, your detection logic must evaluate dynamic link library load paths and flag discrepancies between where executables run and where their loaded dependencies originate.

Understanding Load-Order Hijacking

The standard Windows side-loading attack relies on default DLL search order behavior. When an executable calls LoadLibrary or imports functions from a dynamic library without specifying a fully qualified path, the Windows loader searches in a deterministic sequence:

  1. The directory from which the application loaded.
  2. System directories (C:\Windows\System32 and C:\Windows\SysWOW64).
  3. The 16-bit system directory.
  4. The Windows directory (C:\Windows).
  5. The current working directory.
  6. Directories listed in the %PATH% environment variable.

Because the application’s working directory takes precedence over system directories, placing a spoofed dbghelp.dll in C:\Users\Public\Downloads\ alongside a signed utility ensures the binary executes the attacker’s payload first.

Telemetry Requirements and Sysmon Event ID 7

To detect this technique across your environment, you need module load telemetry. Sysmon Event ID 7 (ImageLoaded) provides the necessary context:

  • Image: The absolute path of the process performing the load.
  • ImageLoaded: The absolute path of the dynamic link library being loaded into memory.
  • SignatureStatus and Signed: The signature status of the loaded module.

When baseline auditing is active, core system libraries like version.dll, winmm.dll, or propsys.dll should almost exclusively load from C:\Windows\System32\ or C:\Windows\SysWOW64\. Any event where a system-standard DLL loads from a user-writable path like \AppData\, \Users\Public\, \ProgramData\, or \Temp\ represents a actionable anomaly.

Building the Detection Query

Using Kusto Query Language (KQL) or an equivalent SIEM syntax, you can construct a high-confidence rule targeting side-loading attempts by pairing targeted DLL names with path exclusions:

DeviceImageLoadEvents
| where FolderPath !startswith "C:\\Windows\\System32\\"
    and FolderPath !startswith "C:\\Windows\\SysWOW64\\"
    and FolderPath !startswith "C:\\Program Files\\"
    and FolderPath !startswith "C:\\Program Files (x86)\\"
| where LoadedHeader endswith "\\version.dll"
    or LoadedHeader endswith "\\dbghelp.dll"
    or LoadedHeader endswith "\\uxtheme.dll"
    or LoadedHeader endswith "\\winmm.dll"
    or LoadedHeader endswith "\\propsys.dll"
    or LoadedHeader endswith "\\cryptbase.dll"
| project Timestamp, DeviceName, InitiatingProcessFileName, InitiatingProcessFolderPath, LoadedHeader, FolderPath

If implementing this logic in Sysmon logs, filter for EventID == 7 where ImageLoaded ends with target DLL names and ImageLoaded does not begin with C:\Windows\.

Tuning False Positives in Production

While this detection methodology yields high fidelity, you will encounter legitimate software packages that ship custom or portable builds containing duplicate Windows DLL names. Common sources of benign noise include:

  • Custom application installers dropping temporary helper DLLs into local user directories during setup.
  • Developer environments and IDEs bundling specific runtime libraries inside project workspaces.
  • Self-contained desktop applications executing self-updates from \AppData\Local\ directories.

To refine your detection logic without creating dangerous coverage gaps:

  1. Avoid broad folder exclusions: Never whitelist entire paths like C:\Users\*. Instead, scope exclusions to precise binary hash values or executable names paired with verified digital signatures.
  2. Inspect process parentage: Legitimate side-loads during updates typically originate from known installer binaries or update services, whereas malicious side-loading frequently stems from command interpreters, scripting engines, or temporary execution paths.
  3. Enforce hard blocks on core API DLLs: Critical architecture libraries like ntdll.dll or kernel32.dll should never load outside of system directories. Any instance of these modules loading from non-standard locations demands immediate triage regardless of process context.

By systematically monitoring module load paths against baseline expectations, you can neutralize one of the adversary’s favorite stealth execution mechanisms.

Photo by Luke Chesser on Unsplash.