Hijack execution flow lets an attacker run their own code inside a trusted, often signed and sometimes privileged process, simply by controlling which library or binary the operating system finds first. MITRE ATT&CK tracks it as T1574 Hijack Execution Flow, placed in ATT&CK v20 under the Stealth (TA0005) and Execution (TA0002) tactics, with 12 active sub-techniques across Windows, Linux and macOS. DLL side-loading alone is listed against more than a hundred groups, campaigns and malware families in the v20 dataset, including PlugX, Mustang Panda, APT41 and the 3CX supply chain attack. This guide explains the mechanics at the level of the ATT&CK descriptions, then concentrates on what defenders can log, block and fix. It is for detection engineers, endpoint and platform teams, and developers who ship Windows or Unix software.
Key takeaways
- The loader is the attack surface. Every T1574 variant abuses a search order or a configuration point (DLL search order, PATH, LD_PRELOAD, service ImagePath, .NET profiler settings) that decides what code a legitimate process loads.
- Writable paths are the root cause. Most sub-techniques need write access to a directory, file or registry key that a more trusted process reads; removing that write access closes the class, not just one instance.
- Signed does not mean safe. Side-loading pairs a genuine signed executable with an unsigned or foreign-signed library, so detection must look at the library, its path and its signer, not only the parent executable.
- Application control has to cover libraries. Allowlisting that only checks executables misses this technique; App Control for Business user-mode enforcement, macOS library validation and Linux allowlisting extend to loaded code.
- Developers can remove whole sub-techniques. Fully qualified load paths, restricted DLL search flags, quoted service paths and hardened runtime builds prevent hijacking before any security tool is involved.
How the attack works
ATT&CK describes T1574 as adversaries executing their own payloads by hijacking the way operating systems run programs, including how the system locates programs and libraries, and by poisoning the locations searched, such as directories and, on Windows, the Registry. The same placement gives persistence (the hijack reoccurs each time the host program runs), privilege escalation (when the host runs as SYSTEM or root) and stealth (the malicious code runs inside a trusted process). From a defender's view three conditions are always present:
- An unqualified reference: a program loads a library or launches a binary by name, a relative path, an unquoted path with spaces, or through an environment variable.
- A writable earlier location: the attacker can write to a location searched before the legitimate one, or can change the setting that points to it.
- A trigger: a user launch, service start, scheduled task or reboot causes the host program to run.
On Windows, Microsoft documents the standard search order for unpackaged applications with safe DLL search mode enabled: DLL redirection, API sets, side-by-side manifest redirection, the loaded-module list, Known DLLs, the package dependency graph (Windows 11 21H2 and later), the application's folder, the system folder, the 16-bit system folder, the Windows folder, the current folder and finally the directories in PATH. The application folder sits ahead of System32, which is why copying a signed executable into a user-writable folder next to a planted DLL works. On Linux, the dynamic linker loads anything named in LD_PRELOAD or /etc/ld.so.preload before other libraries, then searches DT_RPATH, LD_LIBRARY_PATH, DT_RUNPATH, /etc/ld.so.cache and the default library directories.
| ID | Name (ATT&CK v20) | What is hijacked | Platforms |
|---|---|---|---|
| T1574.001 | DLL | Side-loading, search order hijacking, DLL redirection, phantom DLLs and DLL substitution | Windows |
| T1574.004 | Dylib Hijacking | A dylib with an expected name in an @rpath or weak-linked search location | macOS |
| T1574.005 | Executable Installer File Permissions Weakness | Binaries an installer runs from a writable directory | Windows |
| T1574.006 | Dynamic Linker Hijacking | LD_PRELOAD, /etc/ld.so.preload, DYLD_INSERT_LIBRARIES | Linux, macOS |
| T1574.007 | Path Interception by PATH Environment Variable | An earlier, writable directory in PATH | Linux, macOS, Windows |
| T1574.008 | Path Interception by Search Order Hijacking | Programs launched without a full path | Windows |
| T1574.009 | Path Interception by Unquoted Path | Service or shortcut paths with spaces and no quotes | Windows |
| T1574.010 | Services File Permissions Weakness | A service binary or its folder writable by non-admins | Windows |
| T1574.011 | Services Registry Permissions Weakness | Weak ACLs on keys under HKLM\SYSTEM\CurrentControlSet\Services | Windows |
| T1574.012 | COR_PROFILER | A profiling DLL loaded into every .NET CLR process | Windows |
| T1574.013 | KernelCallbackTable | Callback pointers in a GUI process's PEB | Windows |
| T1574.014 | AppDomainManager | How .NET loads assemblies into application domains | Windows |
The former side-loading sub-technique T1574.002 is revoked and now covered by T1574.001, so update rule tags and coverage maps that still use it.
Where it shows up
- Initial loaders: phishing archives and ISO files that carry a signed vendor executable, a malicious DLL and an encrypted payload, so the visible process is genuine. ATT&CK records PlugX (S0013) using both search order hijacking and side-loading, and Mustang Panda (G0129) using a legitimately signed executable to run a malicious DLL. See the ISO and Container File Malware Delivery Guide.
- Supply chain: in the 3CX Supply Chain Attack (C0057), ATT&CK notes the attackers split functionality across multiple DLLs to execute code from an embedded DLL inside another, which complicates analysis because every file must be collected. See the Malware Loaders and Droppers Guide.
- Privilege escalation on servers: unquoted service paths, writable service folders and weak service registry ACLs turn a standard user foothold into SYSTEM on the next service start.
- Linux persistence: an entry in
/etc/ld.so.preloadinjects a library into every dynamically linked program. - Developer and admin workstations: user-writable tool folders early in
PATH(package manager bins, local script folders) let a planted binary shadowgit,pythonorssh.
Impact
The direct impact is code execution under the identity, privileges and reputation of the host process. If the host is a service running as LocalSystem, a backup agent or an EDR component, the attacker inherits that context. Because the process image and signature look normal, hijacking is used to slip past allowlists that trust the executable, to hide command and control inside a trusted binary, and to persist without creating new services or Run keys that most teams already monitor.
Detection
MITRE's v20 detection strategies for T1574 describe the same behaviour on each platform: library loads from abnormal paths, writes into directories a trusted program searches, changes to service paths or registry keys, and modifications to linker configuration. The table below maps them to concrete telemetry.
| Behaviour | Telemetry | What to alert on |
|---|---|---|
| DLL loaded from an unusual path (.001) | Sysmon Event ID 7 (Image loaded), EDR module-load events | Signed process loading an unsigned or differently signed DLL from a user-writable folder (%APPDATA%, %TEMP%, Downloads, C:\ProgramData); a system DLL name loaded from outside System32 |
| Executable and DLL dropped together | Sysmon Event ID 11 (FileCreate), Event ID 29 (FileExecutableDetected) | A known vendor executable and a DLL written to the same new folder within seconds, followed by Event ID 1 process creation from that folder |
| Service path or binary changed (.009, .010, .011) | Sysmon Event ID 13 (Registry value set) on ImagePath, Event ID 16 config change; Windows System 7045 and Security 4697 service installed | ImagePath, ServiceDll or FailureCommand pointing to a user-writable path; service binary hash changing outside a patch window |
| .NET profiler or AppDomainManager abuse (.012, .014) | Registry value set for COR_ENABLE_PROFILER, COR_PROFILER, COR_PROFILER_PATH; file creation of .config files beside .NET executables | Profiler variables set at system or user scope on hosts that are not developer machines |
| Linux preload abuse (.006) | auditd watch on /etc/ld.so.preload and /etc/ld.so.conf.d/, process environment from EDR or osquery | Any write to /etc/ld.so.preload; LD_PRELOAD set for daemons or SSH sessions |
| macOS dylib injection (.004, .006) | Unified log, Endpoint Security framework events from EDR | DYLD_INSERT_LIBRARIES in a launch agent or daemon plist; unsigned dylibs loaded by apps that should enforce library validation |
Volume control: Microsoft notes that Sysmon Event ID 7 is disabled by default and that logging every image load produces a large volume. Enable it with include filters: unsigned modules, modules loaded from user-writable paths, and modules loaded by a short list of commonly abused signed binaries. See the Sysmon Guide and the EDR Guide.
Proactive hunting: Microsoft's DLL security guidance describes using Process Monitor with filters on CreateFile and LoadImage operations for .dll, .exe, .ocx and similar files, excluding SUCCESS results, to find programs that probe for missing libraries. The failed probes are the phantom DLL opportunities an attacker would use.
Measures that show it is working:
- Number of services with unquoted paths containing spaces, or with binaries or folders writable by non-admins (target zero, trend weekly).
- Percentage of endpoints where library loads are covered by application control in enforced mode.
- Unsigned or foreign-signed DLL loads from user-writable paths per 1,000 endpoints per day, after tuning.
- Count of hosts with a non-empty
/etc/ld.so.preloador system-wideCOR_PROFILERthat is not on an approved list. - Median time from a side-loading alert to containment of the host.
Prevention and hardening
| Control | ATT&CK mitigation | Practical setting |
|---|---|---|
| Restrict library loading | M1044 Restrict Library Loading | Keep HKLM\System\CurrentControlSet\Control\Session Manager\SafeDllSearchMode enabled (the default; do not set it to 0); protect the KnownDLLs key; disallow remote DLL loading |
| Application control for libraries | M1038 Execution Prevention | App Control for Business with option 0 Enabled:UMCI so user-mode binaries are checked; start with 3 Enabled:Audit Mode; prefer FilePublisher or Hash rules over FilePath; keep the runtime FilePath protection (do not set 18 Disabled:Runtime FilePath Rule Protection) |
| Write-protect search locations | M1022 Restrict File and Directory Permissions | Install software only under Program Files or root-owned paths; remove write rights for Users and Authenticated Users from service folders and any folder in the system PATH |
| Protect service configuration | M1024 Restrict Registry Permissions, M1018 User Account Management | Audit ACLs on service keys; only administrators can change ImagePath; quote every service path that contains spaces |
| Find weaknesses first | M1047 Audit | Scheduled scans for unquoted service paths, writable service binaries, writable PATH entries and phantom DLL loads in gold images |
| Fix the software | M1013 Application Developer Guidance, M1051 Update Software | Fully qualified paths; SetDefaultDllDirectories with LOAD_LIBRARY_SEARCH_SYSTEM32; SetDllDirectory("") early in start-up; hashes in manifests; patch vendor side-loading bugs |
| Linux and macOS loader settings | M1028 Operating System Configuration | Treat /etc/ld.so.preload as must-be-empty; ship macOS apps with the Hardened Runtime and without the allow-dyld-environment-variables or disable-library-validation exceptions unless justified |
| Limit elevation | M1052 User Account Control | Standard users cannot approve elevation; installer detection enabled |
On Linux, the dynamic linker's secure-execution mode already ignores LD_LIBRARY_PATH and slash-containing LD_PRELOAD entries for set-user-ID programs, so the system-wide /etc/ld.so.preload file is the higher risk; the ld.so manual itself describes it as usually undesirable. On macOS, Apple states that the Hardened Runtime, with System Integrity Protection, protects against code injection and library hijacking, and that it is required for notarisation. See the fapolicyd and Linux Application Allowlisting Guide and the macOS Security Guide for Enterprises.
Rollout order
- Inventory and fix weaknesses: run the M1047 audit across servers and gold images; fix unquoted paths, writable service folders and weak service key ACLs first, because these give privilege escalation.
- Turn on telemetry: enable filtered Sysmon Event ID 7 and the file and registry events above on a pilot ring; tune for two to four weeks against software deployment tools and updaters.
- Application control in audit mode: deploy an App Control for Business policy with UMCI and audit mode; collect the would-block events for DLLs, merge legitimate publishers into the policy.
- Enforce by ring: enforce on servers and privileged access workstations first, then on standard endpoints. Keep the previous policy version signed and ready to redeploy as the rollback path, and test the rollback once.
- Close the loop with development: add the Process Monitor phantom-DLL test and service path checks to release testing for in-house software and vendor onboarding. See the Application Allowlisting Guide.
Small versus large estates: a small organisation gets most of the value from fixing permissions, keeping users off local admin and enabling the EDR's library-load protections. Large estates with many line-of-business applications should expect application control for DLLs to take months and should prioritise servers, domain controllers and admin workstations.
Where identity fits
T1574 is ultimately an abuse of trust in a process identity. Services that run as LocalSystem or under highly privileged service accounts make every weak path on their load route a privilege escalation, and local admin rights on workstations let attackers write to the protected folders that would otherwise stop the technique. Run services under managed, least-privileged accounts, remove standing local admin and rotate local administrator passwords. See the Windows Services and Service Account Security Guide and the Local Administrator Password Solution (LAPS) Guide.
Common failure patterns
- Allowlisting executables only: an allowlist that trusts a signed vendor binary but never checks the libraries it loads is the exact gap side-loading targets.
- FilePath rules on writable folders: allowing a path that users can write to turns the allowlist into a side-loading launch pad; this is why App Control checks that FilePath rules point to admin-writable paths by default.
- Alerting on signatures alone: treating "signed by a known vendor" as benign on the process, while ignoring that the loaded module is unsigned.
- Removing the file, not the weakness: deleting a planted DLL while the folder ACL, unquoted path or service key permission stays as it was.
Framework mapping
| Framework | Reference | Relevance |
|---|---|---|
| NIST CSF 2.0 | PR.PS-05, PR.PS-01, DE.CM-09 | Prevent unauthorised software execution, configuration management, runtime monitoring |
| NIST SP 800-53 Rev. 5 | CM-5(6) Limit Library Privileges, CM-7 Least Functionality, SI-7, AC-6, SI-4 | Library write protection, allowlisting, integrity checks, least privilege, monitoring |
| CIS Controls v8.1 | Safeguards 2.5, 2.6 and 2.7 | Allowlist authorised software, libraries and scripts |
| ISO/IEC 27001:2022 Annex A | A.8.7, A.8.19, A.8.9, A.8.16 | Malware protection, software installation, configuration management, monitoring |
| MITRE D3FEND | D3-EAL Executable Allowlisting | Countermeasure for unapproved executables and libraries |
Practitioner checklist
- Scan every server and gold image for unquoted service paths, writable service binaries and folders, and weak service registry ACLs; fix them before anything else.
- Confirm SafeDllSearchMode has not been disabled anywhere and that the KnownDLLs key is protected.
- Remove user-writable directories from the system
PATHon Windows and from root'sPATHon Linux. - Enable filtered Sysmon Event ID 7 or equivalent EDR module-load telemetry for unsigned and user-path loads.
- Alert on any write to
/etc/ld.so.preloadand on system-wideCOR_PROFILERsettings. - Extend application control to libraries in audit mode, then enforce on servers and admin workstations.
- Add phantom DLL and service path checks to release testing for in-house and vendor software.
- Remove standing local admin and run services under least-privileged managed accounts.
Standards and references
- MITRE ATT&CK: Hijack Execution Flow (T1574)
- MITRE ATT&CK: Hijack Execution Flow: DLL (T1574.001)
- Microsoft Learn: Dynamic-link library search order
- Microsoft Learn: Dynamic-Link Library Security
- Microsoft Learn: Understand App Control for Business policy rules and file rules
- Microsoft Sysinternals: Sysmon
- Linux man-pages: ld.so(8)
- Apple Developer: Hardened Runtime
Related NHI Mgmt Group resources: Malware Guide · T1055 Process Injection Defensive Guide · ATT&CK Stealth and Defense Impairment Tactics Guide · EDR Evasion and Defence Guide