Author: Jakub Kroustek

In this article, we focus on analysis of a 32-bit WinPE sample with MD5 sum C8F3C24F123D851F57AFF21958ADAC76. Its goal is to steal credentials from a running web browser. This sample is interesting because it uses several different layers of its protection – obfuscation, encoding & encryption, code hiding, proactive defense against AV software, and other similar techniques.

The malware has been developed in the not-so-common AutoIt scripting language. The implementation of most of these techniques is publicly available for several years directly in the AutoIt language, e.g. RunExeFromMemory, RunBinary, SetDebugPrivilege, AES. The author of this malware simply reused and connected the existing modules together and created a tougher-to-analyze sample.

The syntax of the AutoIt language is similar to BASIC. The main advantage of this language is its flexibility and support of rapid application development by using built-in functions. Finally, the AutoIt scripts can be compiled into stand-alone executables with no DLL dependencies. In other words, it is very easy to distribute such applications. Those are probably the primary reasons why AutoIt is heavily misused by malware writers in recent years, see comments from our colleagues 1, 2. This is interesting because AutoIt does not belong in a group of the most popular programming languages. According to the recent research, the most popular programming languages are still C, Java, and PHP.languages

Analysis

Executable files generated via the official Aut2Exe application or via the online compiler are not compiled into a native executable code, as we are used to in languages like C. In this case, the resulting executable file contains an interpreter of the user’s AutoIt script. This script is not stored as plain text, but as a pre-compiled code, which can be detected via sequence AU3!EA06. The pre-compiled code is interpreted by the interpreter during run-time. This code is usually stored at the end of the executable file in the so-called overlay. However, in our case, the script is stored in the manifest resource (type 24) of the executable file.

resources_2By the preliminary analysis, we can conclude that this sample is not packed (e.g. UPX, PECompact). Normally, we would use our retargetable decompiler for code analysis; however, there exists another decompiler that is focused directly on AutoIt executables – Exe2Aut (we used version 0.10). The decompilation process was flawless and it generated a file with 40 user functions. However, the function and variable names are obfuscated:

We noticed that the obfuscation process has been either badly configured or done in a rush because some names still contain well-readable parts in a suffix, e.g.:

Furthermore, most of the string literals are stored as encrypted strings and they are decrypted during run-time in function isdmecxgijvxvjlgiriw(). The decryption engine is stored as a pre-compiled native code (x86) within the script. This technique is used multiple times by the author in this sample. We used our retargetable decompiler for decompilation of this native code and we found out that the Corrected Block TEA (XXTEA) cipher has been used for this purpose. Therefore, we will refer to this function as XXTEA_Decrypt(). The first argument passed to this function is an encrypted string and the second argument is a key for a particular string. The code of the decryption engine is stored as string "0x5557565383EC1C8B4C24348B4424308B18BA3400...", it is dynamically allocated in memory as executable code, and function XXTEA_Decrypt() passes the encrypted string and key to this code. This is done via AutoIt function DllCall() that invokes WINAPI function CallWindowProc(), which finally passes control to this native code where the decryption of a given string is done.

To reconstruct all the strings, we simply re-used this function and replaced calls to it with decrypted strings. After some function and variable name replacing, we were able to analyze the behavior of this sample. Here is the de-obfuscated result for the example listed above:

AV Defense

The very first thing the malware does is a trivial defense against AV solutions. Well, actually only one of them. The sample tries to detect a running instance of the AVAST Antivirus. If found, it falls asleep until the AVAST’s behavioral scan is finished, just like a polar bear hibernating during winter.

Get Debug Privilages

During the analysis of this sample, we found that it consists of multiple AutoIt snippets that are available online. This function is available here. It basically tries to obtain the flag SeDebugPrivilege for the sample’s process. This is achieved via a sequence of WINAPI-function calls OpenProcessToken(), LookupPrivilegeValue(), and AdjustTokenPrivileges(). This privilege is necessary for interaction with other processes that is done in other functions.

Built-in Decoding and Decryption Functions

