Execution Guardrails
Adversaries may use execution guardrails to constrain execution or actions based on adversary-supplied and environment-specific conditions expected to be present on the target. Guardrails ensure a payload only executes against an intended target, reducing collateral damage from an adversary's campaign. Values used as guardrails include specific volume serial numbers, hostnames, Active Directory domain membership, IP addresses, the presence of specific files or processes, and specific command-line arguments. This technique is distinct from Virtualization/Sandbox Evasion (T1497): sandbox evasion avoids any analysis environment, while guardrails require a specific target environment to be confirmed before execution proceeds. Real-world examples include DEADEYE verifying volume serial number and hostname, Exbyte checking for a configuration file before completing execution, TONESHELL checking for ESET security processes (ekrn.exe, egui.exe) before injecting into waitfor.exe, BPFDoor using a PID mutex file at /var/run/haldrund.pid, RansomHub terminating if the machine appears on an allowlist, and Small Sieve requiring the literal keyword 'Platypus' as a command-line argument.
// T1480 Execution Guardrails — Environmental fingerprinting from suspicious execution contexts
// Detects processes performing target-validation checks (volume serial, hostname/domain, network identity,
// file presence, process presence) launched from LOLBin or script host parents.
// These behaviors are consistent with guardrail-enabled malware verifying it is on an intended target.
let ScriptHostsAndLolbins = dynamic([
"wscript.exe", "cscript.exe", "mshta.exe", "rundll32.exe",
"regsvr32.exe", "msiexec.exe", "installutil.exe", "cmstp.exe",
"powershell.exe", "pwsh.exe"
]);
let VolumeSerialPatterns = dynamic([
"VolumeSerialNumber", "Win32_LogicalDisk",
"vol c:", "vol d:", "vol e:", "fsutil volume"
]);
let DomainHostnamePatterns = dynamic([
"Win32_ComputerSystem", "DNSDomain", "userdnsdomain",
"logonserver", "nltest /domain_trusts", "nltest /dclist"
]);
let NetworkFingerprintPatterns = dynamic([
"Win32_NetworkAdapterConfiguration", "MACAddress",
"DefaultIPGateway", "Win32_NetworkAdapter"
]);
let FilePresencePatterns = dynamic([
"if exist", "if not exist", "Test-Path",
"haldrund.pid", "irc.pid"
]);
let ProcessPresencePatterns = dynamic([
"ekrn.exe", "egui.exe",
"tasklist /FI", "Get-Process -Name"
]);
DeviceProcessEvents
| where Timestamp > ago(24h)
| where InitiatingProcessFileName in~ (ScriptHostsAndLolbins)
or (FileName in~ ("wmic.exe", "nltest.exe") and InitiatingProcessFileName in~ (ScriptHostsAndLolbins))
| where ProcessCommandLine has_any (VolumeSerialPatterns)
or ProcessCommandLine has_any (DomainHostnamePatterns)
or ProcessCommandLine has_any (NetworkFingerprintPatterns)
or ProcessCommandLine has_any (FilePresencePatterns)
or ProcessCommandLine has_any (ProcessPresencePatterns)
| extend GuardrailType = case(
ProcessCommandLine has_any (VolumeSerialPatterns), "VolumeSerial",
ProcessCommandLine has_any (DomainHostnamePatterns), "DomainOrHostname",
ProcessCommandLine has_any (NetworkFingerprintPatterns), "NetworkIdentity",
ProcessCommandLine has_any (FilePresencePatterns), "FilePresence",
ProcessCommandLine has_any (ProcessPresencePatterns), "ProcessPresence",
"Unknown"
)
| extend RiskScore = case(
GuardrailType == "VolumeSerial", 3,
GuardrailType == "ProcessPresence" and ProcessCommandLine has_any ("ekrn.exe", "egui.exe"), 3,
GuardrailType in ("DomainOrHostname", "FilePresence", "ProcessPresence"), 2,
1
)
| project Timestamp, DeviceName, AccountName, FileName, ProcessCommandLine,
InitiatingProcessFileName, InitiatingProcessCommandLine,
GuardrailType, RiskScore
| sort by RiskScore desc, Timestamp desc Data Sources
Required Tables
False Positives
- Legitimate deployment scripts (SCCM, Group Policy) that check domain membership or hostname before applying configuration — typically parent process is svchost.exe or ccmexec.exe, not a LOLBin
- Monitoring and inventory agents (Tanium, Qualys, SolarWinds) that enumerate network adapter properties or system info — whitelist by exact parent process name
- IT automation tools (PDQ Deploy, Altiris) that verify target environment before running installation packages
- Developer environment setup scripts that check for specific environments (dev/staging/prod) using hostname or domain name
- Backup software (Veeam, Acronis) that queries volume serial numbers for backup source identification — typically runs as a known service account
References (9)
- https://attack.mitre.org/techniques/T1480/
- https://www.cyberscoop.com/kevin-mandia-fireeye-u-s-malware-nice/
- https://www.fireeye.com/blog/threat-research/2019/12/breaking-the-rules-tough-outlook-for-home-page-attacks.html
- https://www.trellix.com/blogs/research/qakbot-evolves-to-onenote-malware-distribution/
- https://www.sandflysecurity.com/blog/bpfdoor-an-evasive-linux-backdoor-technical-analysis/
- https://www.mandiant.com/resources/blog/apt41-us-state-tax-departments
- https://github.com/redcanaryco/atomic-red-team/blob/master/atomics/T1480/T1480.md
- https://github.com/SigmaHQ/sigma/search?q=T1480
- https://learn.microsoft.com/en-us/windows/win32/wmisdk/wmi-start-page
Unlock Pro Content
Get the full detection package for T1480 including response playbook, investigation guide, and atomic red team tests.