In the latter half of 2015, the FireEye Labs Advanced Reverse Engineering (FLARE) team identified several versions of an ICS-focused malware crafted to manipulate a specific industrial process running within a simulated Siemens control system environment. We named this family of malware IRONGATE.
FLARE found the samples on VirusTotal while researching droppers compiled with PyInstaller — an approach used by numerous malicious actors. The IRONGATE samples stood out based on their references to SCADA and associated functionality. Two samples of the malware payload were uploaded by different sources in 2014, but none of the antivirus vendors featured on VirusTotal flagged them as malicious.
Siemens Product Computer Emergency Readiness Team (ProductCERT) confirmed that IRONGATE is not viable against operational Siemens control systems and determined that IRONGATE does not exploit any vulnerabilities in Siemens products. We are unable to associate IRONGATE with any campaigns or threat actors. We acknowledge that IRONGATE could be a test case, proof of concept, or research activity for ICS attack techniques.
Our analysis finds that IRONGATE invokes ICS attack concepts first seen in Stuxnet, but in a simulation environment. Because the body of industrial control systems (ICS) and supervisory control and data acquisition (SCADA) malware is limited, we are sharing details with the broader community.
IRONGATE's key feature is a man-in-the-middle (MitM) attack against process input-output (IO) and process operator software within industrial process simulation. The malware replaces a Dynamic Link Library (DLL) with a malicious DLL, which then acts as a broker between a PLC and the legitimate monitoring software. This malicious DLL records five seconds of 'normal' traffic from a PLC to the user interface and replays it, while sending different data back to the PLC. This could allow an attacker to alter a controlled process unbeknownst to process operators.
IRONGATE's second notable feature involves sandbox evasion. Some droppers for the IRONGATE malware would not run if VMware or Cuckoo Sandbox environments were employed. The malware uses these techniques to avoid detection and resist analysis, and developing these anti-sandbox techniques indicates that the author wanted the code to resist casual analysis attempts. It also implies that IRONGATE’s purpose was malicious, as opposed to a tool written for other legitimate purposes.
We first identified IRONGATE when investigating droppers compiled with PyInstaller — an approach used by numerous malicious actors. In addition, strings found in the dropper include the word “payload”, which is commonly associated with malware.
While IRONGATE malware does not compare to Stuxnet in terms of complexity, ability to propagate, or geopolitical implications, IRONGATE leverages some of the same features and techniques Stuxtnet used to attack centrifuge rotor speeds at the Natanz uranium enrichment facility; it also demonstrates new features for ICS malware.
IRONGATE’s characteristics lead us to conclude that it is a test, proof of concept, or research activity.
Even though process operators face no increased risk from the currently identified members of the IRONGATE malware family, IRONGATE provides valuable insight into adversary mindset.
Network security monitoring, indicator of compromise (IoC) matching, and good practice guidance from vendors and other stakeholders represent important defensive techniques for ICS networks.
To specifically counter IRONGATE’s process attack techniques, ICS asset owners may, over the longer term, implement solutions that:
FireEye has identified six IRONGATE droppers: bla.exe, update.exe1, update_no_pipe.exe1, update_no_pipe.exe2, update_no_pipe.exe2, update.exe3. All but one of these Python-based droppers first checks for execution in a VMware or Cuckoo Sandbox environment. If found, the malware exits.
If not found, the IRONGATE dropper extracts a UPX-packed, publicly available utility (NirSoft NetResView version 1.27) to audiodg.exe in the same directory as the dropper. The dropper then executes the utility using the command audiodg.exe /scomma scxrt2.ini. This command populates the file scxrt2.ini with a comma-separated list of network resources identified by the host system.
The dropper iterates through each entry in scxrt2.ini, looking for paths named move-to-operational or move-to-operational.lnk. If a path is found, the dropper first extracts the Base64-encoded .NET executable scada.exe to the current directory and then moves the file to the path containing move-to-operational or move-to-operational.lnk. The path move-to-operational is interesting as well, perhaps implying that IRONGATE was not seeking the actual running process, but rather a staging area for code promotion. The dropper does not execute the scada.exe payload after moving it.
Each IRONGATE dropper currently identified deploys the same .NET payload, scada.exe. All but one of the droppers incorporated anti-detection/analysis techniques to identify execution in VMware or the Cuckoo Sandbox. If such environments are detected, the dropper will not deploy the .NET executable (scada.exe) to the host.
Four of the droppers (update.exe1, update_no_pipe.exe1, update_no_pipe.exe2, and update.exe3) detect Cuckoo environments by scanning subdirectories of the %SystemDrive%. Directories with names greater than five, but fewer than ten characters are inspected for the subdirectories drop, files, logs, memory, and shots. If a matching directory is found, the dropper does not attempt to deploy the scada.exe payload.
The update.exe1 and update.exe3 droppers contain code for an additional Cuckoo check using the SysInternals pipelist program, install.exe, but the code is disabled in each.
The update.exe2 dropper includes a check for VMware instead of Cuckoo. The VMWare check looks for the registry key HKLM\SOFTWARE\VMware, Inc.\VMware Tools and the files %WINDIR%\system32\drivers\vmmouse.sys and %WINDIR%\system32\drivers\vmhgfs.sys. If any of these are found, the dropper does not attempt to deploy the scada.exe payload.
The dropper bla.exe does not include an environment check for either Cuckoo or VMware.
We surmise that scada.exe is a user-created payload used for testing the malware. First, our analysis did not indicate what triggers scada.exe to run. Second, Siemens ProductCERT informed us that scada.exe is not a default file name associated with Siemens industrial control software.
When scada.exe executes, it scans drives attached to the system for filenames ending in Step7ProSim.dll. According to the Siemens ProductCERT, Step7ProSim.dll is not part of the Siemens PLCSIM software. We were unable to determine whether this DLL was created specifically by the malware author, or if it was from another source, such as example code or a particular custom ICS implementation. We surmise this DLL simulates generation of IO values, which would normally be provided by an S7-based controller, since the functions it includes appear derived from the Siemens PLCSIM environment.
If scada.exe finds a matching DLL file name, it kills all running processes with the name biogas.exe. The malware then moves Step7ProSim.dll to Step7ConMgr.dll and drops a malicious Step7ProSim.dll – the IRONGATE payload – to the same directory.
The malicious Step7ProSim.dll acts as an API proxy between the original user-created Step7ProSim.dll (now named Step7ConMgr.dll) and the application biogas.exe that loads it. Five seconds after loading, the malicious Step7ProSim.dll records five seconds of calls to ReadDataBlockValue. All future calls to ReadDataBlockValue return the recorded data.
Simultaneously, the malicious DLL discards all calls to WriteDataBlockValue and instead calls WriteInputPoint(0x110, 0, 0x7763) and WriteInputPoint(0x114, 0, 0x7763) every millisecond. All of these functions are named similarly to Siemens S7ProSim v5.4 COM interface. It appears that other calls to API functions are passed through the malicious DLL to the legitimate DLL with no other modification.
As mentioned previously, IRONGATE seeks to manipulate code similar to that found on a blog dealing with simulating PLC communications using PLCSIM, including the use of an executable named biogas.exe.
Examination of the executable from that blog’s demo code shows that the WriteInputPoint function calls with byte indices 0x110 and 0x114 set pressure and temperature values, respectively:
WriteInputPoint(0x110, 0, 0x7763)
WriteInputPoint(0x114, 0, 0x7763)
Equivalent pseudo code from Biogas.exe:
S7ProSim.WriteInputPoint(0x114, 0, (short)this.Temperature.Value)
We have been unable to determine the significance of the hardcoded value 0x7763, which is passed in both instances of the write function.
Because of the noted indications that IRONGATE is a proof of concept, we cannot conclude IRONGATE’s author intends to manipulate specific temperature or pressure values associated with the specific biogas.exe process, but find the similarities to this example code striking.
The IRONGATE droppers are Python scripts converted to executables using PyInstaller. The compiled droppers contain PyInstaller artifacts from the system the executables were created on. These artifacts may link other samples compiled on the same system. Five of the six file droppers (bla.exe, update.exe1, update_no_pipe.exe1, update_no_pipe.exe2 and update.exe3) all share the same PyInstaller artifacts listed in Table 1.
Table 1: Pyinstaller Artifacts
The remaining dropper, update.exe2, contains the artifacts listed in Table 2.
Table 2: Pyinstaller Artifacts for update.exe2
Figure 1 and 2 list the unique strings discovered in the scada.exe and Step7ProSim.dll binaries.
Figure 1: Scada.exe Unique Strings
Figure 2: Step7ProSim.dll Unique Strings
Table 3 contains the MD5 hashes, file and architecture type, and compile times for the malware analyzed in this report.
Table 3: File MD5 Hashes and Compile Times
FireEye detects IRONGATE. A list of indicators can be found here.
Special thanks to the Siemens ProductCERT for providing support and context to this investigation.