Before we discuss other behavior of this sample, we must mention another native code stored within the script (similarly to the XXTEA decrypter). It belongs to the Base64 decoder. However, this is nothing new because this AutoIt implementation is publicly available for a long time.

This decoder has only a single purpose – to decode another piece of native code that is embedded in the script as a Base64 string "magAAIcA24PsHI...sxecNisBUFjDwAA="(17.236 characters in total). This code is decoded via the Base64_Decode() function and some other minor modifications are performed. We decompiled the resulting code and found out that this code implements the AES. After some search, we found the original AutoIt source as well. The usage of this AES decrypter is described in the following section.

Extract Payload

During the execution, the process extracts the payload (i.e. pre-compiled native code) from its WinPE resource called BWnbooPAIGeTQvuRFDpP. This payload is hidden in resource type 127 and it is 154.000 bytes long. In the following figure, we can also notice another suspicious resource called MFabcRoVpJoguel that is used later.

resources_3
The extraction is done by using other WINAPI functions: FindResourceW(), SizeofResource(), LoadResource(), and finally LockResource().

The author takes an extra caution about protection of this code against analysis because it is stored in an encrypted form. Therefore, it has to be decrypted via the previously mentioned AES decrypter before it can be used. The decryption key "a3B4e59v0neQMDH5" is stored in the script, while the initialization vector (IV) is stored in the first 16 bytes of the payload. The CBC mode has been used for encryption.

After decryption, the size of the payload is 153.984 bytes. However, the payload is still not in its “naked” form because it is compressed and it has to be decompressed in the next step. The script does not contain any decompression algorithm. However, this algorithm is stored separately in another WinPE resource file – do you remember the MFabcRoVpJoguel resource that we mentioned earlier? This resource contains 35.168 bytes of native machine-code that implements the decompression algorithm. Maybe you already guessed that it is once again stored in an encrypted form – this time the XXTEA algorithm has been used (the same algorithm that has been used to obfuscate the strings). After the decompilation of the XXTEA-decrypted code, we detected that it is the LZMA algorithm. We also found that this native code (as well as several AutoIt functions that are responsible for calling this code) are also re-used from an existing code.

Afterwards, the payload can be finally decompressed and executed. The complete process is summarized in the following figure.

cg

The size of the decompressed payload is 623.104 bytes. As we can see, it is another WinPE executable file. In other words, the original sample is dropper that drops another malicious sample with MD5 sum A030408D3492D7EACB7A5B3119DB8195.

decompressedPayload

Execution of the Payload

At the very beginning of the decompiled script, we can notice another well-known native code for AutoIt – function RunPE() that is based on this VisualBasic implementation. However, this function is not called anywhere in this script. Instead, to execute the payload, the author used function RunBinaryInMemory(). Once again, it is an existing implementation. We use the original step-by-step description made by the author of this function back in 2009:

  • Start your script.
  • Create a new process by using the CreateProcess() function with the CREATE_SUSPENDED flag.
  • Use the GetThreadContext() function to fill the CONTEXT structure.
  • Read and interpret the passed binary.
  • Allocate enough memory for the new module inside the victim process.
  • Simulate the loader. Construct the new module (load) in place of the allocated space.
  • Make use of the mentioned CONTEXTstructure. Change entry point data and ImageBaseAddress data.
  • Resume the execution.

Shortly, the script creates another process with the same name as the script’s process (by using WINAPI function CreateProcessW()). In the next step, content of this newly created process is rewritten by content of the payload ( GetThreadContext(), VirtualAllocEx(), WriteProcessMemory(), ReadProcessMemory(), and SetThreadContext()). This is done in memory without any patching of files. Afterwards, the execution of the new process is resumed ( ResumeThread()). Finally, the original script exits.

Therefore, the simplified behavior of the script is:

Behavior of the Payload

