Golang Gobfuscator Analysis

Automatic Gobfuscator Deobfuscation with EKANS Ransomware

17 March 2021

By Jacob Pimental


A few months ago I saw an article by Netlab 360 describing the malware BlackRota, specifically the obfuscation method used known as gobuscate. I noticed that a deobfuscator was made for this using Binary Ninja’s API, so I decided to take a crack at developing a plugin for Cutter. To demonstrate the tool I created, I will also give a brief analysis of another malware sample that uses gobfuscate, Ekans.

How Gobfuscate Works

Package Renaming

One of the things gobfuscate will do is rename package names to make it harder for analysts to identify them. It does this by taking the package name, hashing it using sha256, and replacing any numbers in the hash with letters using the algorithm:

’g’ + (x – ‘0’) # x is the current character

This means that the package name contains only the characters a-p and is irreversible. The example that the gobfuscate GitHub page gives is that the package github.com/unixpickle/deleteme becomes jiikegpkifenppiphdhi/igijfdokiaecdkihheha/jhiofoppieegdaif.

String Encryption

Each string in the binary is replaced by a function call. Each function contains two byte-arrays that are Xor’d together to return the original string. There are a few different ways that the byte-arrays are stored after the binary is compiled. The first way was through a hardcoded array.

Gobfuscator String Encryption Function Normal byte-array XOR Loop

The byte-arrays can also be stored in pointers, which are run through the function stringslicetobyte and XOR’d together.

Gobfuscator String Encryption Function Variant Byte-arrays being stored in pointers

These differentiations were noted when designing the deobfuscator, as not all functions will be the same. The names for the string decryption functions always contain funcN at the end, where N is an integer value. This makes them easy to spot and write a decryptor for.

How the Deobfuscator Works

Using Cutter’s API I was able to create a plugin that will either deobfuscate the string encryption function that the cursor is on or bulk deobfuscate all strings in the current method. To install the deobfuscator you will need to know the location in which Cutter stores plugins. You can find this by going to Edit -> Preferences -> Plugins in Cutter.

Where to find Cutter plugin location Plugin location for Cutter

Then download the python script from the GitHub repository and move it into the Python folder under plugins. Cutter will need to be reloaded after this. To use the plugin, right-click on a gobfuscate function then select either Plugins -> DeGobfuscate or Plugins -> Bulk DeGobfuscate. The decrypted string is added as a comment above the function. If the comment doesn’t appear right away, go to View -> Refresh Contents to refresh the screen, which should show the comment.

Degobfuscator plugin example Example of encrypted string function

The deobfuscator utilizes Cutter’s API to loop through the assembly code in the function and grab the two byte-arrays that are present. It will then XOR these together and create a comment at the location. It also checks to see if the arrays are stored in either a pointer or are hardcoded into the function.

Ekans Analysis

The Ekans ransomware has been associated with attacks on Industrial Control Systems (ICS). Ekans does not rely on outside resources to perform its functions. Everything is stored within the binary itself, mostly using the gobfuscate string encryption functions. This makes it an ideal candidate for testing the degobfuscate plugin. You can find this specific sample on Hybrid Analysis. The first step in this analysis will be to use rizin-gohelper to recover the function names from the gopclntab.

The first thing the ransomware will do is attempt to create a Mutex Global\EKANS. If that Mutex already exists then execution will end. It will then create the public key object that it will use to encrypt files using RSA. The public key is stored in a string in the main.main function, which was encrypted by gobfuscate. After running the deobfuscator over this, the public key is shown in a comment above the decryption function. It is best to view multi-line comments in the disassembly view in Cutter since the graph view only shows the first line. This string will then be passed to Golang’s pem.Decode function and later the ParsePKCS1PublicKey function.

EKANS Ransomware public key generation Creation of Public Key

After this, the ransomware will create an array of objects to whitelist. This includes file extensions, file names, directories, and a regex statement. The lists are:

All of these strings were encrypted via gobfuscate, which is why the “bulk” option exists. Ekans will then enumerate drives and grab a list of all files that do not match the whitelists. This new file list will later be passed to worker threads for encryption.

EKANS Ransomware whitelisted files Whitelist creation function

The ransomware will then kill a list of 288 hard-coded services. Instead of listing all of the services in this article here, you can find them here. The Ekans process will then kill a list of 1118 processes, which are also included in the linked repository. Ekans will then delete shadow copies using a WbemScripting.SWbemLocator object with the following WMI query:

SELECT * FROM Win32_ShadowCopy

After this, the ransomware will create several threads and pass in the filenames to these via GolLang’s channel functions. The threads will take the filenames, encrypt the files, and write them back to disk.

EKANS Ransomware encryption loop Loop used to create encryption threads

Finally, the ransom note is dropped to the file Fix-Your-Files.txt. The note itself is hard-coded and uses the sprintf function with the ransomware author’s email to format the note, which in this case is bapcocrypt@ctemplar.com.

EKANS Ransomware ransom note Unformatted Ransom Note

Conclusion

I did not want to delve too deep into the Ekans ransomware analysis as this was to demonstrate the usefulness of the degobfuscator plugin. This was my first attempt at making a plugin for Cutter and I enjoyed the challenge very much. I am excited to see what Cutter has in store for the future and will continue to make plugins for it to aid other analysts. As always, if you have any questions feel free to reach out to me on my Twitter or LinkedIn.

Thanks for reading and happy reversing!

Malware Analysis, GoLang, Cutter, Ekans, Ransomware

More Content Like This: