By Nick Lister and Holger Unterbrink, with contributions from Vanja Svajcer.

News summary

  • Cisco Talos recently discovered a new campaign targeting video game players and other PC modders.
  • Talos detected a new cryptor used in several different malware campaigns hidden in seemingly legitimate files that users would usually download to install cheat codes into video games or other visual and game modifications (aka "mods").
  • The cryptor uses Visual Basic 6 along with shellcode and process injection techniques.
  • We have a full analysis of the VB6 header of one of the samples used in these campaigns and provide a detailed walkthrough for security analysts.

What's new? The cryptor in this campaign uses several obfuscation techniques that makes it difficult to dissect, and could pose a challenge for security analysts not familiar with Visual Basic 6. Our analysis provides insight into the adversaries' tactics and how the crypter works in detail. These types of attacks are a return to form for classic virus campaigns — video game players are no strangers to trying to avoid malicious downloads while trying to change the game they're playing.

How did it work? Video game players may opt to download certain cheats or modifications (aka "mods") to change the way some games are presented. The adversaries use these gaming and OS modding tools to attach hidden malware to infect their victims. We have seen several small tools looking like game patches, tweaks or modding tools, but backdoored with malware obfuscated with this cryptor.

So what?

Defenders need to be constantly vigilant and monitor the behavior of systems within their network. As workers continue to operate remotely during the COVID-19 pandemic and mix work with their private computer usage, enterprises are even more likely to be attacked by compromised personal PC equipment belonging to their employees. Employees will sometimes download modding tools or cheat engines from questionable sources to tweak their PC or games running on the same machine they use for their job. This is a serious threat to enterprise networks.


Many of these campaigns start with advertisements or "How To" videos on YouTube or other video game modding-related social media channels. The screenshot below shows an example of one.

Unfortunately, these tools are providing a bit more than the promised tweaks or cheats, most of them are backdoored with RATs. The one above installs XtremeRAT, a longstanding information stealer, for example.

Technical details
The campaign described above used the Viotto Binder tool from Breaking Security to join two files which got dropped to %AppData%/Local/Temp. One is called "Servidor.exe" ("5ff836d3f691c9e478bb86f7a0b216082062c747e6e3faa85df246ef5a5bfb32"), a sample packed with the VB6 cryptor which acts as a loader for XtremeRAT. We will describe this in more detail below. The Servador.exe file is copied to C:\Windows\SysWOW64\Windows\taskhost.exe. The other file dropped is a sample named "GameLoader.exe" ("e2b6de1933bbfbbab5e7b6c05e4529d4cef7473574281ac161a49e87d149b135") which is a small .NET program with a GUI you can see in the image above.

VB6 cryptor/loader analysis
We are using the sample 4533e1cd680b6be739fa6c12cbfc1b0bb96994a4f6355f26f2 for our deep dive into the VB6 cryptor. This is a sample packed with the aforementioned cryptor, but with a simple payload.

When we looked at it, the file was not listed in VirusTotal. And when we ran it against common antivirus software, we saw results similar to what's shown in the sandbox image below. It looked malicious at worst and suspicious at best. Either way, it was difficult to classify. Today, you can find it on VT, but it still has a lot of generic and false classifications, most based on behaviour and machine learning indicators.

For anyone looking to dive deeper, there's no great options. The common PE tools show it is a VisualBasic 6-based executable. It only imports the msvbvm60.dll and several VB6 functions. Next, we'll load it into VBdecompiler. This software decompiles VB6 code and includes options to merge the decompiled VB6 code into the assembler view. This is quite helpful when debugging VB6 samples.

It looks like it has a FormLoad event in Form1, which is usually code that gets executed first. Unfortunately, VBdecompiler does not provide any clues which class is initialized at address 0x4DD830 or which method is called, exactly. We either need to perform the complex static analysis, which you can find in the "Static analysis of the VB6 header" section, or we just break at that address in our debugger and check out the destination of the call.

The code jumps to the address 0x52457D, and looking around in VBdecompiler, shows it is the "A™…" method in the clsComplexDataConsumer class, which is executed first.

The clsComplexDataConsumer class exists in all samples we looked at and it always looks similar to the figures above and below. The most obfuscated name is usually the start method ("A™…"). The rest are helper procedures.

The start method first reads its own PE file data from disk:

Then, we have a couple of data manipulation operations and the data is handed over to sub_4DD892.

00526A14 | E8 796EFBFF | call sub_4DD892

This is the first time we see a kind of decoded PE header, but it is invalid. This is likely built out of the previously mentioned operations, but we haven't looked deeper into this.

Another interesting call in the 'A™...' method is:

loc_00527050: var_8484 = Proc_2_0_4DDA61(var_1C)

This is a large method with more than 60,000 lines in the decompiled view.

This method is also obfuscated with the Chr$(n) function and several string concatenations, which we have already seen in the start method. With deobfuscated strings, it looks like this:

After rebuilding encrypted data strings, it decodes them via the Proc_2_1_523F36 procedure:

This is done several times. Then, it executes the decoded shellcode via:

loc_00521B91: var_12160 = CallWindowProcA(var_1215C)

The code at 0x8169A0 is then jumping (calling) into the shellcode at offset 0x8169F4 as shown below. Due to the skipped bytes in between, the debuggers disassembler fails decoding it before the jump (call) is taken.

All the "normal" calls are executing typical shellcode that resolves API function addresses — the interesting stuff happens at the 'call eax' ones.

At 'call eax,' the shell code calls the typical process injection functions as shown below. You can go to the last one or break on ResumeThread and dump the new process (payload).

The following is a list of API calls by the Shellcode 'call eax' instructions:

  • eax=<kernel32.VirtualAlloc>
  • eax=<kernel32.VirtualAlloc>
  • eax=<kernel32.VirtualAlloc>
  • eax=<kernel32.VirtualAlloc>
  • eax=<kernel32.VirtualAlloc>
  • eax=<kernel32.VirtualAlloc>
  • eax=<ntdll.RtlMoveMemory>
  • eax=<ntdll.RtlMoveMemory>
  • eax=<kernel32.CreateProcessW>
  • eax=<ntdll.NtUnmapViewOfSection>
  • eax=<kernel32.VirtualAllocEx>
  • eax=<kernel32.WriteProcessMemory>
  • eax=<ntdll.RtlMoveMemory>
  • eax=<ntdll.RtlMoveMemory>
  • eax=<kernel32.WriteProcessMemory>
  • eax=<ntdll.RtlMoveMemory>
  • eax=<kernel32.WriteProcessMemory>
  • eax=<ntdll.RtlMoveMemory>
  • eax=<kernel32.WriteProcessMemory>
  • eax=<kernel32.GetThreadContext>
  • eax=<kernel32.WriteProcessMemory>
  • eax=<kernel32.SetThreadContext>
  • eax=<kernel32.ResumeThread>

This means the quick and dirty unpacking method for this packer is to break on CallWindowProcA until it points to non-library code, then break on ResumeThread and dump the suspended process. The dumped PE from this sample did not need to be fixed — it was a valid PE when loaded into RAM by the packer. This unpacking method does not require any changes after dumping the unpacked sample.

Static analysis of the VB6 header
The quick dynamic analysis is fine, but debugging the file showed a lot of threads started early at runtime, and the sandbox report showed several artifacts that might be decoys. There are also several suspicious strings like 'C:\windows\system32\wmp.oca', which we haven't seen in the quick analysis above. An .OCA file is a binary file that functions as an extended type library file and a cache for the custom control file (.OCX). It looks like the Form is using the Windows Mediaplayer control, but VBdecompiler didn't show it in form view. The static analysis later on confirmed it is part of the Form1 form of the sample. The latter also likely explains why it starts so many threads at runtime.

There are still several questions left unanswered, so next, we'll dig into the VB6 startup routines. We haven't seen any TLS tricks or anything similar up to now, which means we can start with the VB6 header. describes the VB6 initialization process as:

"... If the aSubMain field is present, the ProcCallEngine function will launch the function located at the address specified in that field; that is the main function in the project, and its value is not equal to 0 if there is a module with a "Main"function in the .exe file. If there is no such function, then the first form will load, and control will be passed either to the Form_Initialize function (if it exists) or to the Form_Load function (if the former doesn't exist)..."

In our case, aSubMain is NULL.

So, we'll look at the event handler for Form1 and see where it points to. To see the VB6 header information, you need to load the vb.idc script from Reginald Wong and Bernard Sapaden after auto analysis into IDA.

Form_Initialize points to NULL, so the address in Form_Load is the address pointing to the code which will be executed by the VB6 virtual machine at object initialization time. Looking at the decompiler output, we can see that 0x4DD7B4 is the expected Form_Load routine.

Unfortunately, VBDecompiler can't decompile the first line (0x4DD830) correctly and we don't know what it exactly calls here. IDA Shows us that the code initializes a new Object at 0x4DD80D.

We can see Pub_Obj_Inf4_wRefCount is pointing to the clsComplexDataConsumer class object info.

Its Optional Object Information header is pointing to 0x52457D. This is the method with the obfuscated name starting with "A™…" shown below.

The static analysis has shown that the "A™…" method is the start of the cryptor code.

The event handlers of the other controls (Picture1, Command1, WindowsMediaPlayer1) are similar to the one for the Picture1 control shown below. They are not executing any routines other than the default ones, so it seems they were just decoys. The different samples packed with this crypter have different controls. Therefore, it is also possible they are just there to make the sample look like a valid VB application and make sure the samples have a high enough diversity to trick antivirus softwares' detection algorithms.

The attackers in this case used video game-modding tools to trick users into executing malware droppers. This goes to show how dangerous it is to install random software from questionable sources. With the work from home trend not likely to end any time soon, there's a highly increased use of private PC equipment to connect into company networks — this is a serious threat to enterprise networks. It is important that companies ensure their workers are only downloading software from trusted sources. Due to the huge amount of documentation of obfuscation techniques, plus easy and cheap access to cryptors, the common threats we see today are more sophisticated than they've been in the past. This threat used a complex VisualBasic-based cryptor to hide its final payload. The dropper injected code into a new process to hide its final payload against simple anti-malware tools. The majority of malware is constantly improving its infection techniques. The adversaries combine clever techniques to make detection harder. It's more important now than ever to have a multi-layered security architecture in place to detect these kinds of attacks. It isn't unlikely that the adversaries will manage to bypass one or the other security measures, but it is much harder for them to bypass all of them. These campaigns and the refinement of the TTPs being used will likely continue for the foreseeable future.

Additional ways our customers can detect and block threats such as these are listed below.

Advanced Malware Protection (AMP) is ideally suited to prevent the execution of malware used by threat actors at questionable domains.

Cisco Cloud Web Security (CWS) or Web Security Appliance (WSA) web scanning prevents access to malicious websites and domains, and detects malware.

Email Security can block malicious emails sent by threat actors as part of phishing or other social engineering campaigns.

Network Security appliances such as Next-Generation Firewall (NGFW), Next-Generation Intrusion Prevention System (NGIPS), andMeraki MX can detect malicious activity associated with questionable domains.

AMP Threat Grid helps identify malicious binaries and build protection into all Cisco Security products.

Umbrella, our secure internet gateway (SIG), blocks users from connecting to malicious domains, IPs, and URLs, whether users are on or off the corporate network.

Open Source Snort Subscriber Rule Set customers can stay up to date by downloading the latest rule pack available for purchase on




Dropped SHA256 verified samples: 0bfb087059a4c04cc55d8b691f3c6297e22f6e94b0354265a06382d9e725ee16