CVE-2024-3400: PAN-OS Command Injection Vulnerability in GlobalProtect Gateway. Learn More

CVE-2024-3400: PAN-OS Command Injection Vulnerability in GlobalProtect Gateway. Learn More

Managed Detection & Response

Eliminate active threats with 24/7 threat detection, investigation, and response.

Co-Managed SOC (SIEM)

Maximize your SIEM investment, stop alert fatigue, and enhance your team with hybrid security operations support.

Advisory & Diagnostics

Advance your cybersecurity program and get expert guidance where you need it most.

Penetration Testing

Test your physical locations and IT infrastructure to shore up weaknesses before exploitation.

Database Security

Prevent unauthorized access and exceed compliance requirements.

Email Security

Stop email threats others miss and secure your organization against the #1 ransomware attack vector.

Digital Forensics & Incident Response

Prepare for the inevitable with 24/7 global breach response in-region and available on-site.

Firewall & Technology Management

Mitigate risk of a cyberattack with 24/7 incident and health monitoring and the latest threat intelligence.

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
About Us
Awards and Accolades
Trustwave SpiderLabs Team
Trustwave Fusion Security Operations Platform
Trustwave Security Colony
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

CVE-2024-3400: PAN-OS Command Injection Vulnerability in GlobalProtect Gateway

Overview A command injection vulnerability has been discovered in the GlobalProtect feature within Palo Alto Networks PAN-OS software for specific versions that have distinct feature configurations...

Read More


We all know the cybersecurity industry loves its acronyms, but just because this fact is widely known doesn’t mean everyone knows the story behind the alphabet soup groups of letters, we must deal...

Read More

Phishing Deception - Suspended Domains Reveal Malicious Payload for Latin American Region

Recently, we observed a phishing campaign targeting the Latin American region. The phishing email contained a ZIP file attachment that when extracted reveals an HTML file that leads to a malicious...

Read More