Anti-Debugging Techniques from a Complex Visual Basic Packer

Introduction

As we described in our previous post, one of the latest trends for the attackers is to leverage the ISO files in order to reduce detection chances. This technique has also been used by a recent Hawkeye spreading campaign.

“Hawkeye Keylogger” is an info-stealing malware for sale in the dark-web. Anyone can  easily subscribe to the malware service by paying a fee. It has been in continuous development at least since 2013  and the malware authors behind Hawkeye have improved the malware service adding new capabilities and techniques. It can collect credentials from various applications, mostly email clients, web browser and FTP clients, and send them to the crooks via various protocols such as FTP, HTTP, and SMTP.

So, our Cybaze-Yoroi ZLAB decided to take a look at this recent Hawkeye attack, tacking its anti-analysis protection and the anti-debugging techniques enforced by the Visual Basic packer used by the crooks.

Technical Analysis

The delivered file is an ISO image. Inside of it, there is a bat file, but actually is a well formed PE file. So, we can extract the “bat” file and replace its extension in “exe”.

Figure 1: Fake .bat file inside the ISO archive
Hash32951a56e3fcd8f5b006c0b64ec694ddf722eba71e2093f7ee90f57856941f3d
ThreatHawkey Spyware
Brief DescriptionHawkey Spyware inside a Visual Basic Packer
Ssdeep12288:GVwYvwrMkE9LfRUXkpW7zGidwY/rwxOp8mH:COrI9zRUJfGCfzw0

Table 1: Information about the PE file inside the ISO image

The ISO file has low AV detection rate, but only by extracting the executable from  the ISO image, the rate raises:

Figure 2: AV Detection of the ISO compressed file (left) and of the extracted file (right)

The PE file is packed with a Visual Basic 5.0 stub. It has the duty to protect the core of the malware and complicate the analysis:

Figure 3: Visual Basic packer evidence

As seen above, the malware is written in Visual Basic 5.0. So it is possible to decompile the malware through the use of the ad-hoc decompilers.

Figure 4: Visual Basic code decompilation in P-Code

The decompiled code has been translated in P-Code and it is quite obfuscated in the same way. The only solution to obtain more information about the infection mechanisms is to debug the program.

The first trick to complicate the analysis is to dynamically create a new memory section where inject some code, through the use of the “VirtualAlloc” function. The malware decodes some a piece of code, and choose a random new virtual address space to alloc memory, in this case “0x00260000” loaded into the EAX register.

Figure 5: Memory allocation through the VirtualAlloc API

The GetTickCount Anti-Debug Technique

After the context switch inside the new allocated area, the malware adopts the well known “GetTickCount()” anti-debug technique. According to the MSDN documentation, GetTickCount retrieves the number of milliseconds that have elapsed since the system was started, up to 49.7 days. This API call is used by the malicious actors to retrieve the time of the execution of the process, and if it is higher than a preset threshold, the malware terminates its execution:

Figure 6: GetTickCount routine a new address space

The first malicious action of the created address space is the invoking of the GetTickCount API and the result is:

Figure 7: GetTickCount result in EAX register

The result of the GetTickCount function is stored in EAX register. After doing some other decrypting operations, the malware invokes it another time.

Figure 8: GetTickCount subtraction anti-debug trick

After the second invocation of GetTickCount, there is immediately the subtraction of the two values and it is placed in EAX register. The next instruction is a comparison between the EAX register and a preset threshold value, “0x5DC”, which is 1500 in decimal representation. According to the Microsoft documentation, the resolution of the GetTickCount function is 10ms, thus we can deduce that the decided threshold by the cyber criminal is 15 seconds. After understood the trick, it quite easy to bypass and go on to analyze the sample.

Figure 9: ShellExecute routine to run the payload

The malware allocates another memory space to write an entire file with the MZ header and it is opened through the “ShellExecute” API function. Dumping the process in this moment, another piece of code hidden in a resource, which did not exist before the anti-debug trick, emerges:

Figure 10: Resource comparison between the original exe and the self-modified exe

As shown in the above figure, the original file (on the left) presents as resources only the icons and the manifest, instead the self-manipulated file presents a resource called “RCData” with a resource named “__”. It is the encrypted final payload.

Figure 11: Malicious resource retrieving routine

In order to protect itself and to make more difficult the analysis, the malware respawns itself through the “CreateProcessInternalW” API call:

Figure 12: Execution routine of the final payload

Now the real payload is ready to be self-decrypted with a custom internal routine. 

Figure 13: Decoding routine of the final payload

After the decryption routine, the malware copies this new code into another piece of memory through the “memcpy” function. Moreover, in order to validate the correct extraction of the payload, the malware checks if the first two bytes of the memory spare are “0x5A4D” which is “MZ” in ASCII code.

Figure 14: Validation check of the correct decoding of the final payload

Dumping the file, the real payload is unveiled.

The Payload

The extracted payload is a PE file compiled in .NET C# language with the following static information:

Hasha3aa6e220591f05f4e2ecc4f4741ac6b6715ebb2b5c42c2b7bb52142c54be30b
ThreatHawkey Spyware
Brief DescriptionHawkey Spyware obfuscated payload
Ssdeep6144:HuXT5iKKhhSHCMA2g22fB1YbcLetS7iz+K3hk:OXtxc/r1fXrwgil3h

Table 2: Static information about the final payload

The payload sample is obfuscated with the .NET Reactor tool, but the cleared version can be easily restored:

Figure 15: Usage of .NET Reactor obfuscator evidence

Below some static information of the final payload is reported:

Hasha848c84a1306ea7cc4704eced4067db1012c0bf1b9b65f8c04a8379d71464eaa
ThreatHawkey Spyware
Brief DescriptionHawkey Spyware clear payload
Ssdeep6144:37iz+K3hkCAg3JhmkuEFZ+1WjsroyGh0DBabr:Lil3hdhmOF

Table 3: Static information about the cleared version of the final payload

Due to the fact that the payload is written in .NET framework, it is possible to debug the code in order to retrieve all the details of this new sample. The debugging of the sample lets emerge the attribution of the malware, HawkEye.

Figure 16: Recurrent string decryption routine through the usage of Rijndael algorithm

Every sensitive information, string or other information  is encrypted through Rijndael algorithm, as shown in figure 16. Before starting any operation, the malware tries to make a simple evasion trick. It retrievers the username of the victim machine and it compares this one with a series of usernames hardcoded. These usernames are the classical ones adopted by the sandboxes and if one of them is matched, probably the malware is run inside a virtual machine.

Figure 17: Sandbox evasion trick

After the simple check, the info stealer starts to perform its malicious operations. The first malicious operation is the persistence mechanism adopted by the malware:

Figure 18: Persistence mechanism

The persistence is guaranteed through the setting of the classic registry key “HKCU\Software\Microsoft\Windows\CurrentVersion\Run” with the value “C:\Users\Admin\AppData\Roaming\MyApp\MyApp.exe”, having already copied itself in this path. However, it’s important to say that if the malware is launched from the original wrapper, it copies in the “MyApp” path the entire executable, because the payload is executed inside the wrapper process as a thread; instead if only the final payload is executed, only this part is stored. 

Figure 19: Task Manager disabling

A particular auto-protection mechanism adopted by the malware is the disabling the possibility to open the Task Manager process from the user, through the setting of the highlighted registry key in the Figure 19. At this point the malware can start the information stealing routines.

Figure 20: Password retrieving routine from Internet Explorer

The first information retrieved is the password stored inside Internet Explorer through the routine described in the above figure. This is only the starting point: it retrieves all sensitive data and login data from a large list of browsers. A little example is shown in the following figure:

Figure 21: Piece of the browser list harvested by the malware

Below, the complete list:

  • Google Chrome
  • Yandex
  • Comodo Dragon
  • Cool Novo
  • Chromium
  • Torch Browser
  • 7Star
  • Amigo
  • Brave
  • Cent Browser
  • Chedot
  • Coccoc
  • Elements Browser
  • Epic Privacy
  • Kometa
  • Orbitum
  • Sputnik
  • Uran
  • Vivaldi
  • UC Browser
  • Flock Browser

