Our November post introducing our BlackEnergy2 (BE2) research described new findings on the group’s activity. We presented both details on their plugins and significant findings about some of their targets and victims. In this post, let’s examine several additional plugins more closely, targeting details around BE2 Siemens exploitation, and some of their unusual coding failures.
We previously introduced an unknown set of plugins and functionality for the linux platform, six in total. For the windows platform, we collected 17 plugins. The last post noted the difficulty in collecting on this group. We finish descriptions for our set in this post.
We also collected plugins for the MIPS/ARM architectures, as noted in the previous BE2 post.
Let’s first examine some of the newest and most surprising Windows plugins. It’s interesting that all of these plugins use a custom “FindByHash” function to evade detection schemes and to slow analysis…
The “Destroy” plugin, dstr
The most troubling plugin in the list is the “dstr” plugin. It is a Windows-only plugin. It was used to overwrite data by the BE2 actor, destroying data stored on hard drives by overwriting file contents. While its use may be intended to cover their tracks, it is heavy handed to use this type of tool to cover one’s tracks in a network. Most likely it is a tool of sabotage, much like the Destover wiper seen on Sony Pictures Entertainment’s networks. However, it’s interesting that the BE2 developers created wiper code different from the Destover and Shamoon wiper malware we saw in the Saudi Aramco and SPE attacks. Instead of re-using the commercial EldoS RawDisk drivers in their malware, the BE2 developers wrote their own low-level disk and file destruction routines. It’s also a much more chilling deployment of wipers – instead of a poorly defended media studio, it was delivered to ICS environments.
In order to overwrite stored data on all Windows versions, the dstr plugin supports both user-mode and kernel-mode wiper functionality, which is somewhat surprising. The component maintains both an embedded win32 library and win64 driver modules for its kernel mode functionality. They are rc4 encrypted.
The plugin identifies device id’s for the system’s HDD and creates a handle to the system’s physical drive, with “GENERIC_READ or GENERIC_WRITE” access. Several calls to DeviceIoControl collects data on the physical location of the volume, and the size and properties of this disk. It uses DeviceIoControl with the IOCTL_DISK_GET_DRIVE_GEOMETRY control code in order to retrieve Bytes Per Sector value. dstr then wipes out all open handles to the disk by dismounting it with the FSCTL_DISMOUNT_VOLUME control code.
This routine prepares the system for overwrite and ensures no conflicts for plugin file I/O. Then it makes multiple WriteFile calls to write a zeroed out buffer to disk.
The dstr plugin maintains code for unlocking and deleting the BE2 driver from disk, furthering the group’s goal of keeping their traces hidden from researchers. And notice the FindByHash set of calls above, this sfc_os call disables Windows File Protection for a minute while an application can delete or modify the locked file. So this plugin and its call can proceed and delete the driver.
The plugin looks over all the services in the %system32%\drivers folder and checks the write permission. If access is provided, it unlocks the file, rewrites the embedded driver under the existing driver name and launches it.
Drivers and kernel mode functionality
Decrypted 32-bit driver
|CompiledOn||2014.06.10 13:12:22 GMT|
Decrypted 64-bit driver
|CompiledOn||2014.06.10 13:12:04 GMT|
The 32-bit and 64-bit drivers are identical and compiled from the same source code. These small Windows drivers are supposed to support FAT32 and NTFS file systems, and contain two large code implementation mistakes. In spite of these flaws, it is clear that the author’s goal was to parse a file system and then write random data across files.
These coding fails are unique to this dstr plugin, suggesting a development team effort behind the plugin set code.
Fail #1: The authors reversed the routines for FAT32 and NTFS data wiping when checking the presence of the “FAT32” string in the first 1024-bytes of the system drive.
Fail #2: In the FAT32 routine the Root Directory Sector Number is calculated and is dealt as the absolute offset inside the file rather than next multiplying this number by the bytes per sector
In comparison, there is no such mistake in the NTFS routine and the calculation of the MFT offset is implemented properly:
Goal – File Content Corruption
Apart from that, it is interesting that the authors implement NTFS wiping in an unusual way with strange logic compared to FAT32 ‘straightforward’ wiping. The plugin accomplishes checks for FILE records and at first skips them. Then under certain conditions it rewrites non-FILE record sectors with random buffer which probably corresponds to some file contents and proceeds looping. Then it ends up rewriting the first sectors of MFT and MFT mirror.
grc, plus.google.com replacement communications plugin
This plugin creates a backup communications channel to yet another legitimate service. Most likely this backup channel is used to cloak outbound communications on monitored networks. We have seen APT using everything from Twitter to Google Docs to hide communications in plain sight, and this time the abused service is Google Plus.
This plugin implements the standard Windows HTTP services to interact with Google Plus over https, seeking to find a png file.
The plugin is provided with a specific Google Plus id to connect with, and uses the OLE stream Windows structured storage API along with the GDI+ bitmap functions to handle and parse this png file. This png file content is actually encrypted data containing the new BE configuration file just as it was obtained using ‘normal’ C&C communication. It is encrypted with RC4, just like the embedded dstr drivers. But unlike to the ‘typical’ RC4 BE decryption scheme that uses RC4 once, here it uses RC4 three times: once with hardcoded key found in the grc binary, the second time using the key extracted from the previous decrypted result, and the third time using the ‘id’ machine’s identifier that is normally served as the encryption key during the C&C communication.
Universal serial bus data collection plugin, usb
The usb plugin collects all available information on connected USB drives, and writes out all of these details to a text file, packs it, provides to the main BlackEnergy code, which communicates to a c2.
It uses multiple api calls to collect information on multiple types of connected usb storage devices. It enumerates all usb storage devices connected to the system and retrieves data from all, including SCSI mass storage devices. And, most interestingly, it may be the first implementation of BadUSB-related techniques in APT re-purposed COTS malware that we have seen in the wild.
The code queries scsi devices directly and sends them two types of SCSI commands. The first command with the opcode 0x1A which corresponds to MODE SENSE may result just in the logging of the failed call (‘SendSCSICommand return false’ message).
The second type of SCSI command remains mysterious. It uses undefined opcode 0xf0 and there is no direct evidence of its purpose as it is stated to be vendor specific. This mysterious opcode is referenced around the same time frame of the plugin development in BadUSB offensive research http://algorithmics.bu.edu/twiki/bin/view/EC521/SectionA1/Group5FinalReport. Here, it is noticed in the USB traffic generated by an SMI controller tool. To be specific, there are two calls with the opcode 0xf0 in the code, each passed its own parameters. One of the parameters, 0x2A, is mentioned in the paper to return the string containing the firmware version, NAND flash ID, and controller part number. But this returned information is not logged anywhere.
Also the code loops to retrieve detailed physical data about every attached storage device:
- number of cylinders
- media type (floppy, fixed hard drive, removable media, etc)
- number of tracks per cylinder
- sectors per track
- number of bytes per sector
- physical disk size in bytes
- Device Instance ID
Motherboard and firmware data collection plugin, bios
The bios plugin gathers low level host system information:
It uses several techniques to gather this information:
- win32 api
As a Windows Management Instrumentation (WMI) client application, it initializes COM and connects to the \\root\cimv2 namespace to use the IWbemServices pointer and make WMI requests. The code executes wql queries (“wql” is “sql for wmi”, a subset of sql) to gather victim host details, like the query “SELECT Description, Manufacturer, Name, ProcessorId FROM Win32_Processor”. Here are several queries from the BlackEnergy2 plugin code:
- SELECT Description, Manufacturer, Name, ProcessorId FROM Win32_Processor
- SELECT Product, Manufacturer, Version FROM Win32_BaseBoard
- SELECT Name, OSArchitecture, Version, BuildNumber FROM Win32_OperatingSystem
- SELECT SerialNumber, Description, Manufacturer, SMBIOSBIOSVersion FROM Win32_BIOS
These wql calls provide the attacker with the data like the lines below:
Description=Intel64 Family 6 Model 60 Stepping 3
Name=Intel(R) Core(TM) i7-4710MQ CPU @ 2.50GHz
Name=Microsoft Windows 8.1 Pro
This selectivity is fairly usual. And the plugin does not modify its own behavior based the collected values. What can we infer about the selection of only these values, as they are only being collected and sent back to the attackers? Here are some possibilities:
- the attackers want to evade sandbox and honeypot/decoy environments, and use this collected data to id the host system.
- the attackers have prior knowledge of the environment they are attempting to penetrate, down to the equipment make. Or, they have an idea of the types of hardware they would expect or want to see. In ICS and SCADA environments, these details could be very valuable for an attacker setting up shop. These details could aid in establishing persistence, evaluating true resource capacity and capabilities, tracking down the source of the equipment, or aiding further lateral movement
- the attackers know nothing about the network they are penetrating. They are collecting this information to better understand where this plugin really is running in the victim environment and planning their next moves
When using standard win32 api, the application implements calls to retrieve information on system locales. Oddly, there is special handling for one nordic locale in this particular plugin, “Norwegian-Nynorsk”.
The CPU data collection functionality first calls the Intel cpuid instruction directly. It also directly handles multi-cpu systems and each of their feature sets. This SMP support is hard coded into the plugin.
Additional BE2 Siemens Exploitation Details
Targeting details for BE2 actor events are interesting. When focusing on research sites and energy engineering facilities, the group remotely exploited Siemens’ Simatic WinCC systems. In these events, the attackers attempted to force the ccprojectmgr.exe process to download and execute a specific BlackEnergy2 payload. Let’s examine a couple of example targets here. Based on the different delays for return, the attacks were possibly not automated.
The first exploit attempt ksn recorded was March 2014. The attackers returned with a second failed attempt to exploit that same research system on April 2014, approximately 30 days, 2 hours later.
The BE2 actor then attacked a new target system in May 2014 and failed, and returned with an exploit attempt on that same system in July 2014.
So it looks like there may be a timing cycle to their visits, but the volumes here are too low to be significant.
In all four of these attempts on two different targets, the attackers tried to download their payload from hxxp://94.185.85(dot)122/favicon.ico. The payload changed slightly from March 2014 to the very end of July 2014, presenting the following md5(s). All of these droppers are BE2 malware, modify an existing kernel driver service like “ACPIEC” and start it to load the BE2 kernel module. Note that the attackers planned on re-using the same c2 for the first target, but changed the callback c2 for the second target. None of these components are signed:
fda6f18cf72e479570e8205b0103a0d3 → drops df84ff928709401c8ad44f322ec91392, driver, debug string:”xxxxxxxx.pdb”. C2: 18.104.22.168 (DE, Hetzner Online AG, AS24940)
fe6295c647e40f8481a16a14c1dfb222 → drops 39835e790f8d9421d0a6279398bb76dc, driver, debug string:”xxxxxxxx.pdb”. C2: 22.214.171.124 (DE, Hetzner Online AG, AS24940)
ac1a265be63be7122b94c63aabcc9a66 → drops b973daa1510b6d8e4adea3fb7af05870, driver. C2: 126.96.36.199 (SE, Internetport Sweden AB, AS49770)
8e42fd3f9d5aac43d69ca740feb38f97 → drops f4b9eb3ddcab6fd5d88d188bc682d21d, driver. C2: 188.8.131.52 (DE, Leaseweb Germany GmbH, AS16265)