The payload (i.e. dropped application) is not packed or somehow protected against analysis. It seems that its author took all obfuscation effort into protecting the dropper and, therefore, we are able to decompile the machine code of the payload. The application was written in MS Visual C++ and it refers to itself as version "13.2" . The file is linked with the libcurl library version 7.19.5. However, it seems like a cover maneuver because it does not use any libcurl functions for remote communication. We may also notice several Portuguese strings like "Copia do html inteiro feito com sucesso!", or "Copia do html inteiro feito com sucesso!". That gives a clue about the origin of this malware.

After its execution, the payload tries to open an existing mutex called DynGateInstanceMutexS. This mutex is used to ensure that only one malware instance runs at any time. If the mutex is already set, the application immediately exits. Otherwise, it enumerates all the running processes and tries to find any process that is not in the following list of system processes:

If it finds any other running process, then such a process is opened via WINAPI function OpenProcess(). Furthermore, it allocates new memory space within this process via VirtualAllocEx() and it injects itself into this new memory place by using function WriteProcessMemory(). Finally, it executes this code as a new thread ( CreateRemoteThread()). If the injection has been successful, the current process exits. Otherwise, it tries to find another victim.

The injected code contains multiple DLL libraries within its .idata section. There are four hidden files in total. These files are probably masked because their first bytes (i.e. MZ magic byte denoting WinPE file) are stored with modifications. These modifications of the first byte are fixed during run-time as well loading of these libraries. We can see the original file in the first figure and the hidden files in the following ones.

MZ_1 MZ_2 MZ_3 MZ_4 MZ_5Now, we get closer to the main functionality of this malware – it tries to steal user’s credentials for certain websites like Facebook or Hotmail via injection of malicious code into a running web browser. The three most common browsers for Windows are “supported” – Internet Explorer, Chrome, and Firefox. The process of stealing differs a little bit for each browser, but the approach is the same. We illustrate it on Firefox. The following code is injected into Firefox’s process firefox.exe:

In this case, the malicious code has been injected into the Firefox’s process. It tries to open Firefox’s system library nspr4.dll (the back-up plan is library nss3.dll). Afterwards, it gets the address of function PR_OpenTCPSocket() from this library and places a hook on this function (i.e. user function hook_init()). The same applies to other Firefox’s functions for manipulation with sockets: PR_Write(), PR_Read(), and PR_Close(). The function hooking works this way: whenever the original function is called, the malware’s routine is executed instead of it. However, the malware tries to stay hidden and it executes the original function right after its own routine finishes. Therefore, the user has no clue that something is wrong between him and the remote server.

The function PR_Write() is used for writing data into a socket, e.g. sending a request to a particular web server. One of its arguments is a buffer with user’s data (request). Whenever such a request is send, the malware intercepts it via its function hook_write() . This function parses the content of GET, HEAD, POST, and PUT HTTP requests, filters out uninteresting requests (requests for pictures, videos, etc.), and it is specially interested in login details, configuration details, and other credentials. It especially monitors access to web pages www.facebook.com/login.php, login.live.com/ppsecure, and hotmail.com.

Whenever it finds something interesting (e.g. a login and password), such information is send to the hard-coded remote IP address 75.102.25.190 where the attacker logs this information from all victims. The sending is done via the XML format that is send to port 80 (HTTP) of the aforementioned server. It also sends information about the target URL, version of malware, browser, user ID, operating system, etc. Afterwards, the malicious code invokes the original function PR_Write(). The same applies to the hook of PR_Read() except that the hook calls the original function first and parsers its results (i.e. a response from server) afterwards. An example of sensitive information send to the attacker:

The following XML is send to the remote server via this message:

Finally, the application copies itself into the following executable files with predefined names: %Application Data%\25f5093e and %Application Data%\7c71538a and also a file with a randomly generated name and location: %Application Data%\{eight random chars}\{another eight random chars}.exe. The last one is also registered in Windows registry in order to survive system reboot and automatically start during Windows startup.

As we can see, this sample does not actively try to infect other devices; it only stays on the already infected systems. The infection is done via distribution of the original sample and its (accidental) execution by the user. Therefore, it is always a good idea to be protected by AVG.