Remote access trojans (RAT's) are tools often used by hackers for controlling compromised targets. They've been around for quite a while, and have evolved slowly over time. Last week, the FBI took overt action against many operators of the BlackShades Net RAT, bringing it into the public eye.

BlackShades Net

BlackShades Net is a RAT that has been around for a few years. It has been the source of a few arrests, including the co-author in 2012. It was developed as for sale malware, sometimes poorly masquerading as legitimate remote administration software. It can be found being sold or leaked on black hat forums along with a user manual and setup manual.

Server

In RAT's as well as other malware, the component installed on the infected host can be referred to as the server. It controls operations on the host, in this case including actions like launching DDoS attacks and gathering information such as keystrokes and images from the web cam. From a defense perspective, this is the most interesting component.

Functionality

The features BlackShades has aren't very unique, but there are quite a few of them. Here are the features the attacker has access to:

- Control many computers at once - View Screens - Upload file - Download file - Keylogging - Ransoming files - Facebook Hijacking - USB Infection - Instant Messaging Spreading - Torrent Seeder - Bot market place (buy and sell infected machines) - DDoS - Web cam access - Manage Proxies - Block/Redirect URLs - Proxy through infected - Inject itself into other processes - Multiple persistence methods - Chat with the infected - Delay before execution - Password Recovery - Ad Clicking - Audio capture - Form grabber

Since I had a version of the client available, I decided to try out some of these features first hand to show what an attacker would see.

When a server first connects back to the client, it gets added to the server list.

If we start typing on the compromised box, we can start to see it in the client.

The screen shot feature acts more like an active screen viewer, automatically updating while the window is open.

The web camera feature is intrusive, but it could be worse. When using this feature, the light on my web camera did activate. If you have a strong concern about someone accessing your web camera, I suggest a web camera cover, or opaque tape.

Static Analysis

The server is written in Visual Basic 6, which has long been as a technique by attackers. This allows them to write simpler code to do more complex operations, cutting down on the amount of technical skill required to write or add to their RAT. It also requires some different reverse engineering techniques (or tools) that are generally only used for reversing Visual Basic but can get closer to the original code.

Detection

There are a large number of BlackShades samples around, and depending on how they are packed/crypted, their detection rates vary. Our machine learning-based detection method has no issue with these binaries.

Configuration Extraction

Any configurable malware needs to store some sort of configuration, and this configuration is the key to monitoring the actions of those controlling the malware. Malware developers/users are well aware of this, so they attempt to hide the configuration as much as possible. When building the server binary from the client, there is an option to build with a password, which obfuscates the configuration.

The configuration is stored in an ASCII string, which is hex encoded. The length can be variable since it stores information like the domain being used for the client. Here is a sample:

743A324C48683D60554F60784362505D3578585A3F5B636F60434F504E557636A7C95F6C9C0CAADC57057BFAE1356CB09DF213314D3E98F95DAFC37477A881AF767EC6AABC9CC463BE4F805D8FF98A34DAF3EDA24C972F5F6D9E5FD2929636890049BB1F361E43F3733FC395ADF17E18533013C22529995DA15EB58800F086554EB449347F091D0A4A91A933CA8BDB673475DD294687AD0877B283D170511E416B207F73540F20BCA5AF8957F7FB2B55C258911A0BBD2F723DBFB9D332D9868E07289C635E800728434EE45EB69596BC5D3C3137BF3244

After we decode this, we still have an obfuscated blob of information. The first 32 bytes are used as a key to decrypt the remaining bytes.

The decryption process in two steps, and the first step is seed generation. The seed value is a 4 byte integer, which is generated through a fairly complex set of bit shifts and XOR's. It generates 256-integer entries that are XOR'd against the key value. This is done incrementally, and then returned as the seed. The good news is we don't have to implement any of this if we want to statically extract the configuration.

For the decryption of the configuration, the PRNG for Visual Basic is used. The value generated from the key is set as the seed for next values to come out of the PRNG. This PRNG is powered by the following pseudo-code.

seed1 = ( seed0 * 1140671485 + 12820163 ) % (2^24)

This is actually an extremely simple and weak PRNG. Despite the size of seed values, it is cut down to 24 bits of possible values. This means that if we wanted to brute force this integer value, there would only be 16,777,215 entries we needed to try. The decryption is done by computing the XOR of the PRNG output and each character in the obfuscated blob (one iteration of the PRNG for each character).

Once the decryption finishes, we have the configuration string. The configuration string splits values with three 0x0c bytes. The order of the configuration appear in the following order:

- Controller host name - Client Control Port (TCP) - Client Transfer Port (TCP) - Bot name - File name - "app" or "tmp", determining where to install - Registry Persistence name - Active Setup Persistence name - Install - Unknown - Unknown - Delay length - Infect USB drives - Mutex name - Log file - Folder name - Unknown - "Protect Process"

Here is a sample configuration string decrypted:

0c 0c 0c 31 39 32 2e 31 36 38 2e 31 2e 31 0c 0c |...192.168.1.1..| 0c 34 34 34 33 0c 0c 0c 34 34 33 34 0c 0c 0c 4c |.4443...4434...L| 6f 63 61 6c 0c 0c 0c 6c 6f 63 61 6c 2e 65 78 65 |ocal...local.exe| 0c 0c 0c 61 70 70 0c 0c 0c 77 69 6e 64 6f 77 73 |...app...windows| 0c 0c 0c 0c 0c 0c 30 0c 0c 0c 30 0c 0c 0c 30 0c |......0...0...0.| 0c 0c 30 0c 0c 0c 30 0c 0c 0c 50 44 56 45 46 4a |..0...0...PDVEFJ| 51 55 30 52 0c 0c 0c 4e 61 77 0c 0c 0c 0c 0c 0c |QU0R...Naw......| 31 0c 0c 0c 30 |1...0|

Here is the same configuration string after it has been parsed:

'192.168.1.1' '4443' '4434' 'Local' 'local.exe' 'app' 'windows' '' '0' '0' '0' '0' '0' 'PDVEFJQU0R' 'Naw' '' '1' '0'

Here is a quick Python (v2.7) script to extract the configuration from non-encrypted non-compressed BlackShades binaries.

import re from os.path import abspath, isfile, isdir, join from os import listdir prng_seed = 0 def is_valid_config(config): if config[:3] != "\x0c\x0c\x0c": return False if config.count("\x0C\x0C\x0C") < 15: return False return True def get_next_rng_value(): global prng_seed prng_seed = ((prng_seed * 1140671485 + 12820163) & 0xffffff) return prng_seed / 65536 def decrypt_configuration(hex): global prng_seed ascii = hex.decode('hex') tail = ascii[0x20:] pre_check = [] for x in xrange(3): pre_check.append(ord(tail[x]) ^ 0x0c) for x in xrange(0xffffff): prng_seed = x if get_next_rng_value() != pre_check[0] or \ get_next_rng_value() != pre_check[1] or \ get_next_rng_value() != pre_check[2]: continue prng_seed = x config = "".join((chr(ord(c) ^ int(get_next_rng_value())) for c in tail)) if is_valid_config(config): return config.split("\x0c\x0c\x0c") return None def extract_configuration(file_path): with open(file_path, 'rb') as f: strings = re.findall("[0-9a-fA-F]{154,}", f.read()) for s in strings: if (len(s) % 2) == 1: s = s[:-1] ret = decrypt_configuration(s) if ret is not None and len(ret) > 15: return ret return None def enumerate_paths(path_list, recursive_scan): ret_paths = [] while len(path_list) != 0: file_path = abspath(path_list[0]) del path_list[0] if isfile(file_path): ret_paths.append(file_path) elif isdir(file_path): for p in listdir(file_path): p = join(file_path, p) if isfile(p) or (isdir(p) and recursive_scan): path_list.append(p) return ret_paths if __name__ == '__main__': from argparse import ArgumentParser parser = ArgumentParser( prog=__file__, description="Attempts to extract configuration from BlackShades samples", version="%(prog)s v1.0.0 by Brian Wallace (@botnet_hunter)", epilog="%(prog)s v1.0.0 by Brian Wallace (@botnet_hunter)" ) parser.add_argument('path', metavar='path', type=str, nargs='+', default=None, help="Paths to files or directories to scan") parser.add_argument('-r', '--recursive', default=False, required=False, action='store_true', help="Scan paths recursively") args = parser.parse_args() for path in enumerate_paths(args.path, args.recursive): answer = extract_configuration(path) if answer is not None: print "{0} - {1}".format(path, repr(answer))

Identification

BlackShade servers have plenty of different reliable ways to be detected. The difficulty in identification would be in the cases where the sample was packed or crypted. Here is a quick Yara rule for identification.

rule BlackShadesServer{ strings: $str1 = "bss_server" $str2 = "txtChat" $str3 = "UDPFlood" condition: all of them }

Summary

BlackShades is a remote access trojan which can be used by attackers to remotely control an infected host. It has a wide variety of features, although no particular feature is unique from others we've seen before. It is developed in Visual Basic, and stores its configuration in a string resource, which is obfuscated with a built in key. The key can be ignored in analysis though, as the configuration encryption can easily be brute forced. As always, our machine learning based detection models have no trouble detecting this malware.

- Brian Wallace AKA @botnet_hunter

Samples