MODBUS
===============

Modbus scripts

## in this folder
- `enum_all.py`, script take IP as input and brute force against all the registers. Identified valid registered will be exported to excel file. Modified registers written back to origional values!
- `monitor_multiple.py`, monitor several modbus addresses with a configurable interval and pretty colours
- `set_coil.py`, set a specific coil value, loop option available
- `set_reg.py`, set a specific register value, loop option available
- `GRFICS_bang.py`, GRFICS PoC to destroy the chemical plant via modbus.

## recommendations:
- `https://github.com/sourceperl/mbtget`, Simple perl script for make some modbus transaction from the command line.

## Enumerate SCADA Modbus slave ids (sids) and collects their device information.
when talking to a RTU you supply a SID to tell it which PLC you want to interact with. When talking directly to a PLC generally 0x01 will be the default.
```
nmap --script modbus-discover.nse --script-args='modbus-discover.aggressive=true' -p 502 <host>

```

## mbtget
```
read coils: 
mbtget -u 1 -p 502 -r1 -a 0 -n 125 [ip]

read registers
mbtget -u 1 -p 502 -r3 -a 0 -n 125 [ip]

enumerate coils:
for i in {0..1000}; do mbtget -r1 -a $i -n 1 | grep -v -e exception -e values | tee -a /tmp/coils.txt; done

enumerate registers:
for i in {0..1000}; do mbtget -r3 -a $i -n 1 | grep -v -e exception -e values | tee -a /tmp/holding-regs.txt; done

polling values over time (assume 5 is changing):
for i in {0..1000}; do echo -n `date +"%Y-%m-%d %T"`; mbtget -r3 -a 4 -n 1 | grep -v values | tee -a reg-4.txt; sleep 1; done
```

## enum_all.py
```
$> python enum_all.py -r 0 3 -i 127.0.0.1
******************************
Reading Coils Status - 0x01
100%|████████████████████████████████████| 3/3 [00:00<00:00, 677.19it/s]
Writing Coil Status - 0x05
******************************
Reading Holding Registers - 0x03
100%|████████████████████████████████████| 3/3 [00:00<00:00, 25.89it/s]
Writing Holding Status - 0x06
100%|████████████████████████████████████| 2/2 [00:00<00:00, 246.03it/s]
******************************
Reading Discrete Input - 0x02
100%|████████████████████████████████████| 3/3 [00:00<00:00, 795.93it/s]
******************************
Reading Input Registers - 0x04
100%|████████████████████████████████████| 3/3 [00:00<00:00, 766.69it/s]
******************************
Check the output Excel File - Modbus_Output.xls

```

## monitor_multiple.py
```
$> python monitor_muiltiple.py -h
usage: monitor_muiltiple.py [-h] [-co [COIL [COIL ...]]]
                            [-ho [HOLD [HOLD ...]]]
                            [-di [DISCRETE [DISCRETE ...]]]
                            [-in [INPUT [INPUT ...]]] -i IPADDRESS [-p PORT]
                            [-t TIMEOUT]
optional arguments:
  -h, --help            		show this help message and exit
  -co [COIL [COIL ...]] 		list of addresses
  -ho [HOLD [HOLD ...]]			list of addresses
  -di [DISCRETE [DISCRETE ...]]	list of addresses
  -in [INPUT [INPUT ...]]		list of addresses
  -i IPADDRESS					Input IP Address
  -p PORT 						Port Number
  -t TIMEOUT					request every X seconds

$> python monitor_muiltiple.py -co 0 1 3-6 8 -ho 0-6 -i 127.0.0.1
### watch list ###
coils: (7)[0, 1, 3, 4, 5, 6, 8]
hold reg: (7)[0, 1, 2, 3, 4, 5, 6]
Total = 14
------------------
[coils:[0][1][0][0][0][0][0]][hold regs:[   13][  666][     ][     ][     ][     ][     ]]

```

## set_coil.py
```
$> python set_coil.py -h
usage: set_coil.py [-h] -i IPADDRESS [-p PORT] -c COIL [-tr] [-l] [-t TIMEOUT]

optional arguments:
  -h, --help            show this help message and exit
  -i IPADDRESS, --ipaddress IPADDRESS
                        Input IP Address
  -p PORT, --port PORT  Port Number
  -c COIL, --coil COIL  Coil Number
  -tr, --true           True if set
  -l, --loop            loop on
  -t TIMEOUT, --timeout TIMEOUT
                        request every X seconds

$> python set_coil.py -i 192.168.95.2 -c 5 -tr

```

## set_reg.py
```
$> python set_reg.py -h
usage: set_reg.py [-h] -i IPADDRESS [-p PORT] -r REG -v VAL [-l] [-t TIMEOUT]

optional arguments:
  -h, --help            show this help message and exit
  -i IPADDRESS, --ipaddress IPADDRESS
                        Input IP Address
  -p PORT, --port PORT  Port Number
  -r REG, --reg REG     Register Number
  -v VAL, --val VAL     Register Value
  -l, --loop            loop on
  -t TIMEOUT, --timeout TIMEOUT
                        request every X seconds

```

## GRFICS_bang.py
![GRFICS PoC screenshot](./GRFICS_bang.png)