Skip to content

DLL Search Order Hijacking and Side-Loading

How Malware Hides in a Process

A program loads most DLLs by name. Unless that name is already loaded or is one of Windows' Known DLLs, Windows searches a fixed order of folders, the program's own folder before System32. Windows' own DLLs come from System32, SysWOW64 or the side-by-side store, signed by Microsoft. A Windows DLL name loaded from the program's folder, unsigned or signed by someone else, usually means code placed where the search finds it first. It often sits beside a copy of a signed program in a folder a user can write to, so check each module's folder and signer against its name first.

What It Is

Before, a genuine program loads each Windows DLL from System32, SysWOW64 or the side-by-side store, and its vendor's DLLs from its install folder. After, it loads a DLL of the same name from its own folder or another folder a user can write to.

The program is unchanged and often signed, so only the module gives it away, unsigned or signed by someone its name does not suggest. A name on the Known DLLs list always loads from the system's own copy, so a stray copy of one is not the module that loaded.

Sysmon event 7 in the Sysmon Operational log and DeviceImageLoadEvents in Defender XDR record each load with the module's path, and a memory image's loader list holds it too. MITRE ATT&CK's detection for T1574.001 pairs the load with the DLL's file creation. T1574.008 is the same state for a program named like a system utility, running from an application's own folder.

What Changes Inside the Process

The process is shown before and after, and the pointer marks what changed.

Before

A clean Windows 11 install

version.dll as a program on a clean install loads it, from System32 and signed by Microsoft.
NamePathSigned By
version.dllC:\Windows\System32\version.dllMicrosoft Windows

After

srv-app-01,

The same name loaded by logshipper.exe on srv-app-01, 19 Oct 2026. This is an illustration, not part of the ws-042 incident.
NamePathSigned By
version.dllC:\ProgramData\LogShipper\version.dllNot signed
PathFound in the Program's Own Folder Before System32: Windows' version.dll Lives in System32 DLL Search Order Hijacking and Side-Loading

Look Inside

What It Leaves Behind

A trusted program, often signed and often run from a copy in a user-writable folder, loads a DLL with a familiar name from its own folder instead of System32. The DLL is often unsigned or signed by someone its name does not suggest, and written to disk shortly before it loads. A proxy DLL also forwards its exports to the real DLL of the same name. Sysmon event 7 and DeviceImageLoadEvents record the load with its path, and Sysmon event 11 or DeviceFileEvents record the write.

Why It Matters

The process is genuine and often signed, so a process listing passes it, but the code is in one of its modules. Only the module's folder, signer and age give it away.

Which Evidence Can See It

Each tile says whether that kind of evidence can see it, and what it shows.

  • Memory

    Sees it

    windows.dlllist shows each module's path while its process runs, so a Windows name from the wrong folder stands out.

  • EDR Telemetry

    Sees it

    Defender XDR's image load table records each load with its folder, its SHA1 and the process that loaded it. Its certificate table gives the signer.

  • Disk

    Partly

    The DLL sits in the folder it loaded from unless it was removed, with its signer and version information to compare with the genuine file.

  • Logs

    Partly

    Sysmon event 7 in the Sysmon Operational log records each load with its path, hashes and signature. It is off by default and logs only what its configuration keeps.

How to Confirm It

Work through these in order. Each step names the page that shows how.

  1. List the process's modules with their folders (ListDLLs, Process Explorer, windows.dlllist). A Windows DLL name outside System32, SysWOW64 or WinSxS stands out.Loaded DLLs
  2. Check the DLL's signature against its name. The pattern is a DLL that is unsigned, or signed by someone other than Microsoft for a Windows name, beside a program in a user-writable folder.Loaded DLLs
  3. Find what starts the trusted program from that folder. A task, a service or a Run key that points at a copy outside its install folder brings the DLL back at every start.Process Trees and Call Chains
  4. Look for proxy DLLs that forward their exports to a DLL of the same name. Velociraptor's Windows.Detection.ForwardedImports lists them once its file glob covers the program's folder, as by default it reads only C:\Windows.Loaded DLLs
  5. Collect the DLL and the program, or extract them from a memory image with windows.dumpfiles, and analyse them away from the machine.Dumping a Process and Memory

Investigation Steps With Named Tools

Each question has the tools that answer it on a running machine, and in a memory image, a copy of its memory saved to a file.

  • Where did each module load from, and who signed it?

    On a Running Machine

    In a Memory Image

  • Is the DLL the genuine file of that name?

    On a Running Machine

    In a Memory Image

What Defenders See

Each record names its log and what must be switched on to get it.

