Colonial Pipeline Ransomware Attack: Revealing How DarkSide Works

Colonial Pipeline Ransomware Attack: Revealing How DarkSide Works

roughout the last two weeks, the entire cybersecurity community has been riveted by the Colonial Pipeline ransomware attack. It is one of the most notable attacks on critical infrastructure of the past few years and has directly and indirectly impacted multiple industries in the U.S economy. Thankfully, operations are up and running after an approximately week-long outage and reported payment of a $5 million ransom.1

DarkSide, the Ransomware as a Service (RaaS) deployed against Colonial Pipeline, is a good example of similar malware attacking organizations around the globe. Carefully prepared and deployed, it uses a combination of techniques to successfully extort its victims.

Nozomi Networks Labs has studied the internals of the DarkSide executable and today we’re sharing our findings to reveal the techniques used by its machine code in three areas: the selection of victims and files, ensuring anonymity and anti-detection, and preventing data restoration. We also provide IoCs and a decryption script to help you detect DarkSide.

It’s important to remember that the sum of Darkside’s code translates to devastating consequences in the physical world. We encourage you to understand DarkSide’s techniques to help you assess both your own defenses and your incident response capabilities.

DarkSide Ransomware: Technical Analysis

Victim Validation

The malware first collects basic information about its victim’s computer systems to learn the details of the technical environment.

The malware obtains the affected computer’s name.
The malware obtains the affected computer’s name.
DarkSide collects the victim’s basic system information.
DarkSide collects the victim’s basic system information.

In addition, it skips victims from certain geographical regions by checking the language used by their systems. (Notably, DarkSide does not attack systems that use Russian or other Eastern European languages.2)

The ransomware checks if the system language is the one used in CIS countries.

Selection of Files for Encryption

Next, DarkSide determines what files to encrypt. If malware attempts to encrypt all the files available on the system, it quickly makes the system unusable – and leaves the victim without information on how contact the attackers. In addition, it takes significantly more time to do the encryption than is needed for the purposes of executing the attack. DarkSide is particularly selective about what files it encrypts, selecting them mainly by examining their file directories, file names and file extensions.

The list of directories, file names and file extensions skipped during the encryption.
The list of directories, file names and file extensions skipped during the encryption.

Anonymity

To remain anonymous and prevent prompt shutdown, websites for contacting ransomware threat actors are hosted in the Tor network.

A section of DarkSide’s instructions describing how to access the Tor-based website.
A section of DarkSide’s instructions describing how to access the Tor-based website.

Anti-Detection Techniques

To stay under the radar until the victim’s systems are impacted, DarkSide incorporates various commonly used techniques.

Self-Encryption

Most of the Darkside’s critical strings are encrypted to avoid triggering detection.

The XOR-based decryption algorithm.
The XOR-based decryption algorithm.

For the same reason, the malware’s main configuration is also encrypted. It is compressed with aPLib, with individual configuration values encoded with a Base64 algorithm.

Decryption and decompression of the configuration block.
Decryption and decompression of the configuration block.
Base64-encoded configuration values in the malware.
Base64-encoded configuration values in the malware.

Dynamic API Resolution

WinAPIs are the standard way programs interact with the Windows operating system to access certain functionality, including file and network operations. Therefore, use of these interfaces quickly reveals the actual purpose of the malware to security systems. 

To prevent detection, DarkSide does not immediately have all the APIs used available in the import table, as legitimate executables do. Instead, it resolves them dynamically before using them, some by hashed names and some by encrypted names.

The dynamic WinAPI resolution used by DarkSide.
The dynamic WinAPI resolution used by DarkSide.

Preventing Data Restoration

If system administrators could quickly and easily restore the affected data without paying money to criminals, ransomware attacks would not succeed. The authors of DarkSide incorporate multiple techniques to ensure ransom is paid.

Dealing with Backups

Ransomware makes sure that standard backup solutions are unusable on the targeted machines. Windows has a feature called Shadow Copy aimed at dealing with such situations. It allows the creation of backup copies of computer files so they can be restored when needed. The main limitation of this approach is that the backup files are stored on the same system as the original files. If malware compromises the system, the backup files are readily deleted.

The commands used to get a list of Shadow Copy backups.
The commands used to get a list of Shadow Copy backups.

In addition, the malware can search for backups by name:

The ransomware’s search for and deletion of backups.
The ransomware’s search for and deletion of backups.

Finally, DarkSide attempts to disable various backup solutions, searching for them by name.

The list of services to terminate from the embedded configuration.
The list of services to terminate from the embedded configuration.
The process DarkSide uses to stop and delete backup-related services.
The process DarkSide uses to stop and delete backup-related services.

Correct Use of Symmetric and Asymmetric Encryption

Many first generations of ransomware lacked proper encryption, which made it possible for victims to recover files on their systems for free. Unfortunately, those days are long gone, and modern malware families do not repeat this mistake.

The main difference now is that symmetric encryption has been enhanced with focused use of asymmetric encryption. The former uses the same secret key for both encrypting and decrypting the data, therefore intercepting it is enough to restore access to the data.

On the other hand, asymmetric encryption uses a notion of private and public keys. While the encryption is done using a public key, the decryption is impossible without a private key. DarkSide malware implements this functionality properly by only embedding the public key in the malware and keeping the private key confidential.

 The main disadvantage of asymmetric encryption over symmetric is the encryption speed. To get the best of both worlds, the authors of DarkSide encrypt victims’ files using a symmetric encryption algorithm (Salsa20 with a custom matrix) and then encrypt the corresponding symmetric keys with their asymmetric public key (RSA-1024).

The symmetric Salsa20 encryption algorithm with a custom matrix.
The symmetric Salsa20 encryption algorithm with a custom matrix.

DarkSide Demonstrates Modern Ransomware Techniques

DarkSide is just one example of a modern ransomware family that combines multiple time-tested techniques to achieve its goal. It also highlights the effectiveness of the RaaS model, which is gaining in popularity. With this model, multiple parties are involved in each attack, with a division of effort that plays to the strengths of each party.

With RaaS, experienced malware writers focus on the development of the core ransomware code, leaving deployment to affiliates who specialize in gaining access to the networks of targeted organizations. In the case of DarkSide, it is estimated that their more than 40 victims have paid $90 million in total bitcoin, with $15.5 million going to the development group and $74.7 million going to its affiliates.3

We hope that this technical analysis of DarkSide helps you better understand ransomware techniques and evaluate your own defenses and incident response capabilities. And, to help you detect DarkSide, IoCs and a script for decrypting embedded strings is provided at the end of this article.

It goes without saying that using network monitoring tools that help you detect unusual behavior and activity early in the malware kill chain gives you the best chance to contain ransomware before the final payload is executed. Such tools also provide actionable forensic information, as well as logs and pcaps, to assist with a timely response.

References:

  1. “Colonial Pipeline Paid $5 Million Ransom to Hackers,” CNBC, May 13, 2021.
  2. “Colonial pipeline hack claimed by Russian group DarkSide spurs emergency order from White House,” NBC News, May 10, 2021.
  3. “DarkSide Ransomware has Netted Over $90 million in Bitcoin,” Elliptic, May 18, 2021.

IOCs

  • 0a0c225f0e5ee941a79f2b7701f1285e4975a2859eb4d025d96d9e366e81abb9
  • baroquetees[.]com
  • rumahsia[.]com

Script

Here is an IDAPython script to decrypt embedded strings, it requires the cursor to stay at the decryption routine:

# Author: Nozomi Networks Labs import idautils import idaapi import idc import struct def is_utf16_heur(string): counter = 0 for val in string: if val == '\x00': counter += 1 if counter/float(len(string)) > 0.4: return True return False def chunks(lst, n): for i in range(0, len(lst), n): yield lst[i:i + n] def decrypt_block(enc_string, key_matrix): dec_string = [] for enc_block in chunks(list(enc_string), 255): temp_key_matrix = key_matrix.copy() bl = 0 for i in range(len(enc_block)): bl = (bl + temp_key_matrix[i+1]) & 0xFF al = temp_key_matrix[i+1] ch = temp_key_matrix[bl] temp_key_matrix[bl] = al temp_key_matrix[i+1] = ch al = (al + ch) & 0xFF al = temp_key_matrix[al] enc_block[i] = enc_block[i] ^ al dec_string += enc_block dec_string = ''.join(map(lambda x: chr(x), dec_string)) return dec_string def guess_encoding(dec_string): utf16_flag = False if is_utf16_heur(dec_string): try: dec_string_print = dec_string.encode('latin-1').decode('utf-16le') idc.set_inf_attr(INF_STRTYPE, STRTYPE_C_16) utf16_flag = True except Exception as e: pass if not utf16_flag: dec_string_print = dec_string idc.set_inf_attr(INF_STRTYPE, STRTYPE_C) # dec_string_print = dec_string_print.replace('\r', '\\r').replace('\n', '\\n') return dec_string_print def decrypt_all(enc_func, key_matrix): for ref in idautils.CodeRefsTo(enc_func, True): arg_addr = idc.prev_head(ref) if idc.print_insn_mnem(arg_addr) == 'push': enc_string_addr = idc.get_operand_value(arg_addr, 0) if enc_string_addr == 0: print('Warning: wrong address of the encrypted string at %x: %x' % (arg_addr, enc_string_addr)) continue enc_string_size = struct.unpack('