AppDomainManager
Adversaries may execute their own malicious payloads by hijacking how the .NET AppDomainManager loads assemblies. Known as AppDomainManager injection, this technique forces a legitimate .NET application to load and execute a malicious assembly by manipulating application configuration files (.exe.config), setting process environment variables (APPDOMAIN_MANAGER_ASM, APPDOMAIN_MANAGER_TYPE, or their COMPlus_ prefixed equivalents — COMPlus_AppDomainManagerAsm, COMPlus_AppDomainManagerType), or modifying HKLM\SOFTWARE\Microsoft\.NETFramework registry keys. Because the malicious code executes inside a trusted .NET host process, it inherits the process's privileges and evades detections focused on process-spawn anomalies. Iran-nexus threat actor Yellow Liderc (IMPERIAL KITTEN) deployed IMAPLoader malware against maritime, shipping, and logistics sector victims using this technique. Real-world usage demonstrates that adversaries target high-value .NET host processes (IIS worker processes, MSBuild, InstallUtil, custom enterprise applications) to maximize privilege and blend into legitimate process telemetry.
// T1574.014 — AppDomainManager Injection
// Detection covers three injection vectors: registry, config file, and suspicious assembly load
let SuspiciousPaths = dynamic([
@"\Temp\", @"\AppData\Local\Temp\", @"\AppData\Roaming\",
@"\ProgramData\", @"\Users\Public\", @"\Downloads\",
@"\Desktop\", @"\AppData\Local\Microsoft\Windows\INetCache\"
]);
let DotNetHostProcesses = dynamic([
"dotnet.exe", "msbuild.exe", "installutil.exe", "regsvcs.exe",
"regasm.exe", "aspnet_compiler.exe", "csc.exe", "vbc.exe",
"mscorsvw.exe", "ngen.exe", "dfsvc.exe"
]);
// Vector 1: Registry-based AppDomainManager hijack
let RegistryVector =
DeviceRegistryEvents
| where Timestamp > ago(24h)
| where RegistryKey has @"SOFTWARE\Microsoft\.NETFramework"
| where RegistryValueName in~ ("AppDomainManagerAsm", "AppDomainManagerType")
| extend InjectionVector = "Registry"
| extend DetectionDetail = strcat("Registry key: ", RegistryKey, " | Value: ", RegistryValueName, " = ", RegistryValueData)
| project Timestamp, DeviceName, AccountName, ActionType, InjectionVector, DetectionDetail,
InitiatingProcessFileName, InitiatingProcessCommandLine, InitiatingProcessAccountName;
// Vector 2: Suspicious .config file creation or modification
let ConfigFileVector =
DeviceFileEvents
| where Timestamp > ago(24h)
| where FileName endswith ".exe.config" or (FileName endswith ".config" and FileName !endswith ".web.config")
| where ActionType in ("FileCreated", "FileModified", "FileRenamed")
| where FolderPath has_any (SuspiciousPaths)
or (FolderPath !has @"\Program Files" and FolderPath !has @"\Windows\" and FolderPath !has @"\Program Files (x86)")
| where InitiatingProcessFileName !in~ ("msiexec.exe", "setup.exe", "installer.exe", "update.exe", "updater.exe")
| extend InjectionVector = "ConfigFile"
| extend DetectionDetail = strcat("Config file: ", FolderPath, "\\", FileName, " | Action: ", ActionType)
| project Timestamp, DeviceName, AccountName, ActionType, InjectionVector, DetectionDetail,
InitiatingProcessFileName, InitiatingProcessCommandLine, InitiatingProcessAccountName;
// Vector 3: .NET host process loading assembly from suspicious/writable path
let AssemblyLoadVector =
DeviceImageLoadEvents
| where Timestamp > ago(24h)
| where FileName endswith ".dll"
| where FolderPath has_any (SuspiciousPaths)
| where (InitiatingProcessFileName in~ (DotNetHostProcesses))
or (InitiatingProcessFolderPath has @"\Microsoft.NET\Framework")
or (InitiatingProcessFolderPath has @"\Microsoft.NET\Framework64")
| extend InjectionVector = "AssemblyLoad"
| extend DetectionDetail = strcat("Assembly: ", FolderPath, "\\", FileName, " loaded by ", InitiatingProcessFileName)
| project Timestamp, DeviceName, AccountName, ActionType = "AssemblyLoaded", InjectionVector, DetectionDetail,
InitiatingProcessFileName, InitiatingProcessCommandLine, InitiatingProcessAccountName;
union RegistryVector, ConfigFileVector, AssemblyLoadVector
| sort by Timestamp desc Data Sources
Required Tables
False Positives
- Software development environments (Visual Studio, JetBrains Rider) that create .exe.config files during build/debug cycles in user profile paths
- Custom enterprise .NET applications legitimately installing themselves to %APPDATA% or %ProgramData% with valid config files referencing side-by-side assemblies
- NuGet package installations or .NET tool installs via 'dotnet tool install' that place assemblies in %USERPROFILE%\.dotnet\tools or %APPDATA%\NuGet directories
- Legitimate AppDomainManager extensions used by application frameworks (Unity Engine, Mono runtime, .NET testing frameworks like xUnit AppDomain isolation)
- Security or monitoring software that hooks into .NET processes for telemetry collection using documented AppDomain extensibility
References (11)
- https://attack.mitre.org/techniques/T1574/014/
- https://pentestlaboratories.com/2020/05/26/appdomainmanager-injection-and-detection/
- https://www.rapid7.com/blog/post/2023/05/05/appdomain-manager-injection-new-techniques-for-red-teams/
- https://www.pwc.com/gx/en/issues/cybersecurity/cyber-threat-intelligence/yellow-liderc-ships-its-scripts-delivers-imaploader-malware.html
- https://learn.microsoft.com/dotnet/framework/app-domains/application-domains
- https://learn.microsoft.com/en-us/dotnet/api/system.appdomainmanager
- https://learn.microsoft.com/en-us/dotnet/framework/configure-apps/file-schema/runtime/appdomainmanagerassembly-element
- https://bohops.com/2022/04/02/unmanaged-code-execution-with-net-dynamic-pinvoke/
- https://github.com/redcanaryco/atomic-red-team/blob/master/atomics/T1574.014/T1574.014.md
- https://www.mandiant.com/resources/blog/tracking-apt29-phishing-campaigns
- https://github.com/SigmaHQ/sigma/blob/master/rules/windows/registry/registry_set/registry_set_appdomain_manager_injection.yml
Unlock Pro Content
Get the full detection package for T1574.014 including response playbook, investigation guide, and atomic red team tests.