What Is an APT Campaign?
HuntRule Team · · 8 min read

On this page
SUNBURST does nothing for the first 12 to 14 days after its DLL is written to disk. FireEye documented that the exact threshold is picked at random from that interval, and that the backdoor keeps re-checking the file write time on every run of the legitimate recurring background task that loads it. That single design choice is why the trojanized Orion updates signed between March and May 2020 were not caught until December 2020.
A campaign is what you call the set of intrusions that share that implant, that dormancy window and that objective. Not an actor. Not a malware family. A bounded set of intrusions linked by evidence, with a start, an end, and a common goal.
What a campaign actually is
Three things have to hold. The intrusions share an objective, they fall inside a time window, and they overlap in tradecraft strongly enough that a different operator is a worse explanation than the same one. Drop any of the three and you have a cluster, not a campaign.
MITRE ATT&CK tracks the SolarWinds Compromise as campaign C0024 and attributes it to APT29 (G0016). The same activity was published under five vendor names before the merges settled: UNC2452 by FireEye, NOBELIUM and Solorigate by Microsoft, Dark Halo by Volexity, StellarParticle by CrowdStrike, and SolarStorm by Palo Alto Unit 42. In April 2021 the US and UK governments attributed it to Russia's SVR. Mandiant merged UNC2452 into APT29 in 2022.
Linking evidence, strongest first
Shared implant configuration and keys are the strongest link. These are per-build constants an operator does not vary between victims. FireEye published SUNBURST's guard pipe 583da945-62af-10e8-4902-a8f205c72b2e, its abuse of the ReportWatcherRetry key inside SolarWinds.Orion.Core.BusinessLayer.dll.config as persistent config storage, and its FNV-1a variant that XORs the finished hash with 6605813339339102567 to check that its own process name hashes to 17291806236368054941. Two samples carrying all of that came out of one build pipeline.
Infrastructure reuse comes next. SUNBURST resolved DGA subdomains under avsvmcloud[.]com, concatenated with one of four fixed regional prefixes such as .appsync-api.us-west-2[.]avsvmcloud[.]com. This is what actually merged two separate investigations. Volexity had worked three incidents at a US think tank across late 2019 and 2020 under the name Dark Halo, and stated it tied them to FireEye's UNC2452 report through overlap in C2 domains plus a backdoored Orion server. Note the limit though. FireEye also documented that the operators set their C2 hostnames to match a legitimate hostname inside each victim's environment, so a large part of the infrastructure was deliberately unique per victim and links nothing.
Code overlap and compilation artifacts are third, and they are suggestive rather than decisive. In January 2021 Kaspersky published overlaps between SUNBURST and Kazuar, a backdoor previously associated with Turla: a modified FNV-1a in both, an MD5-plus-XOR routine for generating victim UIDs in both, and a sleep routine built on the same Random().NextDouble() formula, with Kazuar picking two to four weeks and SUNBURST picking 12 to 14 days. Kaspersky listed five explanations, including shared source, a developer moving teams, and a deliberate false flag, and wrote that it did not know which was true. That is the correct posture for code overlap.
Tradecraft sequence is fourth. Order matters more than any single step. Microsoft documented the second-stage activation chain in January 2021:
SolarWinds.BusinessLayerHost.exewrites a VBScript named after an existing service or folder on the host.It writes a Cobalt Strike loader DLL, compiled uniquely per machine, into a plausible subfolder of
%WinDir%. Published paths includeC:\Windows\SKB\LangModel.dll,C:\Windows\Registration\crmlog.dllandC:\Windows\ELAMBKUP\WdBoot.dll, each one letter or extension away from a real Windows object.It sets an Image File Execution Options Debugger value for
dllhost.exe.Whenever
dllhost.exenext runs on its own, the Debugger value launcheswscript.exeagainst the VBScript.The VBScript runs
rundll32.exeagainst the loader export.
Target selection is last and weakest. CISA and its partners assessed that around 18,000 SolarWinds customers received the trojanized update while a much smaller number saw follow-on activity, and FireEye showed the DGA encoded the victim's machine domain so operators could pick who to advance on. Sharing a vendor, a sector or a country is a starting hypothesis, not a link. Vendors do publish campaign clusters built mostly on sector and geography. Read those as a lead to be tested, and check what else the report puts on the table.
Where the Diamond Model fits
Caltagirone, Pendergast and Betz published the Diamond Model of Intrusion Analysis in 2013. Every event has four core features: adversary, capability, infrastructure and victim. Meta-features let you chain events into activity threads and cluster threads into activity groups, which is the formal name for what everyone calls a campaign.
The ordering above maps onto it. Implant config and code overlap are capability. Domains and certificates are infrastructure. Target selection is victim. Adversary is the vertex you almost never observe directly, which is why the strongest links are the ones furthest from it.
One documented behaviour, one rule
Step 3 in that chain is the piece worth detecting, because it is the only step that does not depend on a filename, a folder or a domain that the operators varied per victim. The Debugger value under Image File Execution Options is T1546.012. Here is the rule.
title: Image File Execution Options Debugger Value Set
id: 9e7d4a1c-3f52-4b8e-a0d6-5c2f81b7ad34
status: experimental
description: >
Detects a Debugger value written under an Image File Execution Options key.
Setting a Debugger for a benign binary makes Windows launch the attacker's
process instead, as documented by Microsoft in the Solorigate second-stage
chain where dllhost.exe was hijacked to launch wscript.exe.
references:
- https://www.microsoft.com/en-us/security/blog/2021/01/20/deep-dive-into-the-solorigate-second-stage-activation-from-sunburst-to-teardrop-and-raindrop/
- https://attack.mitre.org/techniques/T1546/012/
author: HuntRule
date: 2026-07-31
tags:
- attack.persistence
- attack.privilege-escalation
- attack.t1546.012
logsource:
category: registry_set
product: windows
detection:
selection:
TargetObject|contains: '\Microsoft\Windows NT\CurrentVersion\Image File Execution Options\'
TargetObject|endswith: '\Debugger'
filter_empty:
Details: '(Empty)'
filter_appverif:
Details|contains: '\AppVerifierUI.exe'
condition: selection and not 1 of filter_*
falsepositives:
- Application Verifier and gflags.exe from the Windows debugging tools
- Installers that legitimately register a debugger for their own binary
- Some endpoint agents that hook processes through IFEO
level: highWhat it catches and what it misses
It catches the write, not the payload. Any Debugger value set under the IFEO path fires, on both the native and the WOW6432Node hive, which is why the selection matches on a substring rather than a fixed prefix. Nothing in it references SolarWinds, so it survives the campaign it came from.
It misses three things. The operators could reach the same result through SilentProcessExit, which lives under HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\SilentProcessExit\ with MonitorProcess and ReportingMode values instead of a Debugger, and this rule is blind to that. It also does not see the VBScript drop or the rundll32.exe execution, so on its own it gives you one event with no context. And it depends entirely on your Sysmon config not filtering the IFEO path out of Event ID 13, which many shipped configs do by default. We have not measured the volume this produces on a large estate, so treat the level as a starting point.
Pair it with process creation coverage for wscript.exe spawning rundll32.exe. That combination is what makes the chain legible rather than a lone registry write. If you want the wider background on turning a report into maintained detection logic, see /blog/what-is-detection-engineering.
What a campaign buys a defender
A time window and a behaviour list. That is more actionable than the actor name.

For C0024 the retro-hunt scope falls out of the reporting. Trojanized updates were signed between March and May 2020, the implant sat dormant for 12 to 14 days after install, and disclosure was 13 December 2020. So the search window for activation and follow-on activity is roughly late March 2020 to mid-December 2020. Bounded. Nine months of logs, not everything you have.
Compare that with the actor name. ATT&CK describes APT29 as operating since at least 2008. "Hunt for APT29" gives you no window, no prioritised behaviour and no stopping condition. "Hunt for C0024" gives you an IFEO Debugger write on dllhost.exe, a wscript.exe to rundll32.exe parent chain, DNS for *.avsvmcloud[.]com, and a date range to run all three against.
ATT&CK mapping
Technique | Name | Campaign artifact |
|---|---|---|
T1195.002 | Supply Chain Compromise: Compromise Software Supply Chain | Trojanized Orion hotfix MSP |
T1553.002 | Subvert Trust Controls: Code Signing | DLL signed with a SolarWinds certificate |
T1568 | Dynamic Resolution | DGA subdomains of avsvmcloud[.]com |
T1546.012 | Event Triggered Execution: Image File Execution Options Injection | Debugger value on dllhost.exe |
T1059.005 | Command and Scripting Interpreter: Visual Basic | VBScript run by wscript.exe |
T1218.011 | System Binary Proxy Execution: Rundll32 | Cobalt Strike loader export |
Summary
A campaign is a bounded set of intrusions sharing an objective, a time window and enough tradecraft overlap to survive a different explanation. Rank your linking evidence: implant configuration and keys first, infrastructure second, code overlap third, tradecraft sequence fourth, target selection last and on its own never enough. The SolarWinds compromise became one campaign because Volexity's Dark Halo domains overlapped FireEye's UNC2452 domains, not because the victims looked alike. Take the behaviours and the dates from a campaign report and leave the actor name where you found it.
Windows detections for this chain live under /rules?domain=windows, and the persistence primitive itself under [/rules?q=image file execution options](/rules?q=image file execution options).
Telemetry to collect for a C0024-shaped retro-hunt
Sysmon 13 / registry auditing Debugger value writes under Image File Execution Options
Sysmon 1 or Security 4688 wscript.exe parented by dllhost.exe
Sysmon 1 or Security 4688 rundll32.exe parented by wscript.exe
Sysmon 11 .dll and .vbs writes under C:\Windows\* subfolders
Sysmon 22 or DNS logs queries for *.avsvmcloud.com
Published SUNBURST constants (FireEye, 13 December 2020)
named pipe 583da945-62af-10e8-4902-a8f205c72b2e
config key ReportWatcherRetry in SolarWinds.Orion.Core.BusinessLayer.dll.config
DLL MD5 b91ce2fa41029f6955bff20079468448
cert serial 0f:e9:73:75:20:22:a6:06:ad:f2:a3:6e:34:5d:c0:edRelated articles

What Is Operational Threat Intelligence?
AnyDesk, Fleetdeck.io, Level.io, Mimikatz, Ngrok, Pulseway, Screenconnect, Splashtop, Tactical.RMM, Tailscale, TeamViewer and Teleport.sh. That is Table 1 of CISA advisory AA23-320A, the legitimate…
2025-02-2110 min read

What Is an Indicator of Attack (IOA)?
A SHA-256 hash stops matching the moment the operator recompiles the payload. The way that payload opens LSASS does not change, because the API it needs has been in Windows since Windows XP. That gap…
2025-02-069 min read

What Is an Indicator of Compromise (IOC)?
A SHA-256 hash identifies exactly one file. Flip one byte in that file and the hash is gone, which is why hash-based blocking loses to a recompile. That single property explains most of what an…
2025-01-2710 min read