Contents

Malware - Sikomode

Analyst,

This specimen came from a poor decision and a link that should not have been clicked on. No surprises there. We need to figure out the extent of what this thing can do. It looks a little advanced.

Perform a full analysis and send us the report when done. We need to go in depth on this one to determine what it is doing, so break out your decompiler and debugger and get to work!

IR Team


Objective

Perform static and dynamic analysis on this malware sample and extract facts about the malware’s behavior. Use all tools and skills in your arsenal! Be sure to include a limited amount of debugging and decompiling and employ advanced methodology to the extent that you are comfortable.

Tools

Basic Analysis

  • File hashes
  • VirusTotal
  • FLOSS
  • PEStudio
  • PEView
  • Wireshark
  • Inetsim
  • Netcat
  • TCPView
  • Procmon

Advanced Analysis

  • Cutter
  • Debugger

init phase

First, let’s start with basic recon phase

sha256: 3aca2a08cf296f1845d6171958ef0ffd1c8bdfc3e48bdd34a605cb1f7468213e md5: b9497ffb7e9c6f49823b95851ec874e3

After running a FLOSS on the executable, we can see some interesting strings such as:

  • Desktop\cosmo.jpeg
  • http://cdn.altimiter.local/feed?post=
  • C:\Users\Public\passwrd.txt

To be continued…

The binary hash is harshly flagged on VirusTotal

Challenge Questions:

In order to know what langage the binary is written, I load it in Cutter

Answer

The program is written in nim

The answer to this question can be seen in the same window as the program’s language. It can be viewed in PE-studio too.

Answer

The architecture is 64 bits

I executed the binary without inetsim running to see if there was a DNS query that can’t end up. In the Wireshark capture, we can see a strange DNS query during the detonation: update.ec12-4-109-278-3-ubuntu20-04.local.

The binary deletes itself when the query receive no answers.

So I launched inetsim to see if the binary still deletes itself even if he receive a DNS reply.

Even when he receive a DNS reply, he keeps deleting itself.

We can see the full exchange, starting from DNS to TCP into HTTP. The program performs a HTTP GET on / of the domain previously requested (update.ec12-4-109-278-3-ubuntu20-04.local)

After displaying the graph view on Cutter, we can seek for sym.NimMainModule which looks like the casual main function. We can see that a function named checkKillSwtichURL is called.

The screenshot above means that in every case following the test al, al (first block), it ends up to the houdini method.

Another criteria of self deletion is if inetsim is stopped during the execution, the binary instantly delete itself.

Answer
  • If the binary can’t reach the domain update.ec12-4-109-278-3-ubuntu20-04.local
  • If inetsim is stopped during the execution

After investigation of common persistence mechanisms such as services or registry keys via procmon, I didn’t find any way the program can persist.

Answer

The binary don’t seems to persist on the system

As we have seen before, the first callback domain is update.ec12-4-109-278-3-ubuntu20-04.local:

Answer

The first callback domain is update.ec12-4-109-278-3-ubuntu20-04.local

Now it’s becoming a little bit tricky. Let’s dive deeper into the executable behaviour.

In order to exfiltrate the data, the connectivity with the callback domain must be established. After a successful check in with this domain, the malicious binary write the passwrd.txt file under C:\Users\Public\. After creating the file, it searches for Cosmo.jpeg on the desktop. This can be seen with procmon:

Then, if every conditions are met, the exfiltration occurs by base64 encoding the content of the file and encrypt it with the password previously written:

With inetsim and Wireshark opened, I detonated the malware and looked at the network traffic.

As we can see on the screenshot above, the malware tries to resolve cdn.altimiter.local which resolves to the inetsim IP address and send a suspicious GET HTTP request (GET /feed?post=A3BA2EE38A027FFB6F87.....). Moreover, the user-agent of the request is Nim httpclient/1.6.2.

Answer

cdn.altimiter.local

In the last question, we have seen the GET /feed?post=A3BA2EE38A027FFB6F87[...] request that looks very suspicious. Let’s filter this on Wireshark:

The post parameter is always the same length but we can recognize some pattern through all of them even if they are all different. We can assume that the exfiltration is taking place by those GET requests (poor Cosmo 🤧). Each string is 124 character long.

Here is an example of one of the request:

post=B69C1CF58536758068B81553A8FB34291DEBB01907FC28919D7FABF240128ABE45FDA886199DD6BC30090A6472D426C49A9B8BD2855FCE8C1B5876C9BBA9

In procmon we can see the following steps:

  • Crypto stuff
  • Creation of passwrd.txt
  • Looking for cosmo.jpeg and read its content
  • Read the passwrd.txt file
  • DNS resolution through the hosts file and GET /feed?post=[cosmo.jpeg part] for the exfiltration.

Right before the moment the malware accessed to cosmo.jpeg, some cryptographic library were queried:

It might be related an encryption mechanism, especially with the passwrd.txt file that follows. The content of the passwrd.txt isSikoMode. It may be the encryption password.

Inside Wireshark, we can see the full URI:

Right after the file cosmo.jpeg is accessed by the malware, we can see the passwrd.txt file. It’s

Answer

http://cdn[.]altimiter.local/feed?post=

As we have already seen, the malicious program read the content of cosmo.jpeg and split it in multiple chunks in order to send them inside the post parameter. The exfiltrated content is encrypted using the password SikoMode which is the password inside the passwrd.txt file.

In Cutter, inside the sym.NimMainModule, we can see a reference to RC4 encryption:

By following the execution flow in the main, we can see a reference to RC4. It takes two arguments, the first one being the key and the last one is the plaintext (probably base64 for a better encoding).

Answer

RC4

Answer

SikoModeis the key that we found in thepasswrd.txtfile.

houdini is a method used by the binary to delete itself. It is invoked multiple times during the execution flow, especially if the execution conditions (cosmo.jpeg, internet connexion…) are not met.

To validate this, we can try to decrypt the communication towards the C2. We must wait the end of the exfiltration. This is very very long. I exported all the sniffed packets inside another pcap file (cosmooooooo.pcapng).

Then I ran tshark to extract only the post data and remove the newlines.

tshark -r cosmooooooo.pcapng -Y 'http.request.uri contains "feed?post="' -T fields -e http.request.uri | sed -n 's/.*post=\(.*\)/\1/p' | tr -d '\n' > cosmo.txt

I found this implementation of RC4 in nim: https://github.com/OHermesJunior/nimRC4.git

Here’s a little script in order to decrypt the first C2 communication. It should be the JPEG header once decrypted!

import RC4
import std/base64

var decryptedString: string = fromRC4("SikoMode", "A8E437E8F0367592569A2870BBDD382A1DFBB01A15FC23999D7788C33502AD9256E481B402BDC6BC25167B6478F204C49A9BADD68C4AC2A617437ECCBBA9") #the first GET HTTP

var decodedString: string = decode(decryptedString)
echo "Decoded: ", decodedString
writeFile("cosmo.jpeg", decodedString)

Once compiled, it outputs the JPEG header!

nim c -r --verbosity:0 cosmo.nim
Decoded: JFIFHExifMM*

And the file check:

file cosmo.jpeg

cosmo.jpeg: JPEG image data, JFIF standard 1.01, aspect ratio, density 72x72, segment length 16, Exif Standard: [TIFF image data, big-endian, direntries=13, manufacturer=MM]

I tried for many hours to get the full jpeg back but it was so painful to deal with encoding and break line, even if I had the full C2 communication, I was not able to get the full file back.