Vawtrak Trojan: Bank on it Evolving

Thursday, May 26, 2016

On May 12, 2016, Fidelis Cybersecurity witnessed an update to Vawtrak malware, a banking trojan, spread via an email campaign using subpoena- and lawsuit-related themes.  The configurations observed in this campaign point to an attempt to harvest user credentials when visiting accounts on major financial websites in the U.S. and U.K., such as ADP, Capital One, Citibank, Lloyds Bank, etc. The downloaded Vawtrak malware displays characteristics unlike previously seen variants, including new obfuscation and potential antivirus injection. The full list of targets and details around the technical evolution are discussed in detail below. Further, we're publishing an IDA decoder script to aid fellow researchers.

Vawtrak (aka Neverquest) is a modularized banking trojan active since at least 2013. Banking trojans are malware designed to steal your credentials through various methods (harvesting, keylogging, Man-In-The-Browser, etc.). Historically, Vawtrak has been broken down into “projects” by researchers; the current campaign is referred to as Vawtrak project id: 82.

Vawtrak has been observed being pushed both by Angler Exploit Kit and spam campaigns utilizing many delivery mechanisms.  In this campaign, the malware utilizes a macro document that drops and executes an embedded executable file, the downloader H1N1, which then downloads a pony dll and Vawtrak. It has a larger target list when compared to other banking trojans (See “Project 82 Targets” below), includes a tested and expansive webinject system, and comes with at least five modules that are commonly downloaded in both 32- and 64-bit variety: injecter_(32|64).dll, dg_(32|64).dll, keylog_(32|64).dll, pony_(32|64).dll and bc_(32|64).dll.

Once Vawtrak makes it to disk, it commonly uses the same loader program to inject the AP32 compressed DLL, depending on whether the system is 32- or 64-bit architecture.


1. The strings are encoded using a linear congruential generator (LCG) fed by a psuedorandom number generator (PRNG) (#4 and #5).  The strings in this loader were encoded the same way as the dll strings.

Decoded strings


GET /?id=%0.8X00%0.4X

Host: %s

http:// %s/?id=%0[.]8X01%0[.]4X



2. The traffic pattern generated with these strings is not a normal Vawtrak traffic pattern. Typically, traffic would be generated by the injected dll and not the loader. If the domain resolves, then the loader generates the traffic pattern with swprintf after gathering some information about the system(VolumeID and adapter settings). In the case of this recent and updated version, the parameters passed to swprintf were in the wrong order and caused the loader to crash. This could be some sort of mechanism for trying to track new infections or, possibly, could be used to limit the loader to running only until that domain is activated.


Parameters in wrong order




Parameters fixed


Generated traffic

A Vawtrak sample later delivered by H1N1 on May 16, 2016 did not appear to contain this logic, which suggests that it’s being actively tested during development. However, the May 16 version used the domain found in the loader piece of the May 12 sample as a C2 domain.


3. Both samples contained the string of antivirus names. The loader enumerates the list of running processes, stripping off the ‘.exe’ of each one and then seeing if the name appears in that long string.



















If the string is found, then it sets a flag and immediately begins searching for explorer.exe in an attempt to inject. To test, we spun up a fake Sophos program that appeared to have been injected as suspected. Once the DLL is injected, the malware patches certain functions in memory (CreateProcessInternalW and RegGetValueW) for every process it injects, with the patched in routine looking for Chrome-related objects. We didn’t see any signs of the malware attempting to do anything specific to the injected AV processes, but the functionality could be added in the future to disable or attempt to circumvent them in some way.

Vawtrak is one of the more advanced banking trojans used by cybercriminals today. The observed changes to the malware demonstrate continued development to circumvent detection and thwart AV protection mechanisms. Since Vawtrak began to gain strength late 2015, its target list has grown steadily.  As Vawtrak development continues, we expect the target list to expand and additional techniques to be leveraged to infect systems. 


View the IOCs on GitHub



12may2016 Vawtrak

MD5: 5238cd34caae600b3f592e2595aa6949



dringeraout[.] com/rss/feed/stream










16may2016 Vawtrak

MD5: 6fad86a0fcc912f32474f6c7a86fe37a

















Project 82 Targets



IDA python script for decoding unpacked loader and dll strings

def PRNG(seed):

            seed = (seed * 0x41c64e6d) + 0x3039

            return (seed & 0xFFFFFFFF)

#Unpacked loader - Md5: 3678dc31a2be281fa7ed178d535364fb

for addr in XrefsTo(0x401a1b, flags=0):

#Unpacked dll - Md5: 54db3f86aabaf3e87016bcff923dba41

#for addr in XrefsTo(0x10007df8, flags=0):

            addr = addr.frm


            addr = idc.PrevHead(addr)

            while GetMnem(addr) != "push":

                        addr = idc.PrevHead(addr)


            #Get first param pushed which is address of domain

            data_addr = GetOperandValue(addr,0)

            init_seed = Dword(data_addr)

            data_addr += 4

            xork = Dword(data_addr)

            data_addr += 4

            length = (init_seed ^ xork) >> 16

            out = ""

            for i in range(length):

                        init_seed = PRNG(init_seed)

                        out += chr((Byte(data_addr) - (init_seed & 0xFF)) & 0xFF)

                        data_addr += 1

            if out[-2:] == '\x00\x00':




addr = 0x1000f8a0

for i in range(10):

            data_addr = Dword(addr)

            addr += 4

            init_seed = Dword(data_addr)

            data_addr += 4

            xork = Dword(data_addr)

            data_addr += 4

            length = (init_seed ^ xork) >> 16

            out = ""

            for i in range(length):

                        init_seed = PRNG(init_seed)

                        out += chr((Byte(data_addr) - (init_seed & 0xFF)) & 0xFF)

                        data_addr += 1



-- Jason Reaves, Threat Researcher