A Totally Tubular Treatise on TRITON and TriStation

Read the original article: A Totally Tubular Treatise on TRITON and TriStation


Introduction

In December 2017, FireEye’s Mandiant discussed an
incident response involving the TRITON
framework
. The TRITON attack and many of the publicly discussed
ICS intrusions involved routine techniques where the threat actors
used only what is necessary to succeed in their mission. For both
INDUSTROYER and TRITON, the attackers moved from the IT network to the
OT (operational technology) network through systems that were
accessible to both environments. Traditional malware backdoors,
Mimikatz distillates, remote desktop sessions, and other
well-documented, easily-detected attack methods were used throughout
these intrusions.

Despite the routine techniques employed to gain access to an OT
environment, the threat actors behind the TRITON malware framework
invested significant time learning about the Triconex Safety
Instrumented System (SIS) controllers and TriStation, a proprietary
network communications protocol. The investment and purpose of the
Triconex SIS controllers leads Mandiant to assess the attacker’s
objective was likely to build the capability to cause physical consequences.

TriStation remains closed source and there is no official public
information detailing the structure of the protocol, raising several
questions about how the TRITON framework was developed. Did the actor
have access to a Triconex controller and TriStation 1131 software
suite? When did development first start? How did the threat actor
reverse engineer the protocol, and to what extent? What is the
protocol structure?

FireEye’s Advanced Practices Team was born to investigate adversary
methodologies, and to answer these types of questions, so we started
with a deeper look at the TRITON’s own Python scripts.

Glossary:

  • TRITON – Malware
    framework designed to operate Triconex SIS controllers via the
    TriStation protocol.
  • TriStation – UDP network protocol
    specific to Triconex controllers.
  • TRITON threat actor – The
    human beings who developed, deployed and/or operated TRITON.

Diving into TRITON’s Implementation of TriStation

TriStation is a proprietary network protocol and there is no public
documentation detailing its structure or how to create software
applications that use TriStation. The current TriStation UDP/IP
protocol is little understood, but natively implemented through the
TriStation 1131 software suite. TriStation operates by UDP over port
1502 and allows for communications between designated masters (PCs
with the software that are “engineering workstations”) and clients
(Triconex controllers with special communications modules) over a network.

To us, the Triconex systems, software and associated terminology
sound foreign and complicated, and the TriStation protocol is no
different. Attempting to understand the protocol from ground zero
would take a considerable amount of time and reverse engineering
effort – so why not learn from TRITON itself? With the TRITON
framework containing TriStation communication functionality, we
pursued studying the framework to better understand this mysterious
protocol. Work smarter, not harder, amirite?

The TRITON
framework
has a multitude of functionalities, but we started with
the basic components:

  • TS_cnames.pyc # Compiled
    at: 2017-08-03 10:52:33
  • TsBase.pyc # Compiled at:
    2017-08-03 10:52:33
  • TsHi.pyc # Compiled at: 2017-08-04
    02:04:01
  • TsLow.pyc # Compiled at: 2017-08-03 10:46:51

TsLow.pyc (Figure 1) contains several pieces of code for error
handling, but these also present some cues to the protocol structure.



Figure 1: TsLow.pyc function print_last_error()

In the TsLow.pyc’s function for print_last_error we see error
handling for “TCM Error”. This compares the TriStation packet value at
offset 0 with a value in a corresponding array from TS_cnames.pyc
(Figure 2), which is largely used as a “dictionary” for the protocol.



Figure 2: TS_cnames.pyc TS_cst array

From this we can infer that offset 0 of the TriStation protocol
contains message types. This is supported by an additional function,
tcm_result, which declares type, size = struct.unpack(‘<HH’,
data_received[0:4]), stating that the first two bytes should be
handled as integer type and the second two bytes are integer size of
the TriStation message. This is our first glimpse into what the threat
actor(s) understood about the TriStation protocol.

Since there are only 11 defined message types, it really doesn’t
matter much if the type is one byte or two because the second byte
will always be 0x00.

We also have indications that message type 5 is for all Execution
Command Requests and Responses, so it is curious to observe that the
TRITON developers called this “Command Reply.” (We won’t understand
this naming convention until later.)

Next we examine TsLow.pyc’s print_last_error function (Figure 3) to
look at “TS Error” and “TS_names.” We begin by looking at the ts_err
variable and see that it references ts_result.



Figure 3: TsLow.pyc function
print_last_error() with ts_err highlighted

We follow that thread to ts_result, which defines a few variables in
the next 10 bytes (Figure 4): dir, cid, cmd, cnt, unk, cks, siz =
struct.unpack(‘<, ts_packet[0:10]). Now things are heating up. What
fun. There’s a lot to unpack here, but the most interesting thing is
how this piece script breaks down 10 bytes from ts_packet into
different variables.



Figure 4: ts_result with ts_packet header
variables highlighted



Figure 5: tcm_result

Referencing tcm_result (Figure 5) we see that it defines type and
size as the first four bytes (offset 0 – 3) and tcm_result returns the
packet bytes 4:-2 (offset 4 to the end minus 2, because the last two
bytes are the CRC-16 checksum). Now that we know where tcm_result
leaves off, we know that the ts_reply “cmd” is a single byte at offset
6, and corresponds to the values in the TS_cnames.pyc array and
TS_names (Figure 6). The TRITON script also tells us that any integer
value over 100 is a likely “command reply.” Sweet.

