Advisories | 1898 & Co.

Threat Hunt Plan: Rockwell Automation Logix Controllers — CIP Denial-of-Service and Induced Controller Fault

Written by The 1898 & Co. Team | September 3, 2026

 

Date: 3 September 2026 | Revision 1.0

Hunt Objective and Scope

This hunt determines whether any adversary has probed, reached, or exploited the Common Industrial Protocol (CIP) message-processing path on Rockwell Automation Logix controllers in a manner consistent with CVE-2026-9637, and whether any controller in the environment has entered a major nonrecoverable fault (MNRF) that was induced rather than operational. CVE-2026-9637 carries a CVSS v3.1 base score of 7.5 and a CVSS v4.0 base score of 8.7, and was disclosed by CISA on 1 September 2026 as advisory ICSA-26-244-03. The defect is an improper restriction of operations within the bounds of a memory buffer (CWE-119) triggered by improper validation of input length during CIP message processing; a single crafted message drives the controller into an MNRF that clears only on a physical power cycle. No workaround exists, and no public exploitation has been reported to CISA at the time of writing, which makes this a pre-exploitation posture hunt rather than an incident response.

The device population in scope is every ControlLogix 5580, CompactLogix 5380, GuardLogix 5580, and Compact GuardLogix 5380 controller at firmware V33 or earlier, V34.011 through V34.014, V35.011 through V35.013, or V36.011 through V36.012. Any controller whose firmware revision cannot be confirmed from an authoritative inventory is treated as in scope until proven otherwise. The network scope is every segment from which a CIP message can reach one of those controllers: Purdue Levels 0 through 3, the Level 3.5 industrial demilitarized zone, every engineering workstation and FactoryTalk server that speaks CIP, every jump host and remote-access path that terminates in the control network, and the organization's internet-facing address space. Windows engineering and operations hosts within the control network are in scope for endpoint telemetry; the controllers themselves produce no endpoint telemetry and are observed only through network, SNMP, historian, and OT-monitoring evidence.

The hunt window is 90 days back from the execution date, extended to 180 days for the external-exposure hypothesis so that continuous exposure spanning the disclosure date can be established. Hypothesis 1 (external attack surface) is executed FIRST and its output scopes the remaining hypotheses: any internet-reachable EtherNet/IP service or Rockwell engineering surface confirmed as organization-owned converts the internal hunt for the systems behind it from a sample into an exhaustive pass. Out of scope: exploitation of Logix controllers by physical means, vulnerabilities in Studio 5000 Logix Designer or FactoryTalk outside their role as a CIP client, and any active scanning of production controllers, which is prohibited for the duration of this hunt because the affected devices fault on malformed input by definition.

Hypotheses and Hunt Procedures

Hypothesis 1: an external actor can reach an internet-facing EtherNet/IP or Rockwell engineering surface belonging to the organization, observable as an exposed service in passive internet-scan indices. Execute FIRST; its output scopes the internal hypotheses.

MITRE ATT&CK: Reconnaissance | T1595 Active Scanning (defender-side: passive discovery of what an actor would enumerate) · Initial Access | T1133 External Remote Services · Initial Access | T1190 Exploit Public-Facing Application · ICS | T0883 Internet Accessible Device · ICS | T0819 Exploit Public-Facing Application — an internet-reachable CIP endpoint removes every network precondition for CVE-2026-9637 and makes the controller directly attackable by an unauthenticated actor.

Collection Queries — passive external indices (STRICTLY passive; never probe target infrastructure):

Shodan — run each anchor as its own query; space-separated filters are AND and combining anchors produces a false zero:

port:44818 "EtherNet/IP"

 

port:2222 "EtherNet/IP"

 

port:44818,2222 net:<your_public_CIDR>

 

port:44818,2222 org:"<Your Org Name>"

 

port:44818,2222 asn:AS<your_ASN>

 

http.html:"Rockwell"

 

http.html:"FactoryTalk"

 

http.html:"Studio 5000"

 

// count-only first pass — does not consume result credits
shodan count 'port:44818 net:<your_public_CIDR>'

 

// full pull with the fields needed for attribution and version triage
shodan search --fields ip_str,port,org,hostnames,product,version 'port:44818,2222 net:<your_public_CIDR>'

 

Censys (CenQL — use the current host.services form; the legacy services.* CSL form silently returns zero rows):

host.services: (port = "44818")

 

host.services: (port = "2222")

 

host.services.software.vendor: "Rockwell Automation"

 

host.services.endpoints.http.body: "FactoryTalk"

 

host.services: (port = "44818") and (host.autonomous_system.asn = <your_ASN> or host.ip: "<your_public_CIDR>")

 

Netlas (tie-breaker only, when Shodan and Censys disagree):

host:<your_public_CIDR> AND port:(44818 OR 2222)

 

http.body:"FactoryTalk"

 

certificate.subject.common_name:"<your_domain>"

 

Cross-reference every exposed service and banner version against the CISA Known Exploited Vulnerabilities catalog at https://www.cisa.gov/known-exploited-vulnerabilities-catalog and against CVE-2026-9637 directly. API credentials are referenced by environment-variable name only (SHODAN_API_KEY, CENSYS_API_SECRET, CENSYS_ORG_ID, NETLAS_API_KEY) and are never inlined; a missing key is non-blocking — skip that engine and record the coverage gap.

Analysis Queries — attribution, triage, and corroboration:

