In this article, I will be analyzing a golang ransomware known as robinhood. I will just specifically looking at how the malware encrypts the data in system. No fancy stuff sorry.

NOTE: This is not a complete malware analysis, this is just a article about how a malware written in go may look like.

Lets start by loading the malware in IDA. Since golang binaries are huge, it takes quite some time for IDA to load everything. I take a look at the function windows, and there are already many functions that have helpful names.

Function windows

We know that the main function in the go binary is the main_main function. There are already few functions whose name give away some idea as to what the binary is capable of. For example main_RsaEncrypt most likely does some RSA encryption stuffs, main_Read_Encrypt_Write_WithKey which indicates that it encrypts the file. I decided to hit a breakpoint in those functions, and see where it goes. But the malware did not do any encryption, in stead it just kept on crashing. So started debugging, and found some interesting stuffs. Lets see, the first interesting function that i found was the main_runme function. It takes a argument for the command to run, and it runs it.

main_runme being called

So the main_runme function uses os_exec_command to execute the command.

calling os_exec_command

We can note from here that while coding the code may look something like this:

package main import "os/exec" func runme() { ... exec.Command( .. ) }

It seems in the dissassembly package.Function() appears as outerPackage_InnerPackage_Function. For example exec.Command appears as os_exec_Command, the runme() appears as main_runme. The command being executed here (from the screenshot above) is cmd.exe /c net use * /DELETE /Y. It seems like the ransomware removes all mapped devices in the system. Ok, so no error so far. We continue down again. Ah we see that the ransomware is now trying to read a file.

Trying to read from file

The ransomware tries to read the file c:\\windows\\temp\\pub.key, If the value at esp+0x14 is not zero, then the program exits. In our case the address esp+0x14 had pointed to value 8.

Error

So this is the error handling. Now lets create the file that was missing, and see how it executes. I create a file, with content “stuff like this”

Blurry image

Sorry for the blurry image, but i will describe basically what i am trying to show here.

esp+0x8 will have a slice i.e -> esp+0x8 will point to the value in this case "stuff like this"

-> then below that is length which is 0x1c

-> then below that is capacity which is 0x21c We see that the whole slice is in the stack. More about slices and their structure here https://blog.golang.org/go-slices-usage-and-internals. esp+0x14 is the error code, which is checked if it is zero, this is the

if (err != nil) {} // check i guess

ioutil.ReadFile() function returns slice of byte, and a error, we can see that all of the return is happening in stack.

Go return values

Again after i run the program, the ransomware for some reason does not encrypt the files. Hmm, then i saw that there are a lot of functions to go through here. Malwares are very complex programs, especially ransomware, and going through each functions is a very tiresome and ineffective task. On top of that go compiler adds a lot of functions in the binary.

So instead of going through each function, i analyzed some key funcitons in the main_* domain. Realized that main.Read_Encrypt_Write_WithKey does the actual encryption. Using IDAs xref feature, the following graphs was obtained.

Xref

So then i decided to look only at those function calls that matter here. Continuing my analysis, it seems the content of the file we created is being treated as public key.

Public Key

The malware then uses the path_filepath_Walk function to walk the various available drives. Now the walk function takes an argument to a function to call whenever a new directory or file is encountered. lets name this function WalkFuncPointer. The WalkFuncPointer adds the file into a sort of list and also ensures that the files helpme files the ransomware itself creates is not added to the list to avoid encryption of such files.

filepath function

The rest of the function calls are pretty common for a ransomware, opening files and stuffs. It seems the function main.Read_Encrypt_Write_WithKey calls mainRSA_Encrypt to encrypt, and here is the error we get. The function encoding_pem_Decode throws an error.

It seems the key we wrote the file we created is not of proper format. So I generate a valid public key and wrote it in the pub.key file. And now the malware works.

Also a thing to note is that the malware writes the help files with all the “you need to do this … to get your files back” even before the encryption is successful. Also it does not replace the old file, but rather creates a new file, and then deletes old files using os_Remove. I did not include those, because those analysis did not seem very intersting.

A sample yara rule could be this