When looking back at the ts_result packet header definitions, we
begin to see some gaps in the TRITON developer’s knowledge: dir, cid,
cmd, cnt, unk, cks, siz = struct.unpack(‘<, ts_packet[0:10]). We’re
clearly speculating based on naming conventions, but we get an
impression that offsets 4, 5 and 6 could be "direction",
"controller ID" and "command", respectively.
Values such as "unk" show that the developer either did not
know or did not care to identify this value. We suspect it is a
constant, but this value is still unknown to us.



Figure 6: Excerpt TS_cnames.pyc TS_names
array, which contain TRITON actor’s notes for execution command
function codes

TriStation Protocol Packet Structure

The TRITON threat actor’s knowledge and reverse engineering effort
provides us a better understanding of the protocol. From here we can
start to form a more complete picture and document the basic
functionality of TriStation. We are primarily interested in message
type 5, Execution Command, which best illustrates the overall
structure of the protocol. Other, smaller message types will have
varying structure.



Figure 7: Sample TriStation
"Allocate Program" Execution Command, with color
annotation and protocol legend

Corroborating the TriStation Analysis

Minute discrepancies aside, the TriStation structure detailed in
Figure 7 is supported by other public analyses. Foremost, researchers
from the Coordinated Science Laboratory (CSL) at University of
Illinois at Urbana-Champaign published a 2017 paper titled "Attack
Induced Common-Mode Failures on PLC-based Safety System in
a
Nuclear Power Plant". The CSL team mentions that they used the
Triconex System Access Application (TSAA) protocol to reverse engineer
elements of the TriStation protocol. TSAA is a protocol developed by
the same company as TriStation. Unlike TriStation, the TSAA protocol
structure is described within official documentation. CSL assessed
similarities between the two protocols would exist and they leveraged
TSAA to better understand TriStation. The team’s overall research and
analysis of the general packet structure aligns with our
TRITON-sourced packet structure.

There are some awesome blog posts and whitepapers out there that
support our findings in one way or another. Writeups by Midnight
Blue Labs
, Accenture,
and US-CERT each explain how the TRITON framework relates to the
TriStation protocol in superb detail.

TriStation’s Reverse Engineering and TRITON’s Development

When TRITON was discovered, we began to wonder how the TRITON actor
reverse engineered TriStation and implemented it into the framework.
We have a lot of theories, all of which seemed plausible: Did they
build, buy, borrow, or steal? Or some combination thereof?

Our initial theory was that the threat actor purchased a Triconex
controller and software for their own testing and reverse engineering
from the "ground up", although if this was the case we do
not believe they had a controller with the exact vulnerable firmware
version, else they would have had fewer problems with TRITON in
practice at the victim site. They may have bought or used a demo
version of the TriStation 1131 software, allowing them to reverse
engineer enough of TriStation for the framework. They may have stolen
TriStation Python libraries from ICS companies, subsidiaries or system
integrators and used the stolen material as a base for TriStation and
TRITON development. But then again, it is possible that they borrowed
TriStation software, Triconex hardware and Python connectors from
government-owned utility that was using them legitimately.

Looking at the raw TRITON code, some of the comments may appear
oddly phrased, but we do get a sense that the developer is clearly
using many of the right vernacular and acronyms, showing smarts on PLC
programming. The TS_cnames.pyc script contains interesting typos such
as ‘Set lable’, ‘Alocate network accepted’, ‘Symbol table ccepted’ and
‘Set program information reponse’. These appear to be normal human
error and reflect neither poor written English nor laziness in coding.
The significant amount of annotation, cascading logic, and robust
error handling throughout the code suggests thoughtful development and
testing of the framework. This complicates the theory of "ground
up" development, so did they base their code on something else?

While learning from the TriStation functionality within TRITON, we
continued to explore legitimate TriStation software. We began our
search for "TS1131.exe" and hit dead ends sorting through
TriStation DLLs until we came across a variety of TriStation utilities
in MSI form. We ultimately stumbled across a juicy archive containing
"Trilog v4." Upon further inspection, this file installed
"TriLog.exe," which the original TRITON executable mimicked,
and a couple of supporting DLLs, all of which were timestamped around
August 2006.

When we saw the DLL file description "Tricon Communications
Interface" and original file name "TricCom.DLL", we
knew we were in the right place. With a simple look at the file
strings, "BAZINGA!" We struck gold.

File Name

tr1com40.dll

MD5

069247DF527A96A0E048732CA57E7D3D

Size

110592

Compile Date

2006-08-23

File Description

Tricon Communications Interface

Product Name

TricCom Dynamic Link Library

File Version

4.2.441

Original File Name

TricCom.DLL

Copyright

Copyright © 1993-2006 Triconex Corporation

The tr1com40.DLL is exactly what you would expect to see in a custom
application package. It is a library that helps support the
communications for a Triconex controller. If you’ve pored over TRITON
as much as we have, the moment you look at strings you can see the
obvious overlaps between the legitimate DLL and TRITON’s own TS_cnames.pyc.



Figure 8: Strings excerpt from tr1com40.DLL

Each of the execution command "error codes" from
TS_cnames.pyc are in the strings of tr1com40.DLL (Figure 8). We see
"An MP has re-educated" and "Invalid Tristation I
command". Even misspelled command strings verbatim such as
"Non-existant data item" and "Alocate network
accepted". We also see many of the same unknown values. What is
obvious from this discovery is that some of the strings in TRITON are
likely based on code used in communications librarie

[…]


Read the original article: A Totally Tubular Treatise on TRITON and TriStation