Attribute every hit with at least two independent ownership signals (PTR record, ASN registration, TLS certificate CN or SAN, WHOIS/RDAP registrant, the organization's own public IP and cloud asset inventory) before reporting it. Shared hosting, CDN, and carrier infrastructure break attribution in both directions; an unattributable hit is inconclusive, not negative.

Do not assign an OT-protocol severity tier from a port number alone. TCP/44818 and TCP/2222 are registered to EtherNet/IP, which is what a scan engine's category column reports whether or not the host was observed speaking CIP. Require a banner, service fingerprint, or handshake artifact captured by the index before recording "EtherNet/IP exposed"; until then the finding reads "service on an OT-registered port, protocol unconfirmed".

Apply the honeypot guardrail. OT protocols are the most heavily honeypotted services on the internet and Conpot exists specifically to answer EtherNet/IP and Modbus. Down-weight any hit carrying Shodan's honeypot tag or a Conpot fingerprint and never report it as organizational exposure.

Version-triage each banner against the affected firmware ranges (V33 and earlier, V34.011-V34.014, V35.011-V35.013, V36.011-V36.012) and record the index scan timestamp with every hit. A banner is stale in both directions: an in-range version is a prompt to verify current state from the organization's own inventory, and a fixed-version banner is not evidence of safety if the scan predates the exposure window.

Corroborate in at least two of Shodan, Censys, and Netlas before escalating. Absence from an index is evidence only that the index did not observe the host — never write "not exposed" on the strength of one engine.

Historical pivot: establish whether each exposure spans 1 September 2026, the disclosure date. Continuous exposure across that boundary means the host was presumptively enumerated by the population of actors that reads CISA ICS advisories.

Reconcile every externally observed, organization-attributed host against the authoritative public IP and cloud asset inventory. A host presenting an organization certificate that is absent from the inventory is a shadow-infrastructure finding in its own right, regardless of its firmware state.

Feed every confirmed-owned, in-range instance into Hypotheses 2, 3, and 4 as a priority target and hunt it exhaustively rather than by sampling.

Hypothesis 2: an actor with reachability to the control network has sent malformed or oversized CIP messages to affected Logix controllers, observable as anomalous EtherNet/IP traffic on TCP/UDP 44818 and UDP 2222 in network capture and OT monitoring, correlated with controller major nonrecoverable faults in historian, SNMP, and SCADA alarm records.

MITRE ATT&CK: ICS | T0814 Denial of Service — the direct effect of CVE-2026-9637 exploitation · ICS | T0816 Device Restart/Shutdown — the MNRF halts the controller and requires a power cycle · ICS | T0815 Denial of View and ICS | T0813 Denial of Control — the operator loses both visibility and command of the faulted process · ICS | T0826 Loss of Availability and ICS | T0880 Loss of Safety — the latter where a GuardLogix or Compact GuardLogix safety controller is the target · Enterprise | T1499 Endpoint Denial of Service — the enterprise-side equivalent for the crafted-input mechanism.

Collection Queries:

CrowdStrike Falcon LogScale (CQL) — enumerate every CIP flow initiated by a Falcon-monitored Windows host, which establishes the sanctioned engineering baseline the anomalies are judged against:

#event_simpleName=NetworkConnectIP4
| in(RemotePort, values=["44818","2222"])
| table([@timestamp, aid, ComputerName, LocalAddressIP4, RemoteAddressIP4, RemotePort, Protocol, ContextProcessId], limit=20000)

 

CrowdStrike Falcon LogScale (CQL) — resolve each CIP flow to the process that opened it. NetworkConnectIP4 carries no image name, so the owning process is recovered by joining ContextProcessId back to the ProcessRollup2 TargetProcessId on the same agent:

(#event_simpleName=NetworkConnectIP4 OR #event_simpleName=/ProcessRollup2/)
| case {
#event_simpleName=NetworkConnectIP4 | falconPID := ContextProcessId ;
#event_simpleName=/ProcessRollup2/ | falconPID := TargetProcessId ;
}
| groupBy([aid, falconPID], function=collect([ComputerName, RemoteAddressIP4, RemotePort, ImageFileName, CommandLine, UserName]), limit=100000)
| in(RemotePort, values=["44818","2222"])

 

BPF packet capture — capture CIP traffic at the OT aggregation SPAN or TAP facing the affected controllers. These filters are read-only observation of mirrored traffic; no packet is injected toward a controller:

# all EtherNet/IP explicit and implicit messaging, rolling hourly files, 1 GiB cap each
tcpdump -i <span_iface> -s 0 -G 3600 -C 1024 -w /captures/enip_%Y%m%d_%H%M%S.pcap 'tcp port 44818 or udp port 44818 or udp port 2222'

 

# explicit messaging only, scoped to one controller under investigation
tcpdump -i <span_iface> -s 0 -w /captures/enip_ctrl.pcap 'host <controller_ip> and tcp port 44818'

 

# session establishment only — cheap rate baseline for connection-flood behaviour
tcpdump -i <span_iface> -nn 'tcp port 44818 and tcp[tcpflags] & tcp-syn != 0 and tcp[tcpflags] & tcp-ack = 0'

 

# oversized encapsulation candidates — EtherNet/IP frames materially larger than routine explicit messaging
tcpdump -i <span_iface> -s 0 -w /captures/enip_large.pcap 'tcp port 44818 and greater 900'

 

Datadog Log Search — Windows hosts in the control network that logged CIP client activity or a driver/service fault around a controller event:

source:windows "44818"
// time range: last 90 days

 

source:windows (@evt.id:7031 OR @evt.id:7034) "RSLinx"
// time range: last 90 days

 

Datadog Log Search — firewall and OT gateway logs forwarded from the Level 3.5 boundary, where the CIP conduit is enforced:

source:(firewall OR syslog) ("44818" OR "2222") -@network.client.ip:10.* -@network.client.ip:172.16.* -@network.client.ip:192.168.*
// time range: last 90 days

 

Datadog CloudTrail — cloud-hosted historian, remote-access broker, or site-to-site VPN changes that could have opened a path into the control network during the window:

source:cloudtrail @evt.name:(AuthorizeSecurityGroupIngress OR CreateRoute OR ModifyVpcPeeringConnectionOptions OR CreateVpnConnection)
// Analytics: Table view, group by @network.client.ip, @userIdentity.arn; time range: last 90 days

 

Datadog Live Process Monitoring — Infrastructure > Processes, not a log search. Identifies CIP-capable interpreters and utilities running on control-network hosts:

command:python user:<engineering_service_account>

 

command:rslinx

 

// Fallback where Live Process Monitoring is not enabled on OT-locked hosts:
source:windows @evt.id:4688 ("python" OR "RSLinx" OR "Studio5000")
// time range: last 90 days

 

Windows Event IDs to collect from every engineering workstation, FactoryTalk server, and control-network jump host:

  • 4624 — successful logon; establishes who was on the CIP-capable host at the time of a controller fault
  • 4625 — failed logon; precursor to credential abuse against the engineering population
  • 4688 — process creation with command line; the primary record of CIP tooling execution
  • 4697 — service installed; unexpected service on an engineering workstation
  • 5156 and 5157 — Windows Filtering Platform permitted and blocked connections, the host-side record of CIP flows
  • 7045 — service installed (System log); duplicates 4697 where advanced audit policy is incomplete
  • 4104 — PowerShell script block logging; captures socket-level CIP crafting in script form
  • 1102 — audit log cleared; anti-forensic signal around the event window
Get-WinEvent -FilterHashtable @{LogName='Security'; Id=4688; StartTime=(Get-Date).AddDays(-90)} |
Where-Object { $_.Message -match 'python|RSLinx|Studio5000|RSLogix|nmap|plcscan' } |
Select-Object TimeCreated, MachineName, @{n='User';e={$_.Properties[1].Value}}, @{n='Process';e={$_.Properties[5].Value}}, @{n='CommandLine';e={$_.Properties[8].Value}} |
Export-Csv -NoTypeInformation C:\hunt\cip_process_creation.csv

 

Get-WinEvent -FilterHashtable @{LogName='Security'; Id=5156; StartTime=(Get-Date).AddDays(-90)} |
Where-Object { $_.Message -match '44818|2222' } |
Select-Object TimeCreated, MachineName, Message |
Export-Csv -NoTypeInformation C:\hunt\cip_wfp_connections.csv

 

OT Data Collection: Claroty xDome — scope the controller population, then pull the directional CIP flow record. Devices > All Devices > Advanced Filters: Category = OT AND Purdue Level IN (Level 1, Level 2) AND Manufacturer = Rockwell Automation, then Export CSV to seed the hunt population. Network > Communication > Communication Analysis: Side A left unscoped, Communication: Protocol = CIP and Port = 44818, Side B: Purdue Level = 1 and Purdue Level = 2, Time Frame Past Month, run once per month of the window. Alerts & Threats > OT Activity: export Mode Change, Program Download, and Firmware Update events for the same population. Use the API for pulls above the 100,000-row export ceiling: POST /api/v1/devices/, POST /api/v1/alerts/, POST /api/v1/ot_activity_events/, and POST /api/v1/device/communication-map/ per asset_id.

OT Data Collection: Claroty CTD — on-prem CTD retains continuous full PCAP where xDome does not; where CTD is deployed, request the retrospective packet window covering each controller fault via the CTD /v1/events/<id>/pcap surface rather than relying on the sensor-local buffer. This is the only path that recovers the actual bytes of a CIP message sent weeks ago.

OT Data Collection: Dragos Platform — Assets: scope to Rockwell controllers at Purdue Levels 1 and 2 with a Now-priority vulnerability, and carry that list forward as the hunt population. Communications Hub: filter source-zone = Level 3 or Level 4 AND dest-zone = Level 1 or Level 2 AND protocol = EtherNet/IP or CIP over the full window, then pivot each session to its asset record and event PCAP. Query the Industrial Protocols Query Focused Dataset for anomalous CIP service codes and unauthenticated writes. Export the event PCAP from a firing notification, or Export PCAP for window from the Communications detail, and pull it from SiteStore for offline analysis. API: SiteStore Assets, Notifications, and Vulnerabilities collections.

OT Data Collection: Nozomi Guardian — query the links table, which is where traffic lives; the nodes table returns endpoints, not conversations. Note that head without an explicit N silently returns 10 rows, and a field-to-field comparison requires the $ prefix or it compares against a string literal and returns a false zero:

links | where protocol == "enip" | join nodes to ip | join nodes from ip
| select from_ip to_ip protocol joined_node_to_ip.label->to_label joined_node_from_ip.label->from_label
| head 5000

 

links | where protocol == "enip" and from_zone != to_zone | head 5000

 

nodes | where vendor == "Rockwell Automation" | select ip label type last_activity_time | head 2000

 

alerts | where time >= days_ago(90) | where mitre_attack ~= "T0814" | sort record_created_at asc | head 500

 

OT Data Collection: Armis Centrix — the analyst sets the time window in the UI time-picker; no timeFrame clause appears in the query body. Add the tenant's own OT boundary literal to the endpoint scoping after enumerating it from the console Sites and Boundaries view — do not substitute a shipped default such as Corporate, which parses cleanly and returns a false zero at most tenants:

in:ipConnections
serverPort:44818,2222

 

in:ipConnections
serverPort:44818,2222
endpointA:(networkLocation:"External")

 

in:devices
brand:"Rockwell Automation"
category:"Manufacturing Equipment"

 

OT Data Collection: Tenable OT — Inventory > All Assets, filter AssetType IN (Plc, Controller, BackplaneModule) and vendor Rockwell Automation, then export. Events: pull PLC Stop, PLC Start, and Intrusion Detection policy violations across the window; these surface under Events, not under Risks > Findings. Programmatic pulls go through the GraphQL endpoint at /graphql — there is no REST /api/v1/ query surface for OT Security — or through pyTenable for repeatable scripts. Note that Eng and OtWorkstation are distinct AssetType values from Workstation; scoping an engineering-host query to Workstation misses exactly the hosts that matter.

OT Data Collection: Forescout eyeInspect — use the Command Center Asset Inventory filtered by Purdue level and vendor for the controller population, and the Alerts view filtered by MITRE ATT&CK for ICS technique and protocol for CIP-decoded events. eyeInspect has no analyst-facing query language, so free-text hunting requires forwarding CEF or syslog to the SIEM and querying there; the Forescout OT Network Security Monitoring App for Splunk is the canonical path. Pivot from an alert to the underlying flow and packet capture where sensor PCAP is enabled.

SNMP polling — poll the switch port facing each affected controller and the controller's own SNMP agent where one is exposed. Provision SNMPv3 credentials through snmp.conf or createUser rather than inline, since inline passphrases are visible in the process table, and treat any v1/v2c community-string access to an OT asset as a finding in its own right:

snmpwalk -v2c -c <community> <switch_ip> IF-MIB::ifTable

 

snmpget -v2c -c <community> <switch_ip> IF-MIB::ifHCInOctets.<ifIndex> IF-MIB::ifHCOutOctets.<ifIndex> IF-MIB::ifInErrors.<ifIndex> IF-MIB::ifOutErrors.<ifIndex>

 

snmpwalk -v3 -l authPriv -u <user> -a SHA-256 -x AES-256 <controller_ip> system

 

snmpwalk -v3 -l authPriv -u <user> -a SHA-256 -x AES-256 <controller_ip> IF-MIB::ifTable

 

Poll the counters at 60-second intervals through the hunt window and diff successive values; the 32-bit ifInOctets and ifOutOctets counters wrap on high-speed links, so use the 64-bit ifHCInOctets (1.3.6.1.2.1.31.1.1.1.6) and ifHCOutOctets (.10) for volumetric baselining. Flag any sysUpTime reset on a controller, which indicates the unexpected restart an MNRF recovery produces.

Collect SNMP trap logs from the trap receiver for the window and filter for traps sourced from the controller address ranges. Flag coldStart (1.3.6.1.6.3.1.1.5.1) and warmStart (1.3.6.1.6.3.1.1.5.2) traps indicating device restarts, linkDown and linkUp (1.3.6.1.6.3.1.1.5.3 and .4) traps indicating port flaps around a fault, and authenticationFailure (1.3.6.1.6.3.1.1.5.5) traps indicating unauthorized access attempts on OT network interfaces.

Historian and SCADA alarm correlation — export the controller fault, communication loss, and I/O module fault alarms for every in-scope controller across the window from the process historian, and export the corresponding operator action log. For each fault, record the timestamp to the second, the recovery method (power cycle versus automatic), the operator who cleared it, and whether a maintenance work order exists. A fault with no work order and no preceding maintenance activity is the candidate set for this hunt.

YARA file-system scan — scan engineering workstations, FactoryTalk servers, and control-network jump hosts for CIP exploitation tooling and staged payloads:

yara -r /opt/hunt/rules/logix_cip_hunt.yar C:\Users\ >> /opt/hunt/hits_users.txt

 

yara -r /opt/hunt/rules/logix_cip_hunt.yar C:\ProgramData\ >> /opt/hunt/hits_programdata.txt

 

yara -r /opt/hunt/rules/logix_cip_hunt.yar C:\Windows\Temp\ >> /opt/hunt/hits_temp.txt

 

Analysis Queries:

CrowdStrike Falcon LogScale (CQL) — rate detection. A CIP client that opens more than a hundred connections to one controller in a five-minute window is behaving nothing like Studio 5000 or FactoryTalk and is the shape a repeated fault-and-retry attack produces:

#event_simpleName=NetworkConnectIP4
| in(RemotePort, values=["44818","2222"])
| bucket(span=5m, limit=500, field=[aid, RemoteAddressIP4], function=count(as=CipConnections))
| CipConnections > 100
| sort(CipConnections, order=desc, limit=200)

 

Wireshark display filters — apply against the captured PCAP; the tshark equivalent is given for each so the analysis is scriptable across a large capture set:

enip

 

cip

 

enip.command == 0x0065 || enip.command == 0x0066

 

enip.command == 0x0063

 

enip.length > 504

 

cip.service & 0x7f == 0x4c || cip.service & 0x7f == 0x4d

 

tcp.port == 44818 && tcp.analysis.retransmission

 

tcp.port == 44818 && tcp.flags.reset == 1

 

tshark -r /captures/enip_20260901_120000.pcap -Y 'enip' -T fields -e frame.time -e ip.src -e ip.dst -e enip.command -e enip.length -e enip.session > enip_summary.tsv

 

tshark -r /captures/enip_20260901_120000.pcap -Y 'enip.length > 504' -T fields -e frame.time -e ip.src -e ip.dst -e enip.command -e enip.length

 

tshark -r /captures/enip_20260901_120000.pcap -q -z conv,tcp | head -50

 

tshark -r /captures/enip_20260901_120000.pcap -Y 'cip' -T fields -e ip.src -e ip.dst -e cip.service -e cip.class | sort | uniq -c | sort -rn

 

The encapsulation length field is the analytic centre of this hypothesis. CVE-2026-9637 arises from improper validation of input length during CIP message processing, so an EtherNet/IP frame whose declared encapsulation length is inconsistent with its actual payload, or which materially exceeds the length range the sanctioned engineering tools produce, is the highest-value artifact available. Baseline the length distribution from a known-good capture window before treating any threshold as anomalous.

Datadog Log Analytics — correlate CIP boundary traffic against the controller fault timeline:

source:(firewall OR syslog) ("44818" OR "2222")
// Analytics: Timeseries view, group by @network.client.ip; time range: last 90 days

 

source:windows "44818"
// Analytics: Table view, group by host, @evt.id; time range: last 90 days

 

Datadog Audit Trail — establish whether any Datadog-side monitor, log pipeline, or integration covering the OT boundary was disabled or modified during the window, which would create the visibility gap an actor needs:

source:datadog @evt.name:Monitor @asset.type:monitor
// Analytics: Table view, group by @usr.email, @action; time range: last 90 days

 

source:datadog @evt.name:"Access Management"
// Analytics: Table view, group by @usr.email, @action; time range: last 90 days

 

Datadog Monitor definition:

Type: Log Alert
Query: source:(firewall OR syslog) ("44818" OR "2222") -@network.client.ip:10.* -@network.client.ip:172.16.* -@network.client.ip:192.168.*
Evaluation window: last 5 minutes
Alert condition: count > 0
Message: "ALERT: EtherNet/IP CIP traffic observed from a non-RFC1918 source toward the control network — CVE-2026-9637 exposure, immediate investigation required @ot-soc-pagerduty"
Prerequisites: Level 3.5 boundary firewall syslog and OT gateway logs forwarded to Datadog; RFC-1918 exclusions tuned to the site address plan
Create via: Monitors > New Monitor > Log Alert OR POST /api/v1/monitors

 

Windows Event Log PowerShell analysis — hunt the connection record and the fault window together:

$faults = Import-Csv C:\hunt\controller_faults.csv
foreach ($f in $faults) {
$start = [datetime]$f.FaultTime.AddMinutes(-15)
$end = [datetime]$f.FaultTime.AddMinutes(5)
Get-WinEvent -FilterHashtable @{LogName='Security'; Id=5156; StartTime=$start; EndTime=$end} |
Where-Object { $_.Message -match '44818|2222' } |
Select-Object TimeCreated, MachineName, Message |
Export-Csv -Append -NoTypeInformation C:\hunt\cip_around_faults.csv
}

 

Get-WinEvent -FilterHashtable @{LogName='Microsoft-Windows-PowerShell/Operational'; Id=4104; StartTime=(Get-Date).AddDays(-90)} |
Where-Object { $_.Message -match 'Sockets|TcpClient|44818|EtherNet|CIP' } |
Select-Object TimeCreated, MachineName, Message |
Export-Csv -NoTypeInformation C:\hunt\ps_cip_scriptblocks.csv

 

OT protocol and baseline-deviation analysis — for each in-scope controller, compare the observed CIP peer set, service-code distribution, and session rate against the 90-day baseline. Sanctioned engineering traffic is a small, stable peer set using a narrow set of service codes at low rates; the analytic signal is a new peer, a service code the baseline never carried, or a rate step change. Correlate every deviation against the SNMP interface counters for the same interval and against the historian fault record. A controller fault with a preceding CIP anomaly from an unbaselined peer is escalated immediately.

YARA memory scan — scan running processes on engineering workstations for in-memory CIP crafting artifacts. Classic YARA 4.5 takes the PID as a positional target; there is no -p flag for process scanning, and YARA-X does not support process memory at all:

yara /opt/hunt/rules/logix_cip_hunt.yar 4812

 

Get-Process | Where-Object { $_.ProcessName -match 'python|powershell|rslinx|studio5000' } |
ForEach-Object { & yara C:\hunt\rules\logix_cip_hunt.yar $_.Id } >> C:\hunt\yara_mem_hits.txt

 

CrowdStrike Custom IOAs can carry the process-creation and command-line halves of these rules as standing detection content, and Falcon Real Time Response can execute the YARA binary against a remote host through the put and run command tier, which is the practical route on OT-adjacent Windows hosts that cannot be reached interactively.

Hypothesis 3: an actor has compromised an engineering workstation or FactoryTalk server, obtained the credentials and CIP reachability that host holds, and used it as the launch point for controller-directed activity, observable as unsanctioned CIP-capable tooling, anomalous interactive logons, and credential-access artifacts in endpoint telemetry.

MITRE ATT&CK: Enterprise | T1021.001 Remote Services: Remote Desktop Protocol — the common path onto an engineering workstation from the enterprise network · Enterprise | T1003 OS Credential Dumping — engineering hosts hold the accounts that reach the control network · ICS | T0859 Valid Accounts · ICS | T0866 Exploitation of Remote Services · ICS | T0867 Lateral Tool Transfer — CIP tooling staged onto the engineering host · ICS | T0818 Engineering Workstation Compromise — the enabling step that converts enterprise access into controller reachability.

Collection Queries:

CrowdStrike Falcon LogScale (CQL) — sanctioned engineering tooling execution, which establishes the baseline and identifies the host population:

#event_simpleName=/ProcessRollup2/
| FileName = /^(Studio5000\.exe|RSLogix5000\.exe|RSLogix5K\.exe|RSLinx\.exe|RSLinxNG\.exe|FTLinx\.exe|LogixDesigner\.exe)$/i
| table([@timestamp, aid, ComputerName, UserName, FileName, ImageFileName, CommandLine, ParentBaseFileName, SHA256HashData], limit=20000)

 

CrowdStrike Falcon LogScale (CQL) — unsanctioned CIP-capable scripting and scanning tooling on any monitored host:

#event_simpleName=/ProcessRollup2/
| CommandLine = /(pycomm3|cpppo|enip|ethernet[_\-]?ip|cipscan|plcscan|scapy)/i
| table([@timestamp, aid, ComputerName, UserName, FileName, CommandLine, ParentBaseFileName, SHA256HashData], limit=20000)

 

CrowdStrike Falcon LogScale (CQL) — CIP tooling written to disk. There is no generic FileWritten event in Falcon; the family regex catches every per-file-type write event:

#event_simpleName=/FileWritten$/
| TargetFileName = /.*\\(pycomm3|cpppo|enip|plcscan|cipscan).*/i
| table([@timestamp, aid, ComputerName, TargetFileName, SHA256HashData, ContextProcessId], limit=20000)

 

CrowdStrike Falcon LogScale (CQL) — network and interactive logons to the engineering host population:

#event_simpleName=UserLogon
| in(LogonType, values=["3","10"])
| ComputerName = /(ews|eng|hmi|scada|ftview)/i
| table([@timestamp, aid, ComputerName, UserName, LogonType, LogonDomain, RemoteAddressIP4], limit=20000)

 

Datadog Log Search — remote-access sessions terminating on the engineering population:

source:windows @evt.id:4624 @evt.LogonType:(3 OR 10)
// time range: last 90 days

 

source:kubernetes @kubernetes.namespace_name:"ot-gateway" message:"session"
// time range: last 90 days

 

Datadog CloudTrail — cloud identity and remote-access broker activity that could grant a path to the engineering population:

source:cloudtrail @evt.name:(AssumeRole OR GetSessionToken OR CreateAccessKey) -@network.client.ip:10.*
// Analytics: Table view, group by @userIdentity.arn, @network.client.ip; time range: last 90 days

 

Datadog Live Process Monitoring — Infrastructure > Processes:

command:python user:<engineering_service_account>

 

command:powershell user:<engineering_service_account>

 

// Fallback log search where Live Process Monitoring is not deployed on OT-locked hosts:
source:windows @evt.id:4688 ("python.exe" OR "powershell.exe" OR "cmd.exe")
// time range: last 90 days

 

Windows Event IDs to collect from the engineering population: 4624 (successful logon, with logon type), 4625 (failed logon), 4648 (explicit credential use), 4672 (special privileges assigned), 4688 (process creation with command line), 4697 and 7045 (service installed), 4104 (PowerShell script block), 4720 and 4732 (account created, added to privileged group), 1102 (audit log cleared).

Get-WinEvent -FilterHashtable @{LogName='Security'; Id=4624; StartTime=(Get-Date).AddDays(-90)} |
Where-Object { $_.Properties[8].Value -in @(3,10) } |
Select-Object TimeCreated, MachineName, @{n='User';e={$_.Properties[5].Value}}, @{n='LogonType';e={$_.Properties[8].Value}}, @{n='SourceIP';e={$_.Properties[18].Value}} |
Export-Csv -NoTypeInformation C:\hunt\ews_logons.csv

 

Get-WinEvent -FilterHashtable @{LogName='Security'; Id=4648; StartTime=(Get-Date).AddDays(-90)} |
Select-Object TimeCreated, MachineName, Message |
Export-Csv -NoTypeInformation C:\hunt\explicit_cred_use.csv

 

OT Data Collection: Claroty xDome — Devices > All Devices > Advanced Filters: Device Type = Engineering Workstation, Export CSV; then for each host open the device profile Communications tab to confirm its peer set and protocols, and the Insights tab for insecure-protocol and end-of-life findings. Alerts & Threats > All Alerts: filter Alert Category = Threat Alert with the engineering population as Device Filters.

OT Data Collection: Dragos Platform — Communications Hub: source-zone = Level 4 AND dest-zone = Level 2 or Level 3 AND protocol IN [RDP, SSH, VNC, SMB] across the window, and pivot each cross-Purdue session to its asset record and event PCAP. Where a session is confirmed, open a Case, attach the event PCAP and the SSH-sessions Query Focused Dataset output, and follow the attached playbook.

OT Data Collection: Armis Centrix — enumerate the tenant's own alert types from in:alerts with no type clause before writing any alert-scoped query; Armis alert types are policy-derived and therefore tenant-specific, and a literal lifted from documentation is rejected as an invalid value rather than returning an empty set:

in:ipConnections
serverPort:44818,2222
endpointA:(device:(category:"Computers"))

 

OT Data Collection: Tenable OT — Inventory > All Assets filtered to AssetType IN (Eng, OtWorkstation) for the engineering population; Events for Project Upload and Project Download policy violations across the window. Exclude TenableSensor, TenableIcp, and TenableEm from any asset count reported to stakeholders, or the inventory includes the tooling doing the watching.

YARA file-system scan of the engineering population:

yara -r /opt/hunt/rules/logix_cip_hunt.yar C:\Users\ >> /opt/hunt/hits_ews_users.txt

 

yara -r /opt/hunt/rules/logix_cip_hunt.yar "C:\Program Files (x86)\Rockwell Software\" >> /opt/hunt/hits_rockwell.txt

 

Analysis Queries:

CrowdStrike Falcon LogScale (CQL) — rarity analysis on children of the engineering tooling. A process that Studio 5000 or RSLinx has spawned only once or twice across the estate is the analytic definition of anomalous on a population of near-identical engineering builds:

#event_simpleName=/ProcessRollup2/
| ParentBaseFileName = /^(Studio5000\.exe|RSLinx\.exe|RSLinxNG\.exe|FTLinx\.exe)$/i
| groupBy([FileName, ParentBaseFileName], function=count(as=ExecCount), limit=100000)
| sort(ExecCount, order=asc, limit=50)

 

CrowdStrike Falcon LogScale (CQL) — DNS resolution of CIP tooling and OT reconnaissance infrastructure from monitored hosts:

#event_simpleName=DnsRequest
| DomainName = /(pycomm3|cpppo|plcscan|shodan|scadastrangelove)/i
| table([@timestamp, aid, ComputerName, DomainName, ContextProcessId], limit=20000)

 

Datadog Log Analytics — logon-source distribution across the engineering population, which surfaces the host or subnet that should not be reaching it:

source:windows @evt.id:4624 @evt.LogonType:(3 OR 10)
// Analytics: Table view, group by host, @evt.SourceIP; time range: last 90 days

 

Datadog Audit Trail — account and access changes touching the engineering or OT service accounts during the window:

source:datadog @evt.name:"Organization Management"
// Analytics: Table view, group by @usr.email, @action; time range: last 90 days

 

Datadog Monitor definition:

Type: Log Alert
Query: source:windows @evt.id:4688 ("pycomm3" OR "cpppo" OR "plcscan" OR "cipscan")
Evaluation window: last 5 minutes
Alert condition: count > 0
Message: "ALERT: CIP-capable scanning or scripting tooling executed on a control-network host — possible staging against CVE-2026-9637, immediate investigation required @ot-soc-pagerduty"
Prerequisites: Windows Security log with command-line process auditing (4688 with command line) forwarded from every engineering workstation and FactoryTalk server
Create via: Monitors > New Monitor > Log Alert OR POST /api/v1/monitors

 

Windows Event Log PowerShell analysis — scheduled-task and service persistence review on the engineering population:

Get-WinEvent -FilterHashtable @{LogName='Microsoft-Windows-TaskScheduler/Operational'; Id=106; StartTime=(Get-Date).AddDays(-90)} |
Select-Object TimeCreated, MachineName, Message |
Export-Csv -NoTypeInformation C:\hunt\ews_scheduled_tasks.csv

 

Get-WinEvent -FilterHashtable @{LogName='System'; Id=7045; StartTime=(Get-Date).AddDays(-90)} |
Select-Object TimeCreated, MachineName, Message |
Export-Csv -NoTypeInformation C:\hunt\ews_services.csv

 

YARA memory scan for credential-access tooling on the engineering population, since the credentials that reach the control network are held there:

Get-Process | Where-Object { $_.ProcessName -match 'lsass|python|powershell|rundll32' } |
ForEach-Object { & yara C:\hunt\rules\logix_cip_hunt.yar $_.Id } >> C:\hunt\yara_cred_hits.txt

 

Process-memory scanning of LSASS requires SeDebugPrivilege on the scanning account. Where the engineering host cannot be reached interactively, Falcon Real Time Response can put the YARA binary and rule file and run the scan remotely under the same privilege constraint.

Hypothesis 4: an actor has enumerated the control network for Logix controllers ahead of exploitation, observable as EtherNet/IP List Identity requests or CIP connection attempts fanning out across many controller addresses from a single source.

MITRE ATT&CK: ICS | T0846 Remote System Discovery — enumeration of controllers by protocol response · ICS | T0888 Remote System Information Discovery — the List Identity response returns vendor, product code, and firmware revision, which is precisely the data needed to select in-range targets · ICS | T0842 Network Sniffing · Enterprise | T1046 Network Service Discovery.

An EtherNet/IP List Identity request (encapsulation command 0x0063) is the single most efficient way for an actor to build the affected-controller list, because the response carries the firmware major and minor revision directly. A sweep of List Identity across an OT segment is the highest-fidelity precursor signal available for this CVE, and it is cheap for an actor and loud for a defender.

Collection Queries:

CrowdStrike Falcon LogScale (CQL) — fan-out detection. A monitored host reaching more than ten distinct addresses on the CIP ports is enumerating, not engineering:

#event_simpleName=NetworkConnectIP4
| in(RemotePort, values=["44818","2222"])
| groupBy([aid, ComputerName, LocalAddressIP4], function=[count(as=ConnCount), count(field=RemoteAddressIP4, distinct=true, as=DistinctTargets)], limit=100000)
| DistinctTargets > 10
| sort(DistinctTargets, order=desc, limit=200)

 

BPF packet capture — capture the enumeration traffic specifically. List Identity is commonly sent to UDP/44818, including as a broadcast:

tcpdump -i <span_iface> -s 0 -w /captures/enip_listidentity.pcap 'udp port 44818'

 

tcpdump -i <span_iface> -s 0 -w /captures/enip_broadcast.pcap 'udp port 44818 and (ip broadcast or ip multicast)'

 

tcpdump -i <span_iface> -nn -c 5000 'tcp port 44818 and tcp[tcpflags] & tcp-syn != 0 and tcp[tcpflags] & tcp-ack = 0'

 

Datadog Log Search — boundary firewall record of the sweep:

source:(firewall OR syslog) ("44818" OR "2222") ("deny" OR "drop" OR "reject")
// time range: last 90 days

 

Windows Event IDs to collect: 5156 and 5157 from every control-network Windows host, which record permitted and blocked outbound connections and therefore capture a sweep launched from a compromised host even where no packet capture existed at the time.

Get-WinEvent -FilterHashtable @{LogName='Security'; Id=5157; StartTime=(Get-Date).AddDays(-90)} |
Where-Object { $_.Message -match '44818|2222' } |
Select-Object TimeCreated, MachineName, Message |
Export-Csv -NoTypeInformation C:\hunt\cip_blocked_connections.csv

 

OT Data Collection: Claroty xDome — Alerts & Threats > All Alerts filtered to the scanning and reconnaissance alert categories over the window; Network > Communication > Communication Analysis with Side A pinned to a single suspect address and Side B unscoped, then read the distinct peer count. Note that a one-side-pinned export cannot be pivoted into a per-site matrix, so pivot on SIDE A SITE NAME first and confirm it carries more than one distinct value before drawing any per-site conclusion.

OT Data Collection: Dragos Platform — triage Notifications filtered to ATT&CK for ICS Discovery techniques across the window, and escalate any carrying an Activity Group tag. Query the Industrial Protocols Query Focused Dataset for List Identity and Get Attributes All request volume by source.

OT Data Collection: Armis Centrix — run the pre-flight decisionData exposure probe before relying on the port-scan fields, since decisionData provisioning varies by tenant:

in:activity
type:"Port Scan Detected"
decisionData:(targetPorts:44818 scanType:"Many Targets")

 

OT Data Collection: Nozomi Guardian — enumerate scanning behaviour from the links table and confirm against the alerts table:

links | where protocol == "enip" | group_by from_ip | sort count desc | head 100

 

alerts | where time >= days_ago(90) | where mitre_attack ~= "T0846" | head 500

 

OT Data Collection: Tenable OT — Events filtered to Intrusion Detection and Network Scan policy violations; the Network Map grouped by Purdue level will show which levels the scanning source reached.

OT Data Collection: Forescout eyeInspect — the Alerts view carries protocol-decoded reconnaissance events; forward the CEF stream to the SIEM for source-address fan-out analysis, which eyeInspect cannot express natively.

Analysis Queries:

Wireshark display filters — isolate the enumeration and read the firmware revisions the responses disclosed:

enip.command == 0x0063

 

enip.command == 0x0063 && udp

 

cip.service == 0x01

 

enip.command == 0x0004

 

tshark -r /captures/enip_listidentity.pcap -Y 'enip.command == 0x0063' -T fields -e frame.time -e ip.src -e ip.dst | sort | uniq -c | sort -rn

 

tshark -r /captures/enip_listidentity.pcap -Y 'enip' -T fields -e ip.src -e ip.dst -e enip.command | awk '{print $1}' | sort | uniq -c | sort -rn | head -20

 

CrowdStrike Falcon LogScale (CQL) — timeline correlation between the enumeration and any subsequent single-target burst, which is the sequence that precedes exploitation:

#event_simpleName=NetworkConnectIP4
| in(RemotePort, values=["44818","2222"])
| bucket(span=1h, limit=500, field=[aid, ComputerName], function=count(field=RemoteAddressIP4, distinct=true, as=DistinctTargetsPerHour))
| DistinctTargetsPerHour > 5
| sort(DistinctTargetsPerHour, order=desc, limit=200)

 

Datadog Log Analytics — sweep-source ranking from the boundary logs:

source:(firewall OR syslog) ("44818" OR "2222")
// Analytics: Top List view, group by @network.client.ip; sort descending for the widest sources; time range: last 90 days

 

Datadog Monitor definition:

Type: Log Alert
Query: source:(firewall OR syslog) ("44818" OR "2222") ("deny" OR "drop" OR "reject")
Evaluation window: last 15 minutes
Alert condition: count > 25
Message: "ALERT: repeated denied EtherNet/IP connection attempts at the OT boundary — possible controller enumeration ahead of CVE-2026-9637 exploitation @ot-soc-pagerduty"
Prerequisites: Level 3.5 boundary firewall deny logging enabled and forwarded to Datadog; threshold tuned against the site's normal denied-flow rate
Create via: Monitors > New Monitor > Log Alert OR POST /api/v1/monitors

 

OT protocol analysis — for every List Identity response captured, extract the vendor ID, device type, product code, and firmware major and minor revision, and match the revision against the affected ranges. The set of controllers whose firmware was disclosed to an unbaselined source during the window is the priority remediation list regardless of whether exploitation followed, because the actor now holds the target list.

Threat Actor Profile

Nation-state ICS-capable actors are the most consequential threat to this vulnerability, and the least likely to use it first. Groups with a demonstrated Rockwell and EtherNet/IP capability — the cluster behind PIPEDREAM/INCONTROLLER being the reference case, with its purpose-built CODESYS and OPC UA modules and its Schneider and Omron controller tooling — treat controller enumeration and firmware fingerprinting as routine pre-positioning. Their access path is a multi-stage one: enterprise compromise, credential theft, lateral movement to an engineering workstation, and only then controller-directed traffic from a host that legitimately speaks CIP. Their sophistication is high, their operational security is deliberate, and their use of a denial-of-service primitive is more likely to be a component of a timed disruptive operation than an opportunistic act. For this actor class, the List Identity enumeration in Hypothesis 4 and the engineering-workstation compromise in Hypothesis 3 are the detectable stages; the fault itself would be the last and least recoverable signal.

Hacktivist and ideologically motivated actors are the most likely to attempt this vulnerability soonest, and the least discriminating about where. The pattern established across 2023 through 2026 — unsophisticated groups locating internet-exposed control devices through Shodan and similar indices and manipulating them for publicity — maps directly onto CVE-2026-9637, which needs no credentials, no foothold, and no tooling beyond a crafted packet. Their sophistication is low but their targeting is broad and index-driven, which is precisely why Hypothesis 1 runs first: for this actor class, internet exposure is not one risk factor among several, it is the entire access path. A water utility or small manufacturer with an exposed EtherNet/IP port is a target of opportunity within days of a public advisory.

Ransomware operators and financially motivated intrusion sets are relevant through a different mechanism. They rarely attack controllers directly, because a faulted PLC generates no revenue, but the availability impact of CVE-2026-9637 gives them a coercion lever that pairs with an IT-side encryption event. The realistic pattern is an enterprise ransomware intrusion whose operators discover CIP reachability from a compromised engineering workstation and use the threat of controller disruption as negotiating pressure. Their access path is commodity — phishing, exposed remote access, an unpatched edge appliance — and their sophistication is moderate but their tooling is well resourced.

Opportunistic and insider actors round out the profile. An opportunistic actor scanning broadly for OT-registered ports will find an exposed controller without having sought it, and may trigger the fault through an unmodified scanner rather than deliberate exploitation, which is a real operational risk given that the vulnerability triggers on malformed input. An insider — a contractor, an integrator, or a disgruntled engineer — already holds the CIP reachability every other actor must work to obtain, and their activity is distinguishable only by timing, authorization, and change-record correlation rather than by network position. Hypothesis 3's logon and process telemetry, correlated against maintenance work orders, is the only leg of this hunt that addresses the insider case.

Data Sources Required

Network: full packet capture or SPAN/TAP-fed capture at the OT aggregation points and the Level 3.5 boundary, covering TCP/UDP 44818 and UDP 2222; NetFlow or IPFIX from the industrial core and distribution switches; firewall permit and deny logs from the Level 3.5 boundary and every conduit into the control network; VPN and remote-access broker session logs; DNS query logs from the control network resolvers.

Endpoint: CrowdStrike Falcon telemetry from every Windows engineering workstation, FactoryTalk server, historian collector, and control-network jump host — specifically ProcessRollup2 and SyntheticProcessRollup2, NetworkConnectIP4, DnsRequest, the FileWritten event family, UserLogon and UserLogonFailed2, ScheduledTaskRegistered, and ServiceStarted; Windows Security, System, PowerShell/Operational, and TaskScheduler/Operational event logs with command-line process auditing and script block logging enabled; Sysmon where deployed.

OT and ICS: process historian tag history and alarm records for every in-scope controller, including controller fault, communication loss, and I/O module fault alarms; SCADA and HMI alarm and operator action logs; controller firmware inventory from the asset management system or from Studio 5000 project files; SNMP interface counters and trap logs from the switches facing the controllers and from the controllers themselves where an agent is exposed; OT monitoring platform exports from every deployed platform — Claroty xDome or CTD, Dragos Platform, Nozomi Guardian or Vantage, Armis Centrix, Tenable OT, and Forescout eyeInspect — covering asset inventory, directional flow records, protocol-decoded alerts, and OT activity events.

Vendor and device: Rockwell Automation controller major fault records and fault codes retrieved through Studio 5000 or FactoryTalk; controller connection tables and session counts; managed switch port statistics and MAC address tables for the controller-facing ports; change management records and maintenance work orders for the entire window, which are the only source that distinguishes a sanctioned firmware or program change from an unsanctioned one.

External attack surface: the passive internet-scan indices queried read-only — Shodan, Censys, and Netlas — accessed with credentials referenced by environment-variable name only; the CISA Known Exploited Vulnerabilities catalog; and, critically, the organization's authoritative public IP address inventory and cloud asset inventory. Without the last of these, an externally observed host cannot be attributed to the organization and the exposure determination cannot be made at all; an incomplete inventory bounds the sweep exactly where shadow infrastructure accumulates.

Detection Signatures

SIGMA rule 1 — unsanctioned CIP-capable tooling executed on a control-network host. This is the process-creation half of Hypothesis 3 and the highest-value standing detection this hunt produces, because CIP tooling has no legitimate reason to run outside a small, known engineering population.

title: CIP EtherNet-IP Tooling Execution on Control Network Host
id: 7f3c9a21-4b6d-4e18-9c02-8ad571fe3b40
status: experimental
description: Detects execution of Python CIP libraries, PLC scanners, or packet-crafting tooling capable of generating EtherNet/IP CIP messages, which precedes exploitation of CVE-2026-9637 against Rockwell Logix controllers.
references:
- https://www.cisa.gov/news-events/ics-advisories/icsa-26-244-03
- https://nvd.nist.gov/vuln/detail/CVE-2026-9637
author: 1898 & Co.
date: 2026/09/03
logsource:
category: process_creation
product: windows
detection:
selection_tooling:
CommandLine|contains:
- 'pycomm3'
- 'cpppo'
- 'plcscan'
- 'cipscan'
- 'enip_'
- 'ethernetip'
selection_scanner:
Image|endswith:
- '\nmap.exe'
- '\python.exe'
CommandLine|contains:
- '44818'
- 'enip-info'
- 'enip-enumerate'
condition: selection_tooling or selection_scanner
falsepositives:
- Sanctioned OT asset discovery tooling operated by the OT security team during an approved assessment window
- Vendor commissioning activity performed by a Rockwell integrator with a change record
level: high
tags:
- attack.discovery
- attack.t1046
- attack.impact
- attack.t1499

 

SIGMA rule 2 — outbound CIP connection from a host outside the engineering population. This is the network-connection logsource and complements rule 1 by catching a compiled or renamed tool that rule 1's command-line strings would miss.

title: EtherNet-IP CIP Connection From Non-Engineering Host
id: b41e8d05-2f7a-4c93-a6d1-05e39cb27a68
status: experimental
description: Detects an outbound connection to EtherNet/IP CIP ports 44818 or 2222 from a process that is not a sanctioned Rockwell engineering or communications component, indicating unsanctioned controller-directed traffic.
references:
- https://www.cisa.gov/news-events/ics-advisories/icsa-26-244-03
author: 1898 & Co.
date: 2026/09/03
logsource:
category: network_connection
product: windows
detection:
selection:
DestinationPort:
- 44818
- 2222
Initiated: 'true'
filter_sanctioned:
Image|endswith:
- '\RSLinx.exe'
- '\RSLinxNG.exe'
- '\FTLinx.exe'
- '\Studio5000.exe'
- '\LogixDesigner.exe'
- '\RSLogix5000.exe'
condition: selection and not filter_sanctioned
falsepositives:
- Third-party OPC or historian collectors that speak CIP directly and are absent from the sanctioned image list
- Asset discovery appliances performing scheduled OT inventory
level: high
tags:
- attack.discovery
- attack.t1046
- attack.lateral_movement

 

SIGMA rule 3 — PowerShell constructing raw sockets toward the CIP ports. This uses the PowerShell script block logsource (EID 4104) and catches the living-off-the-land path that leaves no distinctive binary on disk for rules 1 and 2 or for the file-based YARA rule.

title: PowerShell Raw Socket Activity Toward EtherNet-IP CIP Ports
id: 3d92c7e4-8a15-4b60-bd47-1c60fa5e29d3
status: experimental
description: Detects PowerShell script blocks that construct TCP or UDP sockets targeting EtherNet/IP CIP ports, a living-off-the-land path to crafting the malformed CIP message that triggers CVE-2026-9637.
references:
- https://nvd.nist.gov/vuln/detail/CVE-2026-9637
author: 1898 & Co.
date: 2026/09/03
logsource:
product: windows
category: ps_script
detection:
selection_socket:
ScriptBlockText|contains:
- 'System.Net.Sockets.TcpClient'
- 'System.Net.Sockets.UdpClient'
- 'System.Net.Sockets.Socket'
selection_port:
ScriptBlockText|contains:
- '44818'
- '0x63'
- 'ListIdentity'
condition: selection_socket and selection_port
falsepositives:
- Engineering automation scripts maintained by the controls team that poll controller identity for inventory purposes
level: high
tags:
- attack.execution
- attack.t1059.001
- attack.discovery
- attack.t1046

 

SIGMA rule 4 — CIP exploitation tooling written to disk on a control-network host. The file-event logsource catches the staging step that precedes execution and gives the hunt a second chance at an actor who cleans up after running.

title: CIP Exploitation Tooling Written to Disk on Control Network Host
id: 9c5b0f38-6e2d-41a7-8b93-47da2ce016f5
status: experimental
description: Detects files associated with EtherNet/IP CIP libraries, PLC scanners, or crafted-packet scripts being written to a control-network Windows host, indicating staging ahead of controller-directed activity.
references:
- https://www.cisa.gov/news-events/ics-advisories/icsa-26-244-03
author: 1898 & Co.
date: 2026/09/03
logsource:
category: file_event
product: windows
detection:
selection:
TargetFilename|contains:
- 'pycomm3'
- 'cpppo'
- 'plcscan'
- 'cipscan'
- 'enip'
filter_installer:
TargetFilename|contains:
- '\Rockwell Software\'
- '\FactoryTalk\'
condition: selection and not filter_installer
falsepositives:
- Python package installation performed by the controls engineering team into a sanctioned virtual environment
level: medium
tags:
- attack.lateral_movement
- attack.t1570

 

Snort/Suricata rule 1 — EtherNet/IP List Identity sweep. The rule fires only after a source has issued the request to a threshold number of distinct destinations within a window, which is what separates enumeration from the single identity query a legitimate tool issues at connection time. Local SIDs start at 1,000,000 per the Suricata local range.

alert udp $EXTERNAL_NET any -> $OT_NET 44818 (msg:"OT ENIP List Identity sweep - possible Logix controller enumeration ahead of CVE-2026-9637"; flow:to_server; content:"|63 00|"; offset:0; depth:2; threshold:type threshold, track by_src, count 10, seconds 60; classtype:attempted-recon; reference:cve,2026-9637; reference:url,www.cisa.gov/news-events/ics-advisories/icsa-26-244-03; metadata:service enip; sid:1000001; rev:1;)

 

Snort/Suricata rule 2 — anomalous EtherNet/IP encapsulation length on the explicit messaging port. This is the closest network-observable proxy for the input-length validation defect itself, and it is written as a detection_filter so a single malformed frame from a misbehaving legitimate device does not page the SOC while a sustained attempt does.

alert tcp any any -> $OT_NET 44818 (msg:"OT ENIP oversized encapsulation length toward Logix controller - possible CVE-2026-9637 exploitation attempt"; flow:to_server,established; dsize:>700; content:"|6f 00|"; offset:0; depth:2; detection_filter:track by_src, count 3, seconds 60; classtype:attempted-dos; reference:cve,2026-9637; metadata:service enip; sid:1000002; rev:1;)

 

Snort/Suricata rule 3 — CIP traffic from a source outside the sanctioned engineering address set. This is a segmentation-assurance rule rather than an exploit signature; it converts the Level 3.5 conduit policy into a detection so that a policy failure is visible rather than silent.

alert tcp !$ENG_NET any -> $OT_NET 44818 (msg:"OT CIP explicit messaging from non-engineering source - conduit policy violation"; flow:to_server,established; threshold:type limit, track by_src, count 1, seconds 300; classtype:policy-violation; reference:cve,2026-9637; metadata:service enip; sid:1000003; rev:1;)

 

YARA rule 1 targets the on-disk staging artifacts of CIP exploitation tooling. It is structured around three independent branches — Python CIP library imports, EtherNet/IP encapsulation command constants written as source-level literals, and known PLC scanner strings — because an actor may stage any one of them without the others, and requiring all three would produce a rule that only matches a complete toolkit. The condition demands at least two matches from any branch rather than a single string, which suppresses the common false positive of a documentation file or a package manifest that merely names a library.

rule CIP_Exploitation_Tooling_Artifacts
{
meta:
description = "CIP/EtherNet-IP exploitation and enumeration tooling staged on a control-network host; supports the CVE-2026-9637 hunt"
author = "1898 & Co."
date = "2026-09-03"
reference = "https://www.cisa.gov/news-events/ics-advisories/icsa-26-244-03"
strings:
$lib1 = "pycomm3" ascii wide nocase // Python CIP client library import or package path
$lib2 = "from cpppo" ascii nocase // cpppo EtherNet/IP library import form
$lib3 = "cpppo.server.enip" ascii nocase // cpppo ENIP server/client module path
$lib4 = "LogixDriver" ascii nocase // pycomm3 controller driver class
$enc1 = "ListIdentity" ascii wide nocase // ENIP encapsulation command 0x0063 by name
$enc2 = "RegisterSession" ascii wide nocase // ENIP encapsulation command 0x0065 by name
$enc3 = "SendRRData" ascii wide nocase // ENIP encapsulation command 0x006f by name
$enc4 = { 63 00 00 00 00 00 00 00 } // ListIdentity header bytes as a literal in a crafted-packet script
$scan1 = "plcscan" ascii wide nocase // known PLC enumeration tool
$scan2 = "enip-enumerate" ascii nocase // nmap ENIP NSE script name
$scan3 = "enip-info" ascii nocase // nmap ENIP NSE script name
$port = "44818" ascii wide // CIP explicit messaging port as a literal
condition:
2 of ($lib*, $enc*, $scan*) or
($port and 1 of ($lib*, $scan*))
}

 

YARA rule 2 targets the same activity in process memory rather than on disk, which is the only place it appears when the tooling is executed from an interpreter, a memory-resident loader, or a script that is deleted after running. The condition is deliberately looser than rule 1's because a live process holds far fewer complete artifacts than a staged file, and it anchors on the co-occurrence of an encapsulation constant with a socket or port artifact so that a process merely holding the string "44818" in a log buffer does not match.

rule ENIP_CIP_Crafting_In_Memory
{
meta:
description = "In-memory artifacts of EtherNet/IP CIP message crafting on a control-network host; run against live process IDs"
author = "1898 & Co."
date = "2026-09-03"
reference = "https://nvd.nist.gov/vuln/detail/CVE-2026-9637"
strings:
$cmd1 = { 6f 00 } // ENIP SendRRData encapsulation command little-endian
$cmd2 = { 65 00 } // ENIP RegisterSession encapsulation command little-endian
$cmd3 = { 63 00 } // ENIP ListIdentity encapsulation command little-endian
$s1 = "ListIdentity" ascii wide nocase // command name held by a crafting library
$s2 = "RegisterSession" ascii wide nocase // session establishment routine name
$s3 = "UnconnectedSend" ascii wide nocase // CIP unconnected messaging service name
$s4 = "pycomm3" ascii wide nocase // interpreter-resident library name
$s5 = "cpppo" ascii wide nocase // interpreter-resident library name
$sock1 = "socket.SOCK_STREAM" ascii nocase // raw socket construction in an interpreted script
$sock2 = "System.Net.Sockets" ascii wide // .NET socket construction from PowerShell
$port = "44818" ascii wide // CIP explicit messaging port
condition:
(1 of ($s*) and 1 of ($sock*, $port)) or
(2 of ($cmd*) and 1 of ($sock*, $port))
}

 

YARA rule 3 is the standing credential-access rule, included because Hypothesis 3 involves lateral movement to an engineering workstation and credential access on it. Its five branches cover the tools that actually appear on Windows hosts in industrial environments, and the fifth is a catch-all pairing a memory-read API with an LSASS reference so that a novel or renamed tool is still caught by behaviour rather than by name. Scanning LSASS memory requires SeDebugPrivilege on the scanning account; where the engineering host cannot be reached interactively, Falcon Real Time Response can put the YARA binary and rule file and run the scan remotely.

rule Credential_Dump_Tool_Memory_Artifacts
{
meta:
description = "Credential dumping tool artifacts in process memory on engineering workstations reachable to the control network"
author = "1898 & Co."
date = "2026-09-03"
reference = "https://attack.mitre.org/techniques/T1003/"
strings:
$mim1 = "sekurlsa::logonpasswords" ascii wide nocase // mimikatz credential extraction command
$mim2 = "lsadump::sam" ascii wide nocase // mimikatz SAM dump command
$mim3 = "privilege::debug" ascii wide nocase // mimikatz privilege escalation command
$mim4 = "mimikatz" ascii wide nocase // tool name in memory
$mim5 = { 6d 69 6d 69 6b 61 74 7a } // "mimikatz" as literal hex, survives simple renaming
$wce1 = "wce.exe" ascii wide nocase // Windows Credential Editor binary name
$gsec = "gsecdump" ascii wide nocase // gsecdump tool name
$com1 = "MiniDump" ascii wide nocase // comsvcs.dll MiniDump export
$com2 = "comsvcs" ascii wide nocase // comsvcs.dll LOLBIN reference
$api1 = "NtReadVirtualMemory" ascii wide // memory-read API used by dumpers
$api2 = "ReadProcessMemory" ascii wide // memory-read API used by dumpers
$lsass = "lsass.exe" ascii wide nocase // the target process
condition:
any of ($mim*) or
($wce1 and $lsass) or
$gsec or
($com1 and $com2 and $lsass) or
(1 of ($api*) and $lsass and 1 of ($mim*, $wce1, $gsec, $com2))
}

 

All three rules are distributed as a single file, rules/logix_cip_hunt.yar, which is the path referenced by every YARA invocation in Section 2.

Indicators of Compromise

Network indicators. Any EtherNet/IP or CIP traffic on TCP/UDP 44818 or UDP 2222 whose source address is outside the sanctioned engineering address set is an indicator by construction, regardless of content, because the conduit policy at the Level 3.5 boundary should make it impossible. Within sanctioned traffic, the indicators are an EtherNet/IP encapsulation length field inconsistent with the actual frame payload or materially outside the baseline length distribution; a List Identity request (encapsulation command 0x0063) issued to more than a handful of distinct controller addresses by one source in a short window; a connection rate to a single controller exceeding the baseline for the sanctioned engineering tools by an order of magnitude; TCP resets or retransmission storms on port 44818 immediately preceding a controller fault; and any CIP session originating from a Guest, unmanaged, or unclassified network segment.

Host indicators. Execution on any control-network Windows host of a Python interpreter importing pycomm3 or cpppo, of plcscan or a comparable PLC enumeration tool, of nmap with the EtherNet/IP NSE scripts, or of a PowerShell script block constructing a raw socket toward port 44818. Files matching the CIP tooling YARA rule written outside the Rockwell Software or FactoryTalk installation trees. A network or interactive logon to an engineering workstation from a source address outside the engineering VLAN or the sanctioned jump-host set. Credential-access artifacts in the memory of any process on an engineering workstation. A scheduled task or service installed on an engineering workstation during the window with no corresponding change record. Audit log clearing (Event ID 1102) on any control-network host.

OT and operational indicators. A controller entering a major nonrecoverable fault with no preceding maintenance activity, no work order, and no corresponding process upset that would explain it — this is the terminal indicator for this vulnerability and the one an operations team will see first. An SNMP sysUpTime reset on a controller outside a planned outage. A coldStart or warmStart trap from a controller with no change record. A cluster of controller faults across multiple devices in a short window, which no single equipment failure explains. A controller reporting a new CIP peer that the 90-day baseline never carried. A firmware revision disclosed to an unbaselined source through a List Identity response. Any GuardLogix or Compact GuardLogix safety controller fault, which is escalated on discovery irrespective of cause because the safety consequence does not wait for attribution.

External exposure indicators. An organization-attributed host answering on TCP/UDP 44818 or UDP 2222 in any passive index, corroborated in at least two engines and confirmed as organization-owned by at least two independent ownership signals. A Rockwell, FactoryTalk, or Studio 5000 web surface reachable from the internet. An organization-owned certificate presented by a host that is absent from the authoritative public IP inventory, which is a shadow-infrastructure finding regardless of what service it runs. Continuous exposure of any of the above spanning 1 September 2026, which means the host was presumptively enumerated following the advisory's publication.

False Positive Baseline

Sanctioned engineering activity is the dominant false positive and the reason the baseline must be built before any of the anomaly thresholds are read. Studio 5000 Logix Designer, RSLogix 5000, RSLinx Classic, RSLinx Enterprise, FactoryTalk Linx, and FactoryTalk View all speak CIP to controllers continuously and legitimately, and a firmware upgrade campaign or a commissioning window produces exactly the traffic volume and controller-restart pattern this hunt treats as suspicious. Suppress by correlating against the change management record and the maintenance calendar, not by allowlisting the process names, since an actor on the engineering workstation runs those same processes.

OT asset discovery and vulnerability management tooling generates List Identity sweeps and CIP connection fan-out by design. Claroty, Dragos, Nozomi, Armis, Tenable OT, and Forescout all perform some form of active or semi-active enumeration depending on configuration, and Tenable OT's active queries in particular are built to interrogate controllers directly. Enumerate the collector and sensor addresses for every deployed platform and record them as known sources before reading any fan-out result, and confirm with the platform owner which active-query features are enabled — a scan attributed to an unknown source is frequently the organization's own tooling on an address nobody documented.

Third-party OPC servers, historian collectors, MES and SCADA gateways, and reporting systems frequently speak CIP directly to controllers under a service account and from an address that does not belong to the engineering VLAN. These are legitimate and long-lived, and they will trip the non-engineering-source rules in Section 5. Enumerate them per site, record the address and the controller set each one reaches, and disposition them in the baseline rather than re-adjudicating them at each iteration.

Controller faults with an operational cause are common and will contaminate the fault correlation. Power quality events, I/O module failures, backplane faults, watchdog timeouts caused by scan-time overruns, and program logic faults all produce major faults that look identical to an induced one from outside the controller. The discriminator is the presence or absence of a preceding CIP anomaly from an unbaselined peer within the same window, not the fault itself; a fault with a clean network record and a plausible equipment cause is dispositioned as operational.

Network scanners, monitoring probes, and vulnerability assessment tooling operated by the IT organization routinely touch OT-registered ports without any OT intent. An enterprise vulnerability scanner whose scope was widened by an inaccurate asset list will sweep 44818 across an OT range and produce a textbook Hypothesis 4 signal. Confirm the scan source against the IT scanning schedule and scope before escalating, and treat the finding as a segmentation defect in its own right — the scanner should not have had the reachability, whatever its intent.

Passive-index misattribution is the false positive specific to Hypothesis 1 and the most consequential one to get wrong. Shared hosting, CDN edge nodes, and carrier infrastructure will present hostnames or certificates in the organization's namespace on hardware the organization does not control, and a genuinely owned cloud asset will present provider-owned reverse DNS and ASN that hide ownership entirely. Require at least two independent ownership signals before reporting any hit as organizational exposure, treat an unattributable hit as inconclusive rather than negative, and apply the honeypot guardrail — an OT protocol answering on the open internet is as likely to be a Conpot instance as a real controller, and reporting a honeypot as a client's exposed PLC is the most avoidable failure this hunt can produce.

Escalation Criteria

1. Any organization-attributed host confirmed in at least two passive indices as answering on TCP/UDP 44818 or UDP 2222, whether or not a firmware version is readable, is escalated to incident response and to the network team for immediate exposure removal within the same business day.

2. Any organization-attributed internet-facing exposure of a Rockwell, FactoryTalk, or Studio 5000 surface whose observed exposure window spans 1 September 2026 is escalated as presumptively enumerated, and the controllers reachable behind it are hunted exhaustively rather than by sampling.

3. Any externally observed host presenting an organization-owned certificate or hostname that is absent from the authoritative public IP or cloud asset inventory is escalated as a shadow-infrastructure finding requiring ownership resolution, independent of its patch state.

4. Any controller major nonrecoverable fault during the window with no corresponding maintenance work order, change record, or process upset that explains it is escalated to incident response immediately, and the controller is preserved in its faulted state for evidence capture where the process safely allows it.

5. Any GuardLogix or Compact GuardLogix safety controller fault during the window is escalated on discovery regardless of apparent cause, and the functional safety owner is engaged in parallel with the security investigation.

6. Any CIP traffic on 44818 or 2222 observed from a source outside the sanctioned engineering address set, from an external address, or from a Guest, unmanaged, or unclassified segment is escalated as both a security finding and a segmentation control failure.

7. Any EtherNet/IP List Identity fan-out to more than ten distinct controller addresses from a single source that cannot be attributed to a documented OT monitoring collector or an approved assessment is escalated as controller enumeration ahead of exploitation.

8. Any EtherNet/IP frame captured with an encapsulation length field inconsistent with its actual payload, or materially outside the established baseline length distribution, is escalated immediately and the capture preserved, as this is the closest available observation of the vulnerability's trigger condition.

9. Any hit on the YARA rule CIP_Exploitation_Tooling_Artifacts against any control-network host filesystem is escalated to incident response, the host is isolated pending triage, and the staged file is acquired for analysis before any remediation.

10. Any hit on the YARA rule ENIP_CIP_Crafting_In_Memory against a live process on an engineering workstation, FactoryTalk server, or control-network jump host is escalated immediately, the process is captured with a memory image before termination, and the host is treated as compromised until proven otherwise.

11. Any hit on the YARA rule Credential_Dump_Tool_Memory_Artifacts against any process on a host with CIP reachability is escalated to incident response as a credential-access event, and every account that has authenticated to that host is treated as compromised and rotated.

12. Any execution of CIP-capable tooling on a control-network host that cannot be tied to a named engineer and an approved change record within two hours of discovery is escalated regardless of how benign the tooling appears.

13. Any interactive or network logon to an engineering workstation from outside the engineering VLAN or the sanctioned jump-host set is escalated as unauthorized access to a CIP-capable host.

14. Any evidence of audit log clearing, monitor disablement, or log-forwarding interruption on a control-network host or at the OT boundary during the window is escalated as anti-forensic activity and expands the hunt window to cover the full period of lost visibility.

15. Any cluster of two or more controller faults across distinct devices within a four-hour window is escalated to incident response even where each individual fault has a plausible operational explanation.

Hunt Completion Criteria and Reporting

The hunt is complete when all four hypotheses have been executed and dispositioned. Hypothesis 1 is complete when the organization's full public IP range set and cloud asset inventory have been swept in at least two passive indices, every hit has been attributed with at least two independent ownership signals or explicitly recorded as inconclusive, every attributed hit has been version-triaged against the affected firmware ranges with the index scan timestamp recorded, and the historical pivot across 1 September 2026 has been performed for each. Hypothesis 2 is complete when every in-scope controller has been covered by network capture or OT platform flow records across the window, every controller fault in the window has been correlated against the CIP traffic record and dispositioned as operational or suspicious, and the SNMP and historian records have been reconciled against the network evidence. Hypothesis 3 is complete when every engineering workstation, FactoryTalk server, and control-network jump host has been covered by the endpoint queries and the YARA file-system and memory scans, and every logon from outside the engineering population has been dispositioned. Hypothesis 4 is complete when the full window has been searched for CIP fan-out from every available source — endpoint, boundary firewall, OT platform, and packet capture — and every fan-out event has been attributed to a documented collector, an approved assessment, or escalated.

A hypothesis is dispositioned Negative only where the query executed successfully against a populated data source across the full window. Where a data source was absent, a sensor did not cover a segment, a platform returned zero from a scoping clause that could not be validated, or a passive index could not sweep a range, the disposition is Non-Conclusive with the missing input named explicitly — never Negative. This distinction is load-bearing for this vulnerability in particular, because a zero from an unvalidated query and a zero from a genuinely clean environment are indistinguishable in every one of these consoles, and the operational decision that follows them is different.

The hunt report must contain: the controller inventory with firmware revision and affected-or-not determination for every in-scope device, including the count that could not be confirmed; the external attack surface result stated as engines queried, ranges swept, timestamps, and per-hit provenance, with coverage limitations named where anchors were incomplete; the disposition of every controller fault in the window with its supporting evidence; the per-hypothesis disposition with the data sources that carried it; every escalation raised and its outcome; the detection content produced, with a statement of which rules were deployed as standing detections and which require a data source that is not currently forwarded; the false-positive dispositions recorded for reuse in the next iteration; and a named remediation status per controller — patched, scheduled with a date, or accepted with a documented and dated mitigation plan, which is the form a NERC CIP-007-6 R2 auditor expects.

Two recommendations are standing outputs of this hunt regardless of its findings. First, the passive external-exposure sweep should be established as a recurring control rather than a one-time hunt activity, because exposure is created by change and a clean result today constrains nothing about next quarter. Second, the CIP baseline built during Hypothesis 2 — the sanctioned peer set, service-code distribution, and session rate per controller — should be retained and maintained as the reference against which the next OT advisory is hunted, since building it is the most expensive part of this work and it is reusable across every future controller-directed threat.

Advisory IoC Reference

IOC Type IOC
CVE CVE-2026-9637 | CVSS v3.1 7.5 / CVSS v4.0 8.7 | Rockwell Automation ControlLogix 5580, CompactLogix 5380, GuardLogix 5580, Compact GuardLogix 5380 — V33 and earlier, V34.011-V34.014, V35.011-V35.013, V36.011-V36.012 | Improper validation of input length during CIP message processing (CWE-119) lets an unauthenticated network attacker drive the controller into a major nonrecoverable fault requiring a physical power cycle; fixed in V34.015, V35.014, V36.013, V37.011; no workaround; no known public exploitation reported to CISA as of 1 September 2026.
Threat Actor None attributed in source material — CISA reports no known public exploitation specifically targeting this vulnerability; monitor https://www.cisa.gov/known-exploited-vulnerabilities-catalog for KEV addition
Malware None published in source material — no malware family, implant, or tool is associated with CVE-2026-9637 at time of writing
Network IOC None published in source material — no IP addresses, domains, or C2 infrastructure have been released; monitor https://www.cisa.gov/news-events/ics-advisories/icsa-26-244-03 for advisory updates
File IOC None published in source material — no file hashes or filenames have been released; monitor https://www.cisa.gov/news-events/cybersecurity-advisories for follow-on technical advisories
Behavioral EtherNet/IP or CIP traffic on TCP/UDP 44818 or UDP 2222 from a source outside the sanctioned engineering address set
Behavioral EtherNet/IP encapsulation length field inconsistent with actual frame payload, or materially outside the baseline length distribution, on TCP 44818
Behavioral EtherNet/IP List Identity request (encapsulation command 0x0063) issued to more than ten distinct controller addresses by one source within 60 seconds
Behavioral CIP connection rate to a single controller exceeding 100 connections in a five-minute window from one source
Behavioral Controller major nonrecoverable fault with no corresponding maintenance work order, change record, or explanatory process upset
Behavioral SNMP sysUpTime reset, or coldStart (1.3.6.1.6.3.1.1.5.1) / warmStart (1.3.6.1.6.3.1.1.5.2) trap, from a Logix controller outside a planned outage
Behavioral Two or more controller faults across distinct devices within a four-hour window with no common equipment cause
Behavioral Python interpreter importing pycomm3 or cpppo, or execution of plcscan / cipscan / nmap enip-info / enip-enumerate, on a control-network Windows host
Behavioral PowerShell script block constructing a raw TCP or UDP socket referencing port 44818 or the ListIdentity command
Behavioral Outbound connection to port 44818 or 2222 from a process other than RSLinx, RSLinxNG, FTLinx, Studio5000, LogixDesigner, or RSLogix5000
Behavioral CIP tooling files written outside the Rockwell Software or FactoryTalk installation trees on a control-network host
Behavioral Network or interactive logon (Windows Event ID 4624, logon type 3 or 10) to an engineering workstation from outside the engineering VLAN or sanctioned jump-host set
Behavioral Controller reporting a CIP peer absent from the 90-day communications baseline
Behavioral Organization-attributed host answering on TCP/UDP 44818 or UDP 2222 in two or more passive internet-scan indices, with exposure spanning 1 September 2026
Behavioral Audit log clearing (Windows Event ID 1102), monitor disablement, or log-forwarding interruption on a control-network host or at the OT boundary during the hunt window