Introduction
This post is about a malware I analyzed in the last few days:
- Sample and IDA Db
- Password:
infected
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:
Attira.xlxs
: base64 encoded file.San.vst
: base64 encoded file.Pensa.vmw
: binary file.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
isDESKTOP-QO5QU33
COMPUTERNAME
isNfZtFbPfH
COMPUTERNAME
istz
COMPUTERNAME
isELICZ
- 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:
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 structIJzlfMsjjUAgSIaNXoCAh
: Wrapper forGetProcAddress
QFNJvesbypwxcgOBAIt
: Wrapper forVirtualProtect
KRYCFcgmvVbQHOKWFZ
: Wrapper forNtUnmapViewOfSection
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:
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.