In the same way, the malware looks for other credentials coming from other services, like CoreFTP, FileZilla and JDownloader. The last information stolen by the malware is the registered email accounts on the victim machine. The searched email clients are:

  • Outlook
  • SeaMonkey
  • Postbox
  • Thunderbird

Now, we wanted to deepen the password gathering routine of the malware on the Microsoft Outlook application. So, we created a fake account and we logged on the Microsoft email account software. 

Figure 22: Registry key where it is stored the Microsoft Outlook client user configuration

Themalware retrieves a particular registry key: “HKCU\Software\Microsoft\Windows NT\CurrentVersion\Windows Messaging Subsystem\Profiles\Outlook”. Inside of it is stored the configuration of the Microsoft Outlook user profile.

Figure 23: Outlook password decryption routine

The method “smethod_50”  in figure 23 shows how is simple to decrypt the password saved in that registry key: it is enough retrieve the array of bytes and use it as parameter, together with the CurrentUser DataProtectionScope,  to the static method provided from the .NET framework, “ProtectedData.Unprotect()”. After that, the harvested information are collected in a list, ready to be sent to the server.

Figure 24: Creation of the list of the gathered accounts

The last action is properly the preparation to send the information to the recipient. As the classic HawkEye malware, the communication protocol designed to transmit the stolen info is SMTP. For this reason the malware needs to use the API provided by the .NET framework in order to  instantiate an SMTP client. Debugging until the right point, the malware configuration are revealed:

Figure 25: SMTP client account configuration

Conclusion 

Hawkeye is nowadays a well known threat. The security firms analyzed in an excellent way the malware and all the infection chain, but this sample, like our latest ones, has the peculiarity to be protected by a complex and evasive packer. 

In the last two posts we saw a tough Delphi packer to analyze, but also this one has some points to analyze that make challenging  the reverse engineering process for the analyst. In the end, we were able to dissect all the malware chain revealing the threat actor exfiltration address.

Indicators of Compromise

Hashes

  • a3aa6e220591f05f4e2ecc4f4741ac6b6715ebb2b5c42c2b7bb52142c54be30b
  • ad688023760c7f54fe19ef956ca6407bd9f0512d4b019ef4327cfbc63c496309
  • 30349db52f9a502056062354dfd4040dd392d3aaf41652a739de1950e7bc9bd4
  • 32951a56e3fcd8f5b006c0b64ec694ddf722eba71e2093f7ee90f57856941f3d
  • 67a052d6be1368bb1ec29fea377ae5f529ae539ec0114a2c4a70f83009c6db36

C2 (smtps):

  • controlpanel@kaptainlogs.com
  • us2[.outboind[.mailhostbox[.com
  • 208.91.199.225

Persistence Mechanism:

  • Setting of the registry key “HKCU\Software\Microsoft\Windows\CurrentVersion\Run”

Yara Rules 

rule ISO_Dropper_HawkEye_201907 {
meta:
	description = "Yara Rule for HawkEye ISO dropper"
	author = "Cybaze - Yoroi ZLab"
	last_updated = "2019-07-08"
	tlp = "white"
	category = "informational"
strings:
	$s1 = "PowerISO" ascii wide
	$s2 = "MSVBVM60.DLL" ascii wide
	$h1 = {76 B6 45 77 B6 4C 7D B9} 
	
condition:
	all of them
}

rule Visual_Basic_Loader_HawkEye_201906 {
meta:
	description = "Yara Rule for Visual Basic Loader and its payload (HawkEye)"
	author = "Cybaze - Yoroi ZLab"
	last_updated = "2019-07-08"
	tlp = "white"
	category = "informational"
strings:
	$h1 = {52 94 5B C2 56 17 AB 6E 9D 6D F0}
	$h2 = {13 41 63 ED 92 6B DF 6B 36 CD F8}
	$s1 = "MSVBVM60.DLL" ascii wide
	
condition:
	uint16(0) == 0x5A4D and all of them
}

This blog post was authored by Luigi Martire, Antonio Pirozzi and Luca Mella of Cybaze-Yoroi Z-LAB