What Is an Indicator of Attack (IOA)?
HuntRule Team · · 9 min read

On this page
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 is the whole argument for indicators of attack. An IOC is a value you look for. An IOA is a behavior you look for, described in terms of what the attacker is trying to accomplish rather than which binary accomplished it.
IOC and IOA, stated precisely
An IOC names a value: 44d88612fea8a8f36de82e1278abb02f, 185.220.101.34, svchost-update.tmp, a certificate thumbprint, a mutex string. Matching is exact or prefix-based. The lookup is cheap and the answer is binary.
An IOA names an action and its context: a process opening another process with a specific access mask, a document handler creating a script interpreter, a service registering an image path under a user-writable directory. Matching requires fields from the event, and usually more than one event.
Two things people say about this distinction that are wrong. The first is that IOCs are historical and IOAs are real time. A hash blocklist on an EDR fires in real time. The second is that IOAs detect unknown threats while IOCs only detect known ones. An IOA is written from known behavior too. You still had to observe someone dumping LSASS before you wrote a rule for it.
The real difference is durability. An attacker changes a hash by adding a byte. An attacker changes an IOA match by changing how the attack works, which is expensive and sometimes not possible at all.
Where the term came from
IOA is vendor terminology. CrowdStrike has marketed the phrase since roughly 2014 and describes itself as having invented the concept. Take the marketing claim with the usual salt: the underlying split was published three years earlier. The Lockheed Martin kill chain paper (Hutchins, Cloppert and Amin, 2011) already classified indicators as atomic, computed and behavioral, with behavioral indicators defined as combinations of the other two plus a description of adversary activity.
So the idea is older than the label. Use the label anyway, because everyone in a SOC uses it, and arguing about vocabulary does not close alerts.
Credential access without naming the binary
The clearest IOA in Windows telemetry is process access to LSASS. Sysmon Event ID 10 records the source process, the target process, the granted access mask and the call stack. Here is the SigmaHQ rule for it, id 5ef9853e-4d0e-4a70-846f-a9ca37d876da, with the optional vendor filters trimmed:
title: Potential Credential Dumping Activity Via LSASS
id: 5ef9853e-4d0e-4a70-846f-a9ca37d876da
tags:
- attack.credential-access
- attack.t1003.001
logsource:
category: process_access
product: windows
detection:
selection:
TargetImage|endswith: '\lsass.exe'
GrantedAccess|contains:
- '0x1038'
- '0x1438'
- '0x143a'
- '0x1fffff' # Too many false positives
# - '0x01000' # Too many false positives
# - '0x1010' # Too many false positives
# - '0x1400' # Too many false positives
# - '0x1410' # Too many false positives
# - '0x40' # Too many false positives
CallTrace|contains:
- 'dbgcore.dll'
- 'dbghelp.dll'
- 'kernel32.dll'
- 'kernelbase.dll'
- 'ntdll.dll'
condition: selection and not 1 of filter_main_*
falsepositives:
- Unknown
level: mediumNotice what is absent. There is no SourceImage. The rule does not care whether the request came from mimikatz.exe, from a renamed procdump.exe, from taskmgr.exe, or from a beacon running in a hollowed notepad.exe. It cares that something asked the operating system for PROCESS_VM_READ on LSASS.
Also notice the commented-out masks. Five access values that credential dumpers genuinely use were removed because they fired too often on normal endpoint software. That is the IOA tax written directly into the rule.
One honest limitation: the CallTrace clause is close to a no-op. Any user-mode OpenProcess call stack passes through ntdll.dll, so that condition is almost always true. The discriminating work is done by GrantedAccess and by the excluded system accounts. Sysmon also does not log Event ID 10 in a default install, so this rule returns nothing until someone deploys a config that includes lsass.exe as a ProcessAccess target.
Office spawns an interpreter, then the interpreter calls out
Single events here are weak. EXCEL.EXE creating cmd.exe happens with legitimate add-ins. powershell.exe making an outbound HTTPS connection happens constantly on a managed fleet. Neither event alone is worth an alert on most networks.
The pair is different. A macro-enabled document (T1566.001) drops a script, the interpreter runs it (T1059.005), and the script retrieves the next stage over HTTP (T1071.001). Sigma expresses that as a correlation rule over two base rules in one file, separated by ---:
title: Office child interpreter making an outbound connection
status: experimental
correlation:
type: temporal
rules:
- office_spawns_interpreter
- interpreter_outbound_connection
group-by:
- ProcessGuid
timespan: 30s
level: high
---
title: Office application spawns a script interpreter
name: office_spawns_interpreter
logsource:
category: process_creation
product: windows
detection:
selection:
ParentImage|endswith:
- '\winword.exe'
- '\excel.exe'
- '\powerpnt.exe'
- '\outlook.exe'
Image|endswith:
- '\wscript.exe'
- '\cscript.exe'
- '\mshta.exe'
- '\powershell.exe'
condition: selection
---
title: Script interpreter outbound network connection
name: interpreter_outbound_connection
logsource:
category: network_connection
product: windows
detection:
selection:
Image|endswith:
- '\wscript.exe'
- '\cscript.exe'
- '\mshta.exe'
- '\powershell.exe'
Initiated: 'true'
condition: selectionThe join key does the work. Sysmon Event ID 1 sets ProcessGuid to the newly created process, and Event ID 3 sets ProcessGuid to the process making the connection. Grouping on it means the connection has to come from the exact interpreter that Word spawned, not from some unrelated PowerShell session in the same 30 seconds. If your pipeline renames that field, and most field-mapping pipelines do, the group-by has to be renamed with it.
We used type: temporal rather than temporal_ordered on purpose. A process cannot make a network connection before it exists, so ordering adds a constraint that causality already guarantees. The Sigma documentation makes the same point and warns that clock skew between log sources can flip the apparent order of events that are seconds apart. Correlation support is also uneven across backends. Splunk SPL, Elasticsearch ES|QL, Loki, SQL and OpenSearch have it. temporal_ordered is narrower still, so test the conversion before you build a detection on it. If you have not written a plain Sigma rule yet, start at what Sigma rules are before reaching for correlations.
Service created, then executed from a temp path
The third example needs three events and no hashes:
Event ID 7045 in the System log, provider
Service Control Manager, withImagePathcontaining\Windows\Temp\or\AppData\Local\Temp\(T1543.003). Security Event ID 4697 carries the same fact inServiceFileNameif the Audit Security System Extension subcategory is enabled.A process creation within a few seconds where
ParentImageends with\services.exeandImagematches thatImagePath(T1569.002).Optionally a network connection from that new process.
Remote execution tools do exactly this. PsExec writes PSEXESVC.exe, registers it and starts it, which is why so many hands-on-keyboard operators use it and why this sequence lands in incident reports. It is also why software installers and RMM agents trip it. Path is the discriminator, not the behavior: C:\Windows\Temp\ and %LOCALAPPDATA%\Temp\ are user-writable, and a service image belongs there roughly never.
What IOAs cost
Be honest about the bill before you commit to it.
Telemetry. Sysmon Event ID 3 and Event ID 10 are both off by default. Windows Security 4688 without command line auditing enabled gives you a process name and nothing to write a rule against. IOAs assume a level of endpoint instrumentation that many environments do not have.
Authoring effort. A hash IOC takes a copy and paste. The LSASS rule above went through years of revisions and still ships five commented-out access masks.
Noise before tuning. Every IOA in this post fires on legitimate activity in some environment. Budget for a tuning window measured in weeks, with an exclusion list that grows.
Retention and compute. Correlating over a 30-second window means the SIEM holds and joins both event streams. Hash matching does not.
Distribution. You can email a CSV of 400 hashes and the recipient pastes it into a blocklist. You cannot email a behavior. You email a rule, and the rule references field names that depend on the recipient's agent, their normalization schema and their backend. That portability gap is the single strongest practical argument for IOCs, and Sigma exists mostly to narrow it.
When each is the right tool
Use IOCs for known-bad values you want blocked instantly and cheaply: a hash from an advisory, a C2 domain from a threat feed, an IP from a takedown notice. They are precise, fast and trivially shared. They also expire fast.
Use IOAs when the artifact is disposable but the technique is not. Credential access, service-based persistence, document-to-interpreter chains and lateral movement all have a small set of ways they can work, and attackers change binaries far more often than they change methods.
Most detection programs need both, in different lanes. IOCs feed blocklists and retro-hunts. IOAs feed the alerts an analyst actually investigates.
Techniques referenced
Technique | ID |
|---|---|
OS Credential Dumping: LSASS Memory | T1003.001 |
Command and Scripting Interpreter: PowerShell | T1059.001 |
Command and Scripting Interpreter: Visual Basic | T1059.005 |
Application Layer Protocol: Web Protocols | T1071.001 |
Create or Modify System Process: Windows Service | T1543.003 |
System Services: Service Execution | T1569.002 |
Summary
An IOA describes an action and its context, an IOC describes a value. The distinction is not new and the term is vendor-coined, but the property it points at is real: behaviors survive recompilation and hashes do not. Sequence is what turns a noisy single event into a usable IOA, and Sigma correlation rules are the portable way to express that sequence today. The cost is richer telemetry, longer tuning cycles and detections you cannot hand to a peer as a flat list.
Telemetry to collect before writing any of the rules above:
Sysmon EID 1 Process creation (needs ProcessGuid, ParentImage, CommandLine)
Sysmon EID 3 Network connection (off by default, needs Initiated)
Sysmon EID 10 ProcessAccess (off by default, needs lsass.exe as a target)
Security 4688 Process creation with "Include command line" policy enabled
Security 4697 A service was installed (Audit Security System Extension)
System 7045 Service Control Manager service installationBehavioral rules for these techniques are in the catalog under Windows detections, and the credential-access set is at /rules?q=lsass.
Related 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 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

What is an advanced persistent threat (APT)?
In one compromise, Volt Typhoon likely extracted NTDS.dit from three domain controllers over a four-year period. CISA, the NSA and the FBI published that detail in advisory AA24-038A in February…
2025-01-219 min read