Updated: Dec 30, 2022
For those of you who have been following my series on SCADA hacking, you are aware that SCADA/ICS systems do NOT use the usual protocols that we are accustomed to in the TCP/IP/Ethernet world. There are a over 100 different protocols being used within the SCADA/ICS world, most of which were developed to work over a serial connection. Among the most popular of these is modbus. To better understand what we will be doing in this tutorial see my overview of the modbus protocol here and do the modbus simulation here.
In this tutorial, we will be using a command line tool known appropriately as modbus-cli. This handy little Ruby tool is capable of enumerating the coils on a modbus installation as well as reading and writing to the memory registers. This tool can be used by security engineers to test the security of their SCADA installations using modbus or by Black Hat hackers or cyber war soldiers to wreak havoc on an industrial system.
Step #1: Download and install modbus-cli
To get started, you can download this tool from github. Make certain you have Ruby installed. If you are running Kali or most other Linux distros, this should be no problem.
kali > gem install modbus-cli
Step #2: Schneider Electric and Modicon Terminology
Before we proceed, we need to take a minute to review some terminology. mosbus-cli is designed to be used with both Modicon memory terminology and Schneider Electric's proprietary memory address terminology. For a look at the Schneider Electric terminology, see the table below from Schneider's own documentation.
Note that double words (32-bits) in memory are designated %MD, words (16-bit) are designated with %MW, byte (8 bits) with %MB and bits %MX.
modbus-cli also accepts Modicon memory address nomenclature as well.
As you can see from the table above, Discrete Output coils have memory addresses between 1-9999, Discrete Input Contacts between 10001-19999, Analog Input Registers between 30001-39999 and finally, Analog Output Holding Registers between 40001-49999.
Step #3: modbus-cli Help
Now that you have installed modbus-cli, let's take a look at its help file.
kali > modbus --help
As you can see, this tool's syntax is rather simple once you understand the syntax of the modbus protocol.
modbus [options] SUBCOMMAND [ARGUMENTS]
In this case, the SUBCOMMAND's are read, write and dump.
We can pull up help files for each of the subcommands such as read;
modbus > modbus read --help
kali > modbus write --help
kali > modbus dump --help
Step #4 Using modbus-cli to Read Settings
Now that we understand a bit about this tool, let's test it on some open SCADA facilities. There are many ways to find connections to these facilities including Google hacking, nmap and Shodan, but my favorite is Shodan. If you don't have an account on Shodan, now is a good time to open one.
modbus-cli tool is designed to work on just one SCADA/ICS protocol, modbus. Although this is somewhat limiting, modbus is the most widely used communication protocol in SCADA/ICS systems. Even with systems not specifically designed for modbus, manufacturers often include modbus to make them compatible with other manufacturers products.
Modicon developed modbus in 1979, but Modicon has since been acquired by Schneider Electric of France. Modbus uses port 502 as its default TCP port. By searching Shodan for either "port 502" or "Schneider Electric" in their available banner, we should find some SCADA systems with the modbus protocol functioning.
Step #5 Reading the Values from a Functioning SCADA facility
Now that we have located a functioning SCADA facility via Shodan, let's try reading some of the values from that facility. I have obscured the IP address in these screenshots to protect the innocent, but there are literally thousands of SCADA/ICS systems you can attack with this tool.
First, let's try using the Schneider Electric terminology. Schneider Electric using %MW to designate a word in memory. Let's read the first 20 words from memory.
kali > modbus read <IP address> %MW100 20
We can read the same registers using the Modicon terminology
kali > modbus read <IP address> 400101 20
If we want to read the double words, we can use Schneider's %MD terminology
kali > modbus read <IP address> %MD100 20
Next, if we want to read the coils (remember, coils are either energized or not, so that values are either 0 or 1), we can use Schneider Electric terminology for coils, %M.
We can also read the same coils using Modicon terminology (1-99999).
Step #6 Writing to the modbus PLC
Now that we have seen how we can read the values from a modbus PLC enabled site, now let's see if we can write values to the site. Remember, modbus devices have at least two areas that we might be able to write to, the coils and the registers. Let's first try writing to the registers with Modicon terminology. It's important to note here before we proceed that changing these values comes with a risk that you may be changing the functioning of the PLC and possibly the entire system.
When writing to registers with modbus-cli, the command is nearly the same as the read command except that rather finishing the command with the number of registers you want to read, you designate the starting register to write to, followed by the values you want written in succeeding registers. Let's see whether we can enter the value 2 in the six registers starting with 400101. To do so, we would enter;
kali > modbus write <IP address> 400101 2 2 2 2 2 2
Now that we have written to those six registers, let's go back and read those same registers and see whether we have changed the values.
kali > modbus read <IPaddress> 400101 20
As you can see, we have now altered the values in the first six registers with 2's.
Step #7 Capturing the Data
As a security engineer, we may want to capture the data from our SCADA facility for backup or testing. The more malicious Black Hat hacker or cyber war soldier will likely want to capture the data from the target facility to install on a test facility to better understand the functioning of the system and how they might wreak havoc on it. For instance, the Black Hat may want to know which coil controls the pressure valve on the system and what value that pressure value has in its register that is the threshold for opening and closing it. As you can imagine, if this value is changed, the entire plant could be placed at risk.
We can capture the data by using the read subcommand followed by the option --output followed by the filename to store the data, then finally the IP address, the register address, and the number of registers to capture data from.
kali > modbus read --output datacapture.txt <IP address> 400101 500
Here we have the data for 500 registers to a file called "datacapture.txt". We can now view the data by using the cat, less or more command. Here I have used "less" command.
kali > less datacapture.txt
As you see, here is the data capture of the first 500 registers from this SCADA facility.
modbus-cli is a powerful tool for the SCADA pentester to use to test the vulnerability of these modbus-based systems. At the same time, this tool has the potential to being used by malicious Black Hat hackers and cyber war soldiers to alter the setting and values in a SCADA/ICS site that may have significant--to pay the least--repercussions.