Detecting T1574: hijack execution flow via the registry
8 min read
MITRE ATT&CK T1574, Hijack Execution Flow, is the family of techniques where an attacker does not write a new autostart entry and does not create a service — they wedge their own code into the path a legitimate program was already going to take. Several of the most useful T1574 sub-techniques are driven entirely from the registry, and they share one tell that makes COM hijack registry detection (and the rest of the family) tractable offline: a per-user HKCU entry that shadows or overrides the machine-wide HKLM definition. If you learn to read that one pattern, you cover a large slice of T1574 in a single pass over the right keys. This post walks the registry-driven variants of hijack execution flow, gives you the key path and the detection signal for each, and shows where the recurring red flag lives.
The registry hijack variants
DLL search order hijacking and KnownDLLs
The classic DLL search order hijack (T1574.001) is mostly a filesystem game — drop a malicious DLL where a process will find it before the legitimate one — but the registry decides the rules of that search. Two keys matter.
SYSTEM\CurrentControlSet\Control\Session Manager\KnownDLLs lists the system DLLs that are loaded from a fixed, protected location regardless of the application's directory. A DLL named here cannot be hijacked by a copy planted next to an executable. The detection signal is therefore inverted from most of this post: a removed or altered KnownDLLs entry is the finding. Compare the key against a known-good baseline of the same Windows build; an attacker who deletes ntdll-adjacent entries, or repoints one, is opening a search-order hole on purpose.
SYSTEM\CurrentControlSet\Control\Session Manager\SafeDllSearchMode is the master switch for safe DLL search order. When it is set to 1 (the modern default), the application directory is searched before the current working directory, which closes the easiest hijack. A value flipped to 0 weakens the search order machine-wide. Read the value; if it is absent the OS default applies, but an explicit 0 is worth a hard look.
Image File Execution Options
The IFEO Debugger hijack is the registry-purest member of the family. Under SOFTWARE\Microsoft\Windows NT\CurrentVersion\Image File Execution Options\<binary.exe>, a Debugger value tells Windows to launch the named debugger instead of the target binary whenever that binary is invoked. Set Debugger on sethc.exe or notepad.exe and you have redirected execution flow with a single string write. The related GlobalFlag / SilentProcessExit path under ...\SilentProcessExit\<binary.exe> triggers a monitor process when the target exits. Both are tracked under T1546.012, Event Triggered Execution: Image File Execution Options Injection — see the event-triggered execution deep-dive for the full treatment. The detection signal: any Debugger value pointing at something other than a real, signed debugger, and any IFEO subkey for a binary that has no legitimate reason to be debugged (accessibility binaries, AV executables, LOLBins).
COM object hijacking via HKCU\Software\Classes\CLSID
This is the variant the rest of the post keeps circling back to, and the one where the per-user override is the entire mechanism. COM resolves a class by its CLSID under Software\Classes\CLSID\{GUID}, and Windows merges two views of Software\Classes: the machine-wide HKLM\Software\Classes and the per-user HKCU\Software\Classes. The per-user view wins. An attacker who writes:
HKCU\Software\Classes\CLSID\{GUID}\InprocServer32
(Default) : C:\Users\bob\AppData\Roaming\evil.dll
has hijacked every COM activation of that CLSID for that user, overriding whatever HKLM has registered for the same GUID — without needing admin rights, because HKCU is user-writable. This is T1574.001/T1546.015 territory depending on how it fires, and it is extremely effective because the GUIDs attackers pick are ones that get activated constantly by Explorer, scheduled tasks, or background services. The detection signal is exact: a CLSID present under HKCU\Software\Classes\CLSID whose InprocServer32 (or LocalServer32) also exists under HKLM is a shadow override. A legitimate per-user COM registration is rare; a per-user override of a GUID that already has a perfectly good HKLM registration is the hijack. Pull the DLL it points at and check signature and path — AppData, Temp, and ProgramData are the usual homes.
The App Paths key
SOFTWARE\Microsoft\Windows\CurrentVersion\App Paths\<name.exe> lets a bare executable name (typed in Run, or invoked via ShellExecute) resolve to a full path. When a user runs winword.exe without a path, Windows consults App Paths\winword.exe and launches whatever the (Default) value points at, plus optional Path entries prepended to the DLL search path. An attacker repointing an existing App Paths entry, or adding one for a name a victim is likely to type, redirects that invocation to a payload. Like Classes, App Paths exists under both HKLM and (less commonly) HKCU, and the per-user copy takes precedence. The detection signal: an App Paths (Default) that does not match the real install location of the named binary, or any App Paths entry whose Path value adds a user-writable directory to the search path.
File-association and open-command (shell) hijacks
File associations resolve through Software\Classes, which means they inherit the same HKCU-beats-HKLM merge as COM. A file extension maps to a ProgID (Software\Classes\.txt → txtfile), and the ProgID's open verb is defined at Software\Classes\<progid>\shell\open\command. Whatever string sits in that (Default) runs when the user opens a file of that type, with the path passed as %1. An attacker who writes:
HKCU\Software\Classes\<progid>\shell\open\command
(Default) : C:\Users\bob\AppData\evil.exe "%1"
intercepts every open of that file type for the user, overriding the machine default. This covers protocol handlers too (Software\Classes\<protocol>\shell\open\command, e.g. ms-settings, the classic UAC-bypass target). The detection signal: an open-command under HKCU\Software\Classes for a ProgID or protocol that is also defined in HKLM, especially one whose command launches a binary from a user-writable path or wraps the legitimate handler with an extra process.
The recurring red flag: HKCU overriding HKLM
Step back and the pattern is the same in four of the five variants above: Software\Classes (COM CLSID, file associations, protocol handlers) and App Paths are all keys that Windows resolves by merging a machine-wide HKLM view with a per-user HKCU view, and the per-user view wins. That single design choice is what makes these hijacks attractive: they need no administrator rights, they survive in a hive (NTUSER.DAT) that per-machine sweeps often skip, and they only affect the targeted user, which keeps them quiet.
For the analyst it is a gift, because it collapses to one question you can ask mechanically: is there an HKCU\Software\Classes (or per-user App Paths) entry that shadows an existing HKLM definition? A clean system has very few legitimate per-user COM or association overrides. A per-user CLSID, ProgID open-command, or App Paths entry that duplicates a GUID or name already registered machine-wide — and points at a DLL or EXE in a user-writable directory — is the hijack, not a coincidence. KnownDLLs and IFEO are the two that break the HKCU/HKLM mold (both live machine-wide in SYSTEM/SOFTWARE), which is exactly why you check them separately.
How to hunt it
Triage is mechanical once you load the right hives — and the per-user hijacks mean NTUSER.DAT is not optional.
- Load both NTUSER.DAT and SOFTWARE/SYSTEM. The override is only visible when you can compare the per-user view against the machine view. A SOFTWARE-only sweep misses every
HKCUhijack in this post. - Enumerate
HKCU\Software\Classes\CLSID. For each CLSID present, check whether the same GUID has anInprocServer32/LocalServer32underHKLM\Software\Classes\CLSID. Any GUID in both is a shadow override — investigate the per-user DLL's path and signature first. - Diff the open-commands. Walk
HKCU\Software\Classes\<progid>\shell\open\commandand protocol handlers; flag any that override anHKLMProgID or that launch fromAppData/Temp/ProgramData. - Check
App Pathsin both hives. Compare each(Default)against the binary's real install path; flag addedPathentries pointing at user-writable directories. - Read IFEO. Enumerate
Image File Execution Optionsfor anyDebuggerorSilentProcessExitvalue, and treat an IFEO subkey on an accessibility/AV/LOLBin executable as a finding. - Baseline KnownDLLs and SafeDllSearchMode. Compare
KnownDLLsagainst a clean image of the same build; flagSafeDllSearchMode = 0.
The baseline is what makes all of this fast. Most of these keys are stable across the life of a machine and nearly identical across machines of the same build. Snapshot a known-good image once and the diff does the triage for you — a shadow CLSID or a rewritten open-command jumps out of a baseline that has not changed since OS install. Sort by key LastWrite to find the ones touched in your intrusion window. As always, LastWrite tells you a key was modified, not that it was created, so treat a recent timestamp as a lead, not a conclusion.
Investigate it in your browser
You do not need a live system or a Perl environment to run this. Load NTUSER.DAT, SOFTWARE, and SYSTEM and analyze the hive in your browser — the parser surfaces the CLSID, App Paths, file-association, IFEO, and KnownDLLs keys in a tree you can search and paste paths into, so you can pull up HKCU\Software\Classes\CLSID and the matching HKLM view side by side and spot the override without standing up tooling. The whole workflow above is reading keys and comparing two views; a browser tab does it.
Related techniques
Hijack execution flow sits next to the rest of the registry persistence surface, and the same hives carry it. For the IFEO Debugger and SilentProcessExit angle in full, see the event-triggered execution deep-dive (T1546.012). For the DLL-injection cousins that force a library into running processes rather than redirecting an invocation, see AppInit_DLLs and AppCertDLLs. And for the wider map of how these techniques line up against the framework, the MITRE ATT&CK and the registry overview puts T1574 in context with the persistence and privilege-escalation tactics it overlaps. The authoritative reference for the technique itself is MITRE's own T1574 page.
The bottom line for triage: T1574 in the registry is mostly the same move wearing different key paths — a per-user Software\Classes or App Paths entry that overrides a machine-wide definition, plus the two machine-wide outliers (IFEO and KnownDLLs) that you check on their own. Load NTUSER.DAT, compare the HKCU view against HKLM, and the shadow override is rarely subtle once you know it is the thing you are looking for.