Now that we have a better understanding of the structure of the Modbus protocol,
let's see what that looks like in our lab environment by
monitoring the communications between the PLC at .134 and
the factory control unit at .136.
We begin by launching Wireshark and selecting the network
interface that we want to monitor on.
In this case, we'll monitor on eth0,
then we click the blue shark fin to start capturing traffic.
After some initial DNS traffic,
we start to see a pattern of two Modbus packets followed by a TCP packet.
We have a very basic network set up here,
so it's easy to spot,
but in real networks it's likely that the traffic will be more
complex and there'll be no obvious pattern.
But by applying one or two filters,
such as protocol and source or destination IP address,
it should become apparent quite quickly.
The first thing to note is that there's a repeating block of Query,
Response, and [ACK].
Firstly, for Read Discrete Inputs, function code 2,
and then for Write Multiple Coils, function code 15.
This is one PLC cycle.
The cycle time,
which is the time from the start of one cycle to the start of the next,
is 100 ms, but the time to exchange the various messages is less than 5 ms.
That means that for 95% of the time, there are no message exchanges.
We'll take advantage of that later.
Let's now look in more detail at each of the packets,
starting with the Modbus layer.
Function Code 2 is set, which is the function code for reading discrete inputs.
This is the PLC asking the factory controller for
the status of various equipment, such as the Start button,
the Stop button, and the safety gate.
We also see that the Bit Count is set to 12,
which indicates that 12 inputs should be read.
This suggests the factory controller has a total of 12 potential inputs,
but that's not to say there are actually 12 inputs connected to the controller.
Moving up to the Modbus/TCP layer, which is not the packet TCP layer,
we see, as expected, a Transaction ID, which helps to keep messages in order,
a Protocol ID, which is usually set to 0,
as it is in this case,
the Length of the remainder of the packet is set to 6 bytes,
and the server ID is set to 1, which is the only Modbus server in our network.
Moving forward to the Query Response,
we see the data section of the Modbus packet contains the
status of each connected device or sensor.
A bit value of 1 usually represents true whilst 0 represents false.
So for example, if the Start button was on,
it would have a bit value of 1 whilst the Stop button would have a value of 0.
Following the Read Discrete Inputs Query Response exchange,
the PLC sends an ACK packet to the factory controller
to confirm it's received the data.
It's also worth noting here that the TCP sequence and
acknowledge numbers act as the seed for the following
Modbus Write Multiple Coils exchanges.
Again, this will come in useful later.
Next up,
we have the Write to Multiple Coils query identified by Function Code 15.
The Bit Count is set to 12, suggesting a total of 12 potential connected outputs,
but again, this doesn't mean that there are actually 12 outputs connected.
Next, we have the Byte Count,
which indicates how many bytes the data field takes up.
In this case, we have 2 bytes.
The first is hexadecimal 8a, which is 138 decimal and 10001010 binary.
And the second byte is hexadecimal 02, which is 2 decimal and 0010 in binary.
From this binary pattern, we see that some coils are set to on,
or 1, and some to off with 0.
Without testing or documentation, we have no way of telling what each coil does.
We can also see that the packet has the same sequence and
acknowledge numbers as the previous ACK from the PLC.
Here we see the Write Multiple Coils response,
which confirms to the PLC that 12 bits were set.
This packet is then followed by an ACK from the PLC to say that the message
was received and new sequence and acknowledge numbers have been established
to seed the next Read Discrete Input query.
And so the cycle continues.