PLC Simulation Concepts, Design, and Implementation
Cisco Systems, Inc.
Critical Infrastructure Assurance Group (CIAG)
Programmable Logic Controllers (PLCs) are common in some industrial
applications (especially discrete manufacturing) and increasingly have network
interfaces which support Ethernet and TCP/IP protocols as well as more
traditional communication interfaces such as MODBUS, DeviceNet, ContrlNet,
Foundation Fieldbus, etc.
As is the case with any network device, different vendors implement their own
shells on telnet and support various FTP commands, depending on their
application requirements. The Ethernet communication module of the PLC
typically runs an embedded operating system that includes standard network
protocol as well as implementations of industrial network protocols such as
Modbus/TCP or EtherNet/IP. For example, telnet and FTP servers are common and
have identifying information which can be used to determine the vendor and
version of software. Even on the industrial protocol side, we saw that not all
PLCs support all commands of a given industrial protocol, so that
implementations can be fingerprinted. Depending on the type (and capabilities)
of the device there may be slight differences in the protocol.
All of these characteristics make it possible for attackers to identify
specific versions and vendors of device and allow us to be able simulate the
devices as well.
We followed the following approach when simulating a PLC:
Implement the generic features so that users can easily change them, add
new features and re-submit them
The feature implementation should be so that the code will serve as
examples for the users to change it according to their own needs.
Once the users submit enough code for more implementations, we visualize
putting them into templates so that a generic configurable engine can load them
according to a defined configuration
The following are the network components in a PLC that need to be simulated:
The TCP/IP Stack of the PLC
The simulation of the Modbus/TCP server implementation.
The simulation of the FTP server, that is found on some PLCs.
The simulation of the Telnetd server, that may be found on some PLCs.
The simulation of the management HTTP server, which increasingly common on
PLCs and other industrial network devices.
Note that the scripts above can be used along with honeyd
or standalone and need root permissions because they have to
bind themselves to previleged ports below 1024.
Simulating the TCP/IP Stack of the PLC Communication Module
In order for Honeyd to simulate the TCP/IP stack of a PLC, adding the TCP/IP
signature of the device to the honeyd's nmap.prints
file would be sufficient. But in oder for the attacker to feel that the stack
is a PLC stack, the signature has to be in the database of the scanning tool
that he is using. Though we tested that by putting the signature in
nmap-os-fingerprints file (which is Nmap's
fingerprint database), we do not know of any scanner having the signature of
any PLC at the time of writing this document.
Simulation of the Modbus/TCP server
The PLC can have multiple industrial protocol implementations
which will listen at their corresponding ports for packets
from the corresponding clients.
We decided to simulate the Modbus/TCP server as a proof
of concept because the protocol is simple. ModbusSrvr.py
starts out with listen() method, which binds port 502
and waits for client connections. Once a client gets
connected to it, it initiates a thread to serve the client
and continues to listen on the port for further client
connections. The thread calls the processData()
method which extracts the top Modbus Header data and calls
the method sendResponse() to send the correct response.
In MODBUS protocol, the response depends on the function code
of the query. Since we are not the experts of the protocol
and we do not necessarily expect the users and developers
of SCADA honeynet to be experts on industrial protocols, we
followed and recommend the crude approach of observing and
analyzing the communication packets between some clients
and the PLCs. Based on the observation and analysis we chose
to implement the "top responses" and to send an "error code"
for the rest of the queries. The following are the observations:
- There are two types of heavily used queries, the writes and the reads, and
the target can be either coils or registers.
- For responses to read requests, the response would be to give back data,
equivalent to the number of bits requested in the read request. If its read
multiple targets, then you usually give multiple modbus headers.
- For responses to write requests, you give the bit/byte/word c ount of the
We implemented the responses to read_coil (function code 1), write multiple
registers (function code 16), diagnostics (function code 8 and the exception
response with code 1(unknown function code). We welcome the users to study and
analyze other responses and implement them. The script can be found in
We also included our test file, modbusScanner.py, to send modbus packets
towards the modbussrvr.py implementation. The users should manually
go into modbusScanner.py and he can edit values of different modbus headers.
Simulation of the FTP server
The honeyd has shell script based FTP simulation, we decided
to rewrite it in Python because it is an easier language for
and we want to add more functionality to it.
We implemented the following commands:
The user command, when the user gives a username
The password command, when the user gives the password
The list command, when the user gives a ls command
The syst command, which gives the user information
about the system
The port for transferring data for various commands
It has various points where it writes information into the
logfile and the user needs to change that to suite his or
her own needs just by invoking writeLog method and passing it
the string to write. The writeLog methos opens up "/var/log/
scadahoneynet.log" and appends information to it by default.
The user should change the responses given as variables given
at the top (such as ListCommandResponse and Syst
CommandResponse of the file which suites their needs.
The script can be found in plc/vxworks-ftpd.py
Simulation of the Telnet server
We decided to write a specific telnetd script because most of the PLCs run
embedded systems and the shell has a unique set of commands.
We implemented help and ls and cwd commands and the user gets the list of
commands when he just hits return.
The script can be found in plc/vxworks-telnetd.py
Simulation of the Web server
Frequently the user connects to the web server of the device and a Java applet
is downloaded to the client and runs within the web browser. In some cases, the
applet will them make connection back to the PLC using protocols like
Modbus/TCP and FTP for gathering data.
The concept of an applet tracking the information of the downloader is new to
the Honeynet world, we call them "Honey Applet". The problem with applets is
that they would not be allowed to communicate with any other hosts other then
the hosts that served the applet (http://java.sun.com/sfaq/). So make sure you
have the hosIP variable as the exact hostname tof yours. Since each PLC has
its own user interfaces, again our design and implementation goals are to write
a generic enough proof of concept code which touches on most of the features in
PLC applets. We used Java Swing classes to draw the Applet and we used Java
SUN's 1.4.2 for development.
The Button, and feature to track button clicks
The Textfield, and feature to track text addition and removal
To connect back to a host on port 502 and give information back. the user
can run netcat like TCP listener to get the data back from the applet.
The connectBack() will connect back to the ip described statically
in the code, encoded into the variable, host. We called connect back when the
CA button is pressed or when the test is changed in TransmittButton for
The use of threads and repaint with changing numbers in text fields
The script can be found in plc/StatusApplet.java
It needs to be debated whether the Applet can be replaced with a
PHP script and how much would an attacker know about it if it
were a PHP script