Simple DIY real-life malware analysis

Instead of targeting wide audiences, some malware campaigns prefer to fly under the radar. And sometimes they fly straight into the hands of our BadCyberLab analysts, where they are dissected and analysed.

A few days ago a targeted Facebook-based malware campaign was reported to BadCyberLab. We decided to use that opportunity to show how easy malware analysis could be, even for beginners. As the campaign used an off-the-shelf RAT we will focus on the dropper/packer analysis.

Fake job

One of our readers stumbled upon a fake job ad on a closed group for Polish movie industry.

It says

Welcome everybody. Looking for 2 DOPs in Warsaw for Dec 17th. Shooting with my dslrs (5d mark III). 800 PLN [~$190] for 3h.Get in touch if you’re interested, I’ll send the storyboard, screenplay and more details.

The message uses proper language (DOP = director of photography), proper rates (circa 200 EUR for 3h job is good enough to attract attention and not too good to raise suspicion) and promises some interesting work (usually smaller jobs don’t feature a storyboard). It should not come as a surprise that multiple group members contacted the poster within first 10 minutes since the offer was posted.

People who got in touch via FB messages got links to a file hosted on WeTransfer. The filename was Storyboard and screenplay- Exeme.exe. It looks like Exeme was supposed to be the name of the project – probably used to make the EXE extension less suspicious. The same file was also found via VirusTotal with another filename, Design materials – Exetrans.exe. We were unable to locate the post leading to it.

DYI malware analysis

Shortly after receiving the EXE file in our BadCyberLab we identified that it contained an off-the-shelf RAT called LuminosityLink. The RAT itself has been analysed before, so we decided to go after the packer. The actor behind this campaign used some simple tools, which seem perfect for a simple malware analysis tutorial.

The sample is simple, but it has layers. Like ogres do. We’ll start with some static analysis and we’ll try to confirm its findings with dynamic analysis. By the end we’ll identify the method to remove the malware from an infected PC. Let’s start with the sample – you can download it from We perform the analysis on a Linux system, but you can try on (almost) any platform you like.

After downloading the sample we perform a file command.

PE32 executable (GUI) Intel 80386 Mono/.Net assembly, for MS Windows

.NET you say? Looks like we’ll have some bytecode to analyse. We can use dotPeek to have a look at some (almost) easily readable code. In the next step let’s move our analysis to a secure environment guaranteed by a virtual machine (ex. VirtualBox) where we can configure a brand new Windows system using images provided by This way even when our static analysis turns into a dynamic one without our intention of going into this direction, we won’t have much cleaning to do.

Peek inside

After running dotPeek and opening the sample we should see a new entry named “grafikaa” – this is the internal name of our malware. Let’s open the class starting with “xhhe…” (via doubleclick). We should see something similar to the screenshot below.

We’ll start with the funtion named actgHqKiTwOPTJgrMtswcXuISTNbA. By looking at its code we can say that it performs the following actions:

  1. Creation of the byte array by the jocRDdQVGJGYHMHOnyzbQutDfswG method.
  2. Split of the table in two: one up to the 74th byte and a second one with the rest of the bytes.
  3. XOR decryption of the bigger table using smaller one as a key

Equivalent Python code for points 2 and 3 would look like this:

key = table[:74]
data = table[74:]

result = []
for index, character in enumerate(data):
 result.append(chr(ord(character) ^ ord(key[index%74])))

As we already know the encryption algorithm we need to analyse instruction in the function jocRDdQVGJGYHMHOnyzbQutDfswG. It creates the byte table in the following manner:

  1. Reads resource bxOzXIzHUTYdmpK
  2. Reads value (strings table) named lodpxyirK
  3. For every string from the table it reads the resource with the same name
  4. The result is a concatenation of resources from point 3.

If we click on resource bxOzXIzHUTYdmpK we’ll see that dotPeek provides it in the XML format. It should make things easier for us. We copy the contents of the XML to a text file and create a script to decrypt it.

We start be reading the file and finding all the values of this resource. Looking at the contents of the file we can see that the values are encoded with Base64. The code below will read all the values.

# parsing entry file
tree = etree.parse(sys.argv[1])
root = tree.getroot()
# creating dictionary
values = {}
for data in root.findall('data'):
  key = data.get('name')
  value = data.find('value').text
  # decoding base64 before writing
  values[key] = base64.b64decode(value)

Now the dictionary contains all values of the resource. It’s time to read the lodpxyirK table and find all the strings. To rule out any false positives that can come from a way .NET encodes tables, we’ll only look for strings with length greater than 2. This way we won’t have to analyse the serialisation methods used (also know as a “quick and dirty” method). The code below will read the table, find all strings and concatenate them into a one big table.

for string in re.findall('[A-Za-z]{3,}', lod):

table = ''.join(table)

Now we only have to decrypt the table (as in the first piece of code) and save the result. You’ll find the complete script under this link. Try running it, providing as the first argument the XML file and the output file as the second one.

We focused on decryption, but it’s time to have a look at the decryption result. Let’s check it with the file command again:

out: PE32 executable (GUI) Intel 80386 Mono/.Net assembly, for MS Windows

Another .NET file! Let’s open it in dotPeek again.

Another layer: RunPE

This time the internal filename is “Load” and there are three classes under “Root Namespace”: RunPE, Persistence and ExecuteMe. The code is quite clear and without much obfuscation. We can find:

  1. “avast()” function, which probably tries to avoid Avast detection. Task for you: can you figure out how Avast implements some of the functions being detected here?
  2. Displaying dialog boxes with “Archiwum jest uszkodzone!” (Archive file is broken) and “0”. Task for you: when are those windows displayed?
  3. Adding an autostart registry key. Task for you: which key?
  4. Saving executable file to another location. The location itself is saved in another file. Task for you: where are both files located?

You can find the answers below hidden under the spoiler alert. Try not to cheat!

  1. Looks like Avast is adding the snxhk.dll library to every process.
  2. First box will be displayed only if the malware is run from another location than the one where it installed itself. The other will be displayed in every case.
  3. HKEY_CURRENT_USER\Software\Microsoft\Windows NT\CurrentVersion\Windows\Load
  4. A copy of the malware can be found in AppData or Temp folder (depending on Windows version) under the name of FileName.exe and the path to this file will be saved in the tmp0003.txt file.

The resource named Xtreme holds the value of Comp. It is used to run another executable. Now you can try to decode this value using the code written before (with some modifications) in order to obtain another executable.

After stripping both encoding layers you should obtain the final payload. It’s the LuminosityLink RAT used by the campaign author. You can spot it by looking at its resources (including the abuse address!) You can also spot the email address of the person who the RAT is licensed to. The only thing left would be to find the C&C address – which is an easy task for some dynamic analysis.

Confirming static analysis results

Even after putting some considerable effort into the static analysis part there is always some level of uncertainty left. It could be the inherent cyberuncertainty that’s bothering most malware analysts.

We have three different executables – the original one, the intermediate one and the final one. There are now two ways to perform the dynamic part of our analysis. First is to use one of online sandboxes like Hybrid-Analysis or malwr (which is far too easy!) and the other one is to run those files in our virtual environment.

The first and second file should produce more or less the same results. We can check the malware’s behaviour with some nice tools: SysInternals Autoruns to confirm the registry key used to assure persistence and SysInternals Process Monitor to verify the creation of additional files. We can also follow the execution of RunPE. We can also check the information provided by Hybrid Analysis or monitor network connections to find the C&C server address.

If you are thinking now “why should we lose time for static analysis if dynamic analysis provides the same results, but much faster” – it depends on what you want to achieve. If you just need to take aa quick look and extract the C&C information, then dynamic analysis could be your choice. But if you want to understand how the malware works, what are the methods used by malware authors and how they are trying to make our job harder – then static analysis is the way to go. By the way – if you compare the results of dynamic analysis in between the first and the last executable you can easily see that the first one did not perform any network activity – it’s sleep routine prevented the sandbox from analysing the traffic. The last one, unpacked, on the other hand did connect to the C&C without any trouble.

Some conclusions

We had some fun, now let’s move to the useful part. We not only analysed the malware sample but also identified how it should be removed from an infected system. During our analysis we identified a registry key used by the packer to run the payload. It’s existence in the registry of a potentially infected computer is an indicator of compromise (IoC). Removing this registry entry will stop the malware from running on another system start. You should also remember to kill the malicious process (you know its name already) and to remove the file (you also know its location). So:

  1. Kill the process using Process Manager
  2. Remove the malicious file from the disk
  3. Remove the registry key using registry editor or SysInternals Autoruns.

That’s it. So thanks to your hard work you now know how the malware operates and how to remove it from the computer. It’s really that simple! By the way, the C&C server’s domain points to It’s an IP of a VPN service which offers specific port redirection for incoming connections. This is the way malware author hides the real C&C IP.

One thought on “Simple DIY real-life malware analysis”

Leave a Reply

Your email address will not be published. Required fields are marked *