Skip to content

Instantly share code, notes, and snippets.

@ARISTODE
Created November 4, 2025 05:14
Show Gist options
  • Select an option

  • Save ARISTODE/28c416a871aae14316a79502b0a6cea9 to your computer and use it in GitHub Desktop.

Select an option

Save ARISTODE/28c416a871aae14316a79502b0a6cea9 to your computer and use it in GitHub Desktop.

• Investigation Log

  • Connected to IDA session, captured module hashes, enumerated exports (DllEntryPoint, Crash) to frame analysis scope.
  • Decompiled Crash → LaunchConfiguredIec104Sessions:0x100014e0, observed config parsing call and thread fan-out via CreateThread (0x10001547), then traced worker entry StartAddress to identify IEC‑104 workflow.
  • Analyzed ParseIec104ConfigFile:0x10001610; confirmed _wfopen (0x10001674) and _fgets usage, mapped keywords target_ip, target_port, sequence, stop_comm_service, command_type, operation, shift, range, uselog at refs 0x100017B0–0x10002004 to per-session structure fields.
  • Inspected RunIec104SessionWorker:0x10002FE0; documented service-kill logic (OpenProcess 0x1000303D / TerminateProcess 0x10003046), IEC-104 connect (Iec104Connect 0x10003079), handshake (SendStartupSequence 0x1000309D), sequence dispatch (range 0x1000315D, shift 0x100031AE) and command emission (IssueSingleCommand calls at 0x1000331A/0x1000335E/0x100034E6/0x10003507).
  • Reverse engineered transport helpers: Iec104Connect (WSAStartup 0x100023E9, socket 0x10002499, connect 0x100024EB), TransmitApdu (send 0x10002642), ReceiveApdu (recv 0x10002730), ProcessIncomingApdus (response parsing, SendSupervisoryFrame 0x100029F2).
  • Mapped support routines (APCI/ASDU encoders, logging, defaults) and applied descriptive renames to every touched function for traceability.

Function Mapping Table

Original Name | New Name | Address | Brief Description Crash | LaunchConfiguredIec104Sessions | 0x100014e0 | Entry export: parse config, spawn worker threads, wait on handles. StartAddress | Iec104ClientThread | 0x100015e0 | Thread stub: announce IEC-104 target, hand off to worker. sub_10001610 | ParseIec104ConfigFile | 0x10001610 | Reads tokenised config, populates 66 kB session records/vectors. sub_10002FE0 | RunIec104SessionWorker | 0x10002fe0 | Core loop: kill optional service, connect IEC-104, execute sequence. sub_100023C0 | Iec104Connect | 0x100023c0 | Resolve host, open TCP socket, apply 15 s timeout, return handle. sub_10002560 | TransmitApdu | 0x10002560 | Build APDU bytes, manage send counters, call send, log failures. sub_100026D0 | ReceiveApdu | 0x100026d0 | Repeated recv, accumulate into session buffer, set state flags. sub_10002830 | ProcessIncomingApdus | 0x10002830 | Parse inbound frames, trigger logging, schedule supervisory/U-frames. sub_10002B40 | SendSupervisoryFrame | 0x10002b40 | Emit S-frame handshake, expect response via ReceiveApdu. sub_10002C30 | SendControlUFrame | 0x10002c30 | Send U-frame control (STARTDT/STOPDT/TESTFR) for connectivity. sub_10002D30 | IssueSingleCommand | 0x10002d30 | Craft IEC type 45 single commands using config qualifiers. sub_10002EB0 | FindProcessIdByName | 0x10002eb0 | Snapshot processes, case-insensitive match, return PID. sub_10002F80 | AppendSessionLog | 0x10002f80 | Optional file logging with rollover/new-file modes. sub_10003660 | LogApduDetails | 0x10003660 | Console formatter for IEC traffic; decodes cause/type IDs. sub_10001230 | BuildApduBuffer | 0x10001230 | Serialize APCI/ASDU headers into outbound buffer. sub_100012B0 | ParseApduBuffer | 0x100012b0 | Validate inbound APDU, forward to ASDU parser. sub_10001180 | AllocateApduContext | 0x10001180 | Allocate APCI/ASDU helper objects with initial counters. sub_10001060 | EncodeApciHeader | 0x10001060 | Populate APCI control fields for I/S/U frames. sub_100010F0 | DecodeApciHeader | 0x100010f0 | Extract APCI control values from raw bytes. sub_10001330 | ParseAsdu | 0x10001330 | Decode IEC ASDU metadata & payload pointer bookkeeping. sub_100013C0 | SerializeAsdu | 0x100013c0 | Assemble ASDU fields back into wire format. sub_10001490 | ConsolePrintf | 0x10001490 | Variadic formatter to stdout or redirected file handle. sub_10004E20 | InitializeSessionDefaults | 0x10004e20 | Seed session with defaults (log path, D2MultiCommService.exe, ports). sub_10002130 | CopySessionRecord | 0x10002130 | Deep-copy 66 kB session structure, transfer vector ownership. sub_10004830 | ReleaseSessionVectors | 0x10004830 | Free all vector-backed buffers in session array. sub_10003A30 | DescribeWinsockError | 0x10003a30 | Map Winsock error codes to printable text. sub_10003AC0 | DescribeCauseOfTransmission | 0x10003ac0 | Return human-readable IEC cause of transmission string. sub_10003B80 | DescribeIecTypeId | 0x10003b80 | Resolve IEC type IDs to mnemonic strings.

Behavioral Analysis

  • Config-Driven IEC-104 Orchestration
    • LaunchConfiguredIec104Sessions:0x100014f9 loads the operator-supplied path, parses session definitions, and spawns one worker per 66 kB record via CreateThread (0x10001547) before joining with WaitForMultipleObjects (0x100015b9).
    • ParseIec104ConfigFile consumes keyword/value pairs (target_ip 0x100017B0, target_port 0x10001804, sequence 0x10002004, uselog 0x10001AA5, socket_timeout 0x10001BAE, range 0x10001BF3, shift 0x10001F74) to populate IPs, ports, ASDU IDs, timing windows, operation sequences, and logging flags within each session record.
    • Default initialisation (InitializeSessionDefaults:0x10004E20) primes every session with high-value defaults, including watchdog timers (dwMilliseconds = 1000 ms at 0x10021894) and a target service ("D2MultiCommService.exe" at 0x10004ED3), highlighting intended ICS victim context.
  • IEC-104 Transport & Framing
    • Workers establish network reachability through Iec104Connect (WSAStartup 0x100023E9, socket 0x10002499, connect 0x100024EB) and impose 15 s receive timeouts by writing dword_10021890 (15000) via setsockopt 0x10002543.
    • APDUs are built with AllocateApduContext → EncodeApciHeader/SerializeAsdu and dispatched by TransmitApdu (send 0x10002642) while inbound traffic is collected by ReceiveApdu (recv loop 0x10002730) and decoded in ProcessIncomingApdus before logging through LogApduDetails (color-coded console output plus optional file append).
    • Control hygiene is maintained with scheduled SendSupervisoryFrame and SendControlUFrame invocations (refs 0x10002993, 0x10003652) to emit STARTDT/STOPDT/TESTFR frames aligned with IEC-104 expectations.
  • Programmable Command Sequences
    • RunIec104SessionWorker compares the session mode string (strcmp(...,"sequence") at 0x100030E6) then iterates config-derived vectors (command_type, operation, range, shift accesses around 0x10003119–0x10003241) to drive stateful operations.
    • Command execution funnels into IssueSingleCommand (calls at 0x1000331A/0x1000335E/0x100034E6/0x10003507), which hardcodes IEC type 45 (*(_BYTE *)=45 at 0x10002DB0) and programs qualifier bits (a4+48/50 usage) before transmitting and awaiting confirmation.
    • Combined with ProcessIncomingApdus increments and range bounds, the toolkit can repeatedly actuate field devices, step through queued operations, and react to acknowledgements, enabling remote manipulation of substations or breakers.
  • Local Service Disruption & Anti-Interference
    • When stop_comm_service is enabled, workers call FindProcessIdByName and, upon success, execute OpenProcess/TerminateProcess (0x1000303D/0x10003046) against the configured service name (defaults to D2MultiCommService.exe), directly halting ICS communication software.
    • Silent/verbose behaviour toggles (this[2] check in RunIec104SessionWorker and Iec104ClientThread) plus file logging (uselog, logfile) afford attackers operational flexibility while maintaining live feedback through LogApduDetails and printable IEC cause/type breakdowns.
  • Execution Flow Summary
    1. Caller exports Crash to kick off, which parses configuration and spins up one worker thread per target.
    2. Each worker optionally disables a competing communication service, opens an IEC‑104 TCP session, performs the STARTDT handshake, and logs the negotiated counters.
    3. The worker walks the configured timeline (range/shift) of IEC operations, repeatedly issuing single commands or control frames, checking acknowledgements, and re-queueing as dictated by the script.
    4. Threads persist indefinitely, maintaining supervision frames and logging traffic until manually stopped.

Evidence Summary

  • LaunchConfiguredIec104Sessions:0x100014f9–0x100015b9 ties configuration ingestion to multi-threaded execution against all parsed session blocks.
  • ParseIec104ConfigFile token references (target_ip 0x100017B0, stop_comm_service 0x100018EF, command_type 0x10001DDF, operation 0x10001F1F, sequence 0x10002004) demonstrate attacker-controlled scripting parameters.
  • Service-kill path in RunIec104SessionWorker (OpenProcess 0x1000303D / TerminateProcess 0x10003046) coupled with default target string D2MultiCommService.exe (0x10004ED3) evidences deliberate ICS disruption tooling.
  • IEC transport stack: Iec104Connect (WSAStartup 0x100023E9, connect 0x100024EB) plus TransmitApdu (send 0x10002642) and ReceiveApdu (recv 0x10002730) confirm bespoke IEC‑104 client implementation.
  • Command issuance via IssueSingleCommand:0x10002D30 (type ID 45 assignment at 0x10002DB0, qualifier handling 0x10002DE3–0x10002E05) and scheduling logic (range use at 0x1000315D, shift at 0x100031AE) highlights automated actuator control.

Verdict Malicious — purpose-built IEC‑104 intrusion tool capable of terminating industrial communication services and executing scripted control commands against substations; functionality, configuration surface, and targeted defaults provide clear adversarial intent.

Next Steps

  1. Locate and secure any companion configuration scripts on the affected host; they will disclose intended targets and command schedules.
  2. Isolate ICS assets reachable from the compromised machine, review IEC‑104 logs for matching command sequences, and coordinate with plant operators to validate system integrity.
@pehyinchin
Copy link

pehyinchin commented Nov 6, 2025

  • LaunchConfiguredIec104Sessions:0x100014f9 @0x100014e0 Crash
  • WSAStartup: Winsock network communication protocol

  • empty implementation in DllMain
  • ✓ exported Crash symbol creates thread CreateThread to execute at start address StartAddress
  • @0x100015e0 start address StartAddress: "IEC-104 client: ip=%s; port=%s; ASDU=%u"
  • 🔥 Execution Flow Summary

References

WSAStartup: This function is used to initialize low-level network functionality. Finding calls to WSAStartup can often be an easy way to locate the start of network related functionality.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment