Trustwave SpiderLabs Uncovers Critical Cybersecurity Vulnerabilities Exposing Manufacturers to Costly Attacks. Learn More

Trustwave SpiderLabs Uncovers Critical Cybersecurity Vulnerabilities Exposing Manufacturers to Costly Attacks. Learn More

Managed Detection & Response

Eradicate cyberthreats with world-class intel and expertise

Managed Security Services

Expand your team’s capabilities and strengthen your security posture

Consulting & Professional Services

Tap into our global team of tenured cybersecurity specialists

Penetration Testing

Subscription- or project-based testing, delivered by global experts

Database Security

Get ahead of database risk, protect data and exceed compliance requirements

Email Security & Management

Catch email threats others miss with layered security & maximum control

Co-Managed SOC (SIEM)

Eliminate alert fatigue, focus your SecOps team, stop threats fast, and reduce cyber risk

Microsoft Exchange Server Attacks
Stay protected against emerging threats
Rapidly Secure New Environments
Security for rapid response situations
Securing the Cloud
Safely navigate and stay protected
Securing the IoT Landscape
Test, monitor and secure network objects
Why Trustwave
The Trustwave Approach
Awards and Accolades
Trustwave SpiderLabs Team
Trustwave Fusion Platform
SpiderLabs Fusion Center
Security Operations Centers
Technology Alliance Partners
Key alliances who align and support our ecosystem of security offerings
Trustwave PartnerOne Program
Join forces with Trustwave to protect against the most advance cybersecurity threats
SpiderLabs Blog

BlackByte Ransomware – Pt 2. Code Obfuscation Analysis

In Part 1 of our BlackByte ransomware analysis, we covered the execution flow of the first stage JScript launcher, how we extracted BlackByte binary from the second stage DLL, the inner workings of the ransomware, and our decryptor code. In this blog, we will detail how we analyzed and de-obfuscated the JScript launcher, BlackByte’s code, and strings.

De-obfuscating the JScript Launcher

We received the original launcher file from an incident response case. It was about 630 KB of JScript code which was seemingly full of garbage code – hiding the real intent.

Our first approach to de-obfuscate the script was to simply scroll through the whole length of this obfuscated code, find some interesting blocks and figure out if there were any eval() function calls. We wanted to find an eval() call because this is where the script likely executes relevant code.

As seen in the screenshot below, we found that the first hundred lines of code were mostly unused, garbage code. At line 2494 is a blob of seemingly Base64 encoded strings (which turned out to be the main payload). Then at line 7511 is a lone eval() call.

JScript Code
Figure 1: Highlights of the obfuscated JScript code


The next step was to trace back the code beginning from the eval() call at line 7511, finding the references to the eval’s parameter variable name – “bnlpgh”, then start following the flow and references until we obtained the real code.

Here is an initial flow we followed starting from the eval() call.

Figure 3 - eval flow
Figure 2. Code traceback starting from eval() call


Following the code in this fashion, we were able to distinguish the real code from the garbage. We then prettified the code and renamed the variables to be readable. The code snippet below reveals the first layer:

Figure 3. Beautified First layer of the obfuscated JScript launcher


Above you may see in the first layer code our renamed variable - secondLayerEncoded - this is a string that looks like it was encoded in Base64. Although that is true, it is a Base64 string that has been reversed.

The script creates an XML document object, and using this object, creates an HTML element named “tmp”.  Next, the script writes the decoded second layer from the variable assigned to secondLayerEncoded into the created element. It then reads it back as a “binaryStream” and finally runs it using eval().

After decoding and prettifying the second layer, the result looks like this:

Figure 4. Beautified code of the second layer JScript code


The second layer code reveals that it checks if .NET version 4.0.30319 framework is installed in the system, then proceeds to decode the malware payload (the Base64 strings shown in Figure 2 at line 2494). Afterward, it creates a memory stream object to where it writes the decoded Base64 payload. To run it, it uses the Deserialize_2 method of the System.Runtime.Serialization.Formatters.Binary.BinaryFormatter COM object to load managed code via object Deserialization. When invoked, it creates an instance of “jSfMMrZfotrr” – a class from the malicious .NET DLL loader.

BlackByte: De-obfuscating the Code

The BlackByte binary itself is also heavily obfuscated, both the code and the strings.

Figure 7 - dnspy
Figure 5. BlackByte decompiled using dnSpy


The code obfuscation needed some manual refactoring, and it proved to be tedious!

Below is a snippet of the most common code obfuscation technique we found in BlackByte’s code:

Figure 6. Sample of an obfuscated code


In this function, we can remove the if condition in line 7 since it is always true:

9. if ((46945 ^ 472736) == 491969)

And in line 8, since sizeof(double) equals 8, our variable arg_46_0 will be equal to 

-9992+8+9984 which is equals zero. So, we can refactor the code in line 10 like this:

13. Environment.Exit(arg_46_0); // is the same as Environment.Exit(0)

To make it readable, we rename the function and removing all unnessary code, it would look like this:

1. internal static void kill_process()    
2. {
3.    try
4.    {
5.         Process.GetCurrentProcess().Kill();
6.    }
7.    catch
8.    {
9.         Environment.Exit(0);
10.   }

The same obfuscation technique has been used throughout the code. So, we can painstakingly and manually refactor every function to make it readable.

BlackByte: De-obfuscating the Strings

Another hurdle for analyzing this ransomware is the string obfuscation.

Untitled 3
Figure 7. BlackByte's obfuscated string is represented as a function


In the image above, each encrypted string is declared inside a public static object. The call to the method aCDscCCxGvmZ.k(encryptedString) is a call to a string reversal function, where it reverses the chunk of a Base64 string and then afterward joins those chunks together to form a complete Base64 encoded string.

Let’s take for example this encoded string:

public static object P() {
   return aCDscCCxGvmZ.k("AAAACL+BAAAgD") + aCDscCCxGvmZ.k("K95vZqTDABAAA") +
    aCDscCCxGvmZ.k("YbZietcdo57Pk") + aCDscCCxGvmZ.k("AAAAOQDrIJDAC");

First step is to reverse each chunk:

YbZietcdo57Pk -> kP75odcteiZbY

Then join all together to form a complete Base64 string:


The decoded base64 string is a GZip header starting at the 5th byte.

Untitled 5
Figure 8. First 4 bytes is the size of the decrypted string, and the following bytes are the GZIP compressed string.


The first four bytes of the data are the length of the decoded string. So, we can remove the first four bytes, then apply GZIP decompression to the remaining data.


Untitled 6
Figure 9. GZIP header and the data following it


The next step is to decrypt the output with RC4 algorithm with the key [0xCD 0x92 0xCC 0x93 0xCD 0x98]. And finally, we get the decoded string “powershell.exe”

A CyberChef recipe below can help you with the string decoding. It accepts the whole obfuscated string function, parses the encoded string and decode it:

"args": ["User defined", "\"(.*?)\"", true, true, false, false, false, false, "List capture groups"] },
 { "op": "Fork",
   "args": ["\\n", "", false] },
 { "op": "Reverse",
   "args": ["Character"] },
 { "op": "Merge",
   "args": [] },
 { "op": "From Base64",
   "args": ["A-Za-z0-9+/=", true] },
 { "op": "To Hex",
   "args": ["None", 0] },
 { "op": "Find / Replace",
   "args": [{ "option": "Regex", "string": "^\\w{8}" }, "", true, false, true, false] },
 { "op": "From Hex",
   "args": ["Auto"] },
 { "op": "Gunzip",
   "args": [] },
 { "op": "To Hex",
   "args": ["Space", 0] },
 { "op": "RC4",
   "args": [{ "option": "Hex", "string": "CD 92 CC 93 CD 98" }, "Hex", "Latin1"] }

CyberChef came in handy when analyzing this malware. But a scripting tool like Python can make the de-obfuscation process faster. I’ll leave that as an exercise:

Figure 10: Decoding the string using CyberChef


To end this blog, we'll leave some tips on how to approach obfuscated code like this:

  1. Analyze the code first and see what methods it uses.
  2. Find any string blobs, that may be a result of encryption or encoding. This may be data, a series of hex bytes, or a base64 string. Look for any references to this and follow through.
  3. For scripts, keep an eye on those evaluation expressions, we are talking about eval(). You can sometimes exploit this by replacing it with alert(), msgbox(), console.log(), or a file write operation. And let the script run and see what it prints, however, this is extremely dangerous, so run it in a VM environment.
  4. Learn some encoding and encryption algorithms. Base64, RC4, AES, RSA, or even the simplest bitwise operations like XOR and ROTATE will come in handy.
  5. And lastly, use a tool and debug it. It makes you understand how it works when you follow the code.

For anyone interested, a decompiled source of BlackByte that we have partially de-obfuscated can be downloaded from this Github link:

Latest SpiderLabs Blogs

Trustwave SpiderLabs Report: LockBit 3.0 Ransomware Vs. the Manufacturing Sector

As the manufacturing sector continues its digital transformation, Operational Technology (OT), Industrial Control Systems (ICS), and Supervisory Control and Data Acquisition (SCADA) are becoming...

Read More

Overview of the Cyberwarfare used in Israel – Hamas War

On October 7, 2023, the Palestinian organization Hamas launched the biggest attack on Israel in years, resulting in numerous casualties and hostages taken. Israel responded with a large-scale ground...

Read More

The 2023 Retail Services Sector Threat Landscape: A Trustwave Threat Intelligence Briefing

The annual holiday shopping season is poised for a surge in spending, a fact well-known to retailers, consumers, and cybercriminals alike. The latter group, however, is poised to exploit any...

Read More