Record and Where It LandsWhat to ReadHow to Turn It On
7 Image loaded (opens in a new tab)Microsoft-Windows-Sysmon/OperationalIt is written on any Windows computer running Sysmon.ImageLoaded, Signed and SignatureStatus for each module show a Windows DLL name outside System32 that is unsigned or carries an unexpected signer.Loaded DLLs shows how to read it.Run Sysmon with ImageLoad events in its configuration. They are off by default.
DeviceImageLoadEvents (opens in a new tab)Each row is a DLL load, showing which module loaded into which process. The table has no signature columns, so join it to DeviceFileCertificateInfo on SHA1 to see who signed the module.Defender XDR, advanced huntingFileName and FolderPath of the module and the process that loaded it. Join DeviceFileCertificateInfo on SHA1 for the signer.The Defender for Endpoint sensor on the device
DeviceFileCertificateInfo (opens in a new tab)Each row is the signing certificate of a file seen on devices. It says whether the signature is embedded or comes from a catalogue file, and whether it is trusted.Defender XDR, advanced huntingIsSigned, Signer and IsTrusted for the DLL's SHA1 show whether it is unsigned, untrusted, or has a signer its name does not suggest.The Defender for Endpoint sensor on the device
11 FileCreate (opens in a new tab)Microsoft-Windows-Sysmon/OperationalIt is written on any Windows computer running Sysmon.TargetFilename of a new DLL beside a trusted program, written shortly before it loaded.Run Sysmon with FileCreate events in its configuration.
DeviceFileEvents (opens in a new tab)Each row is a file creation, modification or other file system event, so it shows when a binary landed and which process wrote it.Defender XDR, advanced huntingFileName, FolderPath and InitiatingProcessFileName show when the DLL landed and which process wrote it.The Defender for Endpoint sensor on the device

What It Looks Like

This record is decoded field by field, with what each value means.

7 Image loaded (opens in a new tab)On srv-app-01, . Sysmon event 7 for the planted DLL on srv-app-01, 19 Oct 2026.
Field, as the Record Writes ItWhat It Tells You
ImageC:\ProgramData\LogShipper\logshipper.exeThe program that loaded it: a signed vendor tool, run from ProgramData. A copy outside its install folder is the first oddity.
ImageLoadedC:\ProgramData\LogShipper\version.dllA Windows DLL name, loaded from the program's own folder. The real one lives in System32.
SignedfalseNo signature at all. The genuine DLL of that name is signed by Microsoft, so this copy is not it.
CompanyMicrosoft CorporationIts version information claims Microsoft, yet it carries no signature. Splunk's unsigned Microsoft DLL rule looks for exactly that, in its program's own folder.
HashesSHA256=(SHA-256 of the file)Search the hash in threat intelligence and across the estate. The same DLL elsewhere widens the incident.
False Positives

Some vendors ship their own copies of common DLLs beside their programs, and portable apps load DLLs from their own folders by design. Check the signer, and whether the vendor ships that file.

Installers and updaters stage signed programs and their DLLs in temporary folders and run them there.

Blind Spots

Sysmon event 7 is off by default and heavy when on, so a configuration that filters loads can drop the one that matters. Check yours before you trust a miss.

A DLL signed with a stolen or bought certificate passes a signature check, so judge the folder and the signer's name together.

Hunt It

The same hunt is written for four tools, so pick the one you use. Defender XDR and Sentinel queries are in KQL, which you paste into Advanced hunting in the Defender portal or into Sentinel's Logs page. Splunk queries are in SPL, for its Search page, and Velociraptor queries are in VQL, which you run as a hunt.

Needs Defender for Endpoint. DeviceImageLoadEvents has no signer, so the join adds it where Defender has seen the file's certificate. An empty Signer means no data, not proof of no signature.

KQLDefender XDR, Advanced hunting
// DLLs named like a System32 DLL, loaded from outside the system folders and not validly signed by Microsoftlet SystemDllNames = DeviceImageLoadEvents    | where Timestamp > ago(7d)    | where FolderPath startswith @"C:\Windows\System32\"    | distinct FileName;DeviceImageLoadEvents| where Timestamp > ago(30d)| where FileName in~ (SystemDllNames)| where not(FolderPath startswith @"C:\Windows\System32\" or FolderPath startswith @"C:\Windows\SysWOW64\" or FolderPath startswith @"C:\Windows\WinSxS\")| join kind=leftouter (DeviceFileCertificateInfo | summarize arg_max(Timestamp, IsSigned, IsTrusted, Signer) by SHA1) on SHA1| where isnull(IsSigned) or not(IsSigned) or not(IsTrusted) or not(Signer startswith "Microsoft")| summarize Loads = count(), Devices = dcount(DeviceId), FirstSeen = min(Timestamp)    by FileName, FolderPath, Signer, IsTrusted, InitiatingProcessFileName, InitiatingProcessFolderPath| order by Devices asc, Loads asc

In a Memory Image

Volatility 3 reads a memory image, and each of its plugins below shows part of this sign.

Rules to Compare With

Security vendors publish detection rules anyone can read. These look for the same thing, so compare your own with them.

Show the 6 Public Rules

How to Prevent It

Each control helps prevent it, and its line says what it does here.

Sources

MITRE ATT&CK is a free public catalogue of the techniques attackers use. Each technique has an ID, such as T1055 for Process Injection, so defenders can name the same behaviour the same way. This page covers these techniques.