Threat Intelligence

What Is an Indicator of Attack (IOA)?

HuntRule Team · · 9 min read

A line of dominoes caught mid-fall on a dark table, one tile suspended in the air, the rest still standing
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: medium

Notice 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: selection

The 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:

  1. Event ID 7045 in the System log, provider Service Control Manager, with ImagePath containing \Windows\Temp\ or \AppData\Local\Temp\ (T1543.003). Security Event ID 4697 carries the same fact in ServiceFileName if the Audit Security System Extension subcategory is enabled.

  2. A process creation within a few seconds where ParentImage ends with \services.exe and Image matches that ImagePath (T1569.002).

  3. 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 installation

Behavioral rules for these techniques are in the catalog under Windows detections, and the credential-access set is at /rules?q=lsass.

Related articles