Security Technology

Banking Trojan Techniques: How Financially Motivated Malware Became Infrastructure

Clock Icon 10 min read

This post is also available in: 日本語 (Japanese)

Executive Summary

While advanced persistent threats get the most breathless coverage in the news, many threat actors have money on their mind rather than espionage. You can learn a lot about the innovations used by these financially motivated groups by watching banking Trojans.

Because attackers constantly create new techniques to evade detection and perform malicious acts, studying monetarily motivated malware can help defenders understand threat actor tactics and protect organizations more effectively. Some of the banking Trojans described here are historically known for being financial malware, but now they’re primarily used as infrastructure to deliver other malware. Which is to say, by preventing techniques used by banking Trojans, you can also stop other types of threats.

We’ll survey techniques used by notorious banking Trojan families to evade detection, steal sensitive data and manipulate data. We’ll also describe how those techniques can be blocked. These families include Zeus, Kronos, Trickbot, IcedID, Emotet and Dridex.

Palo Alto Networks customers are protected from such attacks using Cortex XDR and WildFire.

Banking Trojan families' techniques discussed Zeus, Kronos, Trickbot, IcedID, Emotet, Dridex

What Are Webinjects?

Webinjects are modules that can inject HTML or JavaScript before a web page is rendered, and are often used to trick users. They are known to be abused by banking Trojans, as well as being employed to steal credentials and manipulate form data inside web pages. In most banking Trojan families, there is at least one webinjects module.

An early stager of the banking Trojan usually injects the banking Trojan’s main bot into a Windows process, and that process injects the webinjects module into the machine’s available web browser processes as shown in Figure 1.

Code snippet showing Trickbot going through browser processes including Chrome, Internet Explorer, Firefox and Microsoft Edge, to inject with its webinjects module.
Figure 1. Trickbot goes through processes one by one to find browsers to inject with its webinjects module, using a stealthy technique known as reflective injection.

The webinjects module hooks the API calls responsible for sending, receiving or encrypting data sent to a web server. By intercepting the data before it is encrypted, the malware can read HTTP-POST headers and manipulate them on the fly.

Code snippet showing Trickbot webinjects module going through browser processes including Internet Explorer, Microsoft Edge, Chrome and Firefox to place hooks.
Figure 2. Trickbot webinjects module placing hooks based on the browser.
Code snippet showing Trickbot placing hooks on Wininet.dll functions including HttpSendRequestA, HttpSendRequestW, HttpSendRequestExA, HttpSendRequestExW and InternetCloseHandle.
Figure 3. Trickbot placing hooks on wininet.dll functions.

By fully controlling the HTTP headers just before the webpage is rendered, the malware can completely modify the forms and fool the user. The malware may inject HTML or JavaScript code to trick the user into inserting sensitive information, such as a PIN code or credit card number, enabling the malware to collect it. The malware can extract this information and send it to its command and control (C2) server without actually sending the forged headers to the targeted web page server.

Chrome (chrome.dll) Firefox (nspr3.dll / nspr4.dll) Internet Explorer / Edge (Wininet.dll)
ssl_read PR_Read HttpSendRequest
ssl_write PR_Connect InternetCloseHandle
PR_Close InternetReadFile
PR_Write InternetQueryDataAvailable
HttpQueryInfo
InternetWriteFile
HttpEndRequest
InternetQueryOption
InternetSetOption
HttpOpenRequest
InternetConnect

Table 1. Frequently hooked API functions.

How to Detect Webinjects

This technique can be prevented by detecting an injection into a web browser process. The injected thread calls the NtProtectVirtualMemory function where the NewAccessProtection argument is PAGE_EXECUTE_READWRITE and the BaseAddress argument is an address to a library function targeted by banking Trojans.

For example, Trickbot uses both VirtualProtect and VirtualProtectEx in its various versions. Inspecting NtProtectVirtualMemory calls covers both.

Some banking Trojans opt to avoid code injection. Instead, they suspend the remote process threads and install the hooks remotely. Inspecting remote NtProtectVirtualMemory calls can detect this variant technique.

Code snippet showing NtProtectVirtualMemory prototype.
Figure 4. NtProtectVirtualMemory prototype.

Infecting Web Browsers During Process Creation

Some banking Trojans aim to infect a target process as soon as it is launched, by injecting code into a predicted parent process of the real target. Once the banking Trojan executes in the context of the parent process, it hooks process creation library functions and waits until the real target is created.

Inside the hook, the banking Trojan manipulates the process creation flow. Then, for example, it initializes the webinjects module inside the remote process. The explorer.exe and runtimebroker.exe parent processes are frequently abused for this goal, as they usually launch the real targets.

For instance, the Karius banking Trojan used this technique by injecting code into explorer.exe and hooking CreateProcessInternalW. The Trojan’s hook handler looked for a spawned web browser process and injected the malicious webinjects module into it.

How to Prevent Attempts to Infect Web Browsers During Process Creation

This technique can be prevented by looking for an injection into explorer.exe or runtimebroker.exe, where the injected thread hooks process creation functions like NtCreateUserProcess, NtCreateProcessEx, CreateProcessInternalW, CreateProcessA or CreateProcessW.

Named Pipe Communication Between Injected Processes

Many banking Trojans use named pipes to communicate with various processes under the threat actor’s control. To do this, they inject their main bot into a Windows process, and then inject their other modules into different processes according to the module’s purpose. They then establish communication between the different processes using named pipes.

For example, Trickbot injects the main bot into svchost.exe. It creates a named pipe server and reflectively injects the webinjects module into web browsers. This injected module connects to the same named pipe as a client to communicate to the main bot and deliver the fetched credentials to the C2 server.

Code snippet showing Trickbot creating a named pipe server.
Figure 5. Trickbot named pipe server.

How to Prevent Named Pipe Communication Between Injected Processes

This technique can be prevented by inspecting named-pipe events. An injected thread creates a named pipe inside a Windows process, and then another injected thread that lives inside a web browser attempts to connect to that same named pipe.

Heaven’s Gate Injection Technique

Heaven's Gate is a technique used by malware, which enables a 32-bit (WoW64) process to execute 64-bit code by performing a far jump/call using segment selector 0x33. Modern malware uses Heaven's Gate to inject into both 64-bit and 32-bit processes from a single 32-bit process on x64 systems. This bypasses WoW64 API hooks, it hinders analysis on some debuggers, and it fails emulation on some sandboxes.

Even though this method is old, it is still effective and frequently used.

Trickbot and Emotet loaders use Heaven's Gate for process hollowing from a WoW64 process into a 64-bit svchost.exe (For more about process hollowing, see the section on Evasive Process Hollowing By Entrypoint Patching below). The architecture of these two banking Trojans dictates that their main bot persists inside svchost.exe while the web content manipulation and credential stealing modules live inside the browser processes.

Showing Emotet using Heaven's Gate technique in its Microsoft Outlook Messaging API module.
Figure 6. Emotet using Heaven's Gate in its Microsoft Outlook Messaging API (MAPI) module.

How to Prevent Heaven's Gate

A WoW64 process usually goes through the wow64cpu.dll to perform the transition to x64 CPU mode. Heaven's Gate does this transition manually.

Prevention methods can find Heaven's Gate by inspecting whether a WoW64 process system call didn’t go through the wow64cpu.dll. This can be done by placing hooks on critical APIs, generating a stack trace and inspecting the stack trace for wow64cpu.dll.

Showing WoW64's normal syscall flow.
Figure 7. WoW64’s normal syscall flow.

Evasive Process Hollowing by Entrypoint Patching

Process hollowing is a process injection technique that creates a new legitimate process in a suspended mode, unmaps its main image and replaces it with malicious code. The malicious code is written into the newly created process and the suspended thread context instruction pointer is changed using NtGetContextThread/NtSetContextThread.

Security product vendors check for main image unmapping combined with the usage of NtGetContextThread/NtSetContextThread to detect process hollowing.

A known technique for evading detection is to patch the process entry point with a small jump that redirects execution to the payload without actually using NtGetContextThread/NtSetContextThread functions or unmapping the main image. For example, Trickbot and Kronos have both used this technique.

Kronos mapped a suspended svchost.exe into its own process and patched it in its own memory address space. Similar to other banking Trojans, Kronos' main module ran within svchost.exe and orchestrated the whole operation from the remote svchost.exe process.

Trickbot implemented process hollowing by first using VirtualProtectEx on the process entrypoint, and then writing the hook stub using WriteProcessMemory.

Code snippet showing Kronos mapping svchost.exe and patching its entrypoint.
Figure 8. Kronos mapping svchost.exe and patching its entrypoint.
Figure 9. Kronos hook stub template – x86 opcodes for push and ret.
Figure 9. Kronos hook stub template – x86 opcodes for push and ret.

How to Prevent Evasive Process Hollowing by Entrypoint Patching

This technique can be prevented either by inspecting whether the address argument provided to the calls of NtWriteVirtualMemory or NtProtectVirtualMemory is a remote process entry point or by detecting suspicious remote mapping and reading of svchost.exe memory.

PE Injection

Common injection methods used by banking Trojans involve writing a mapped PE into a remote process using WriteProcessMemory. Some malware families try to obscure the call by wiping artifacts from the buffer, such as wiping the PE header.

For example, Zeus variants use this technique to inject themselves into other processes, allowing them to stay hidden, as well as to perform webinjects and to perpetrate financial data theft.

Code snippet from Zeus injection code, taken from its leaked source code.
Figure 10. Zeus injection code from its leaked source code.

How to Prevent PE Injection

This technique can be prevented by inspecting the buffer sent to NtWriteVirtualMemory for executable artifacts.

Process Injection via Hooking

Hooking can be used as an injection technique. Injecting a banking Trojan’s main payload into a legitimate-looking process maintains stealth and helps avoid endpoint protection detection.

This technique utilizes hooking to get code execution, usually by hooking a frequently called API function with a jump to a payload/shellcode. This avoids calling any suspicious APIs often used in code injection techniques like CreateRemoteThread or NtSetContextThread.

For instance, IcedID injects its main bot into a hollowed instance of svchost.exe using API hooking. This is also known as the ZwClose technique (ZwClose was the hooked API in Zberp, the first to employ this injection technique in the wild).

The injection flow of IcedID is slightly different than that of Zberp. It first hooks NtCreateUserProcess and then calls CreateProcessA to create svchost.exe without any special parameters or argument. In a regular flow, the newly created svchost.exe should terminate right away.

Code snippet from IcedID initiating svchost.exe hooking.
Figure 11. IcedID initiates svchost.exe hooking.
Code snippet from IcedID hooking NtCreateUserProcess.
Figure 12. IcedID hooks NtCreateUserProcess.

However, because IcedID hooked NtCreateUserProcess, the hook handler is called right after the call to CreateProcessA. In the handler, it performs the following activities:

  • Unhooks NtCreateUserProcess
  • Calls NtCreateUserProcess (which creates svchost.exe)
  • Decompresses a local buffer that contains the payload to inject using RtlDecompressBuffer
  • Allocates memory for the payload at the remote svchost.exe process
  • Writes the payload into the remote svchost.exe using NtAllocateVirtualMemory and ZwWriteVirtualMemory

For the execution, IcedID hooks RtlExitUserProcess in the newly created svchost.exe with a jump stub to the payload. As mentioned, svchost.exe was created without any parameters and it will try to exit. However, due to the IcedID hook, it will jump to the payload.

Code snippet from IcedID hooking RtlExitUserProcess.
Figure 13. IcedID hooks RtlExitUserProcess.

How to Prevent Injection via Hooking

This technique can be prevented by inspecting calls to NtProtectVirtualMemory and NtWriteVirtualMemory. The provided address argument for NtProtectVirtualMemory is an exported function from one of the Windows libraries, and the NtWriteVirtualMemory written buffer is a hooking stub. In both cases, the remote process has to be a known injection target.

AtomBombing Injection Technique

AtomBombing is a technique that allows malware to inject code while avoiding calling suspicious APIs that security vendors are watching. Dridex uses a slightly modified AtomBombing technique that injects one of its stages into a Windows process (usually explorer.exe) and employs various steps to cause financial data theft.

Malware using the AtomBombing technique first writes the payload into the global atom table, which can be accessed by all processes. They then dispatch an asynchronous procedure call (APC) to the APC queue of a target process thread using NtQueueApcThread, forcing the target process to call GlobalGetAtomA.

The target thread then retrieves the payload from the global atom table and inserts it into a read/write (RW) region inside the target process memory space (a code cave inside the kernelbase.dll data section). The payload has to be split into NULL-terminated strings and an atom is created for each string.

For the execution, the injector process dispatches another APC using NtQueueApcThread to force the remote process to execute NtSetContextThread. The injected process then calls NtSetContextThread, which invokes a return-oriented programming (ROP) chain that allocates execute/read/write (RWX) memory. The ROP chain then copies the payload from the RW region into the newly allocated RWX region, and lastly, executes it.

The unique idea behind AtomBombing is the write-primitive, which allows writing to the remote process using atom tables and APC.

Dridex uses a variation of AtomBombing that queues an APC to call memset to clean an RW region in ntdll.dll. Then, it copies the payload and its import table into the target process using the same write technique into the ntdll.dll RW region.

For the execution, Dridex modifies the copied payload memory into executable memory using NtProtectVirtualMemory. Then it hooks GlobalGetAtomA by calling NtProtectVirtualMemory and by using the same write primitive. Finally, it queues an APC into the patched GlobalGetAtomA to get the payload running.

Code snippet from AtomBombing proof of concept
Figure 14. AtomBombing proof of concept code.

How to Prevent AtomBombing and its Variants

These techniques can be prevented by inspecting whether the arguments provided to NtQueueApcThread/NtSetContextThread calls point to a suspicious API – the APC routine argument in the case of NtQueueApcThread, or the new instruction pointer in the context argument in the case of NtSetContextThread. Both API calls have to be called into a remote process.

Conclusion

Threat actors who are in it for the money use a wide range of malware techniques for injection and financial fraud, and they are always looking for new ways to develop evasive techniques. We have explored some of the more interesting banking Trojan techniques and how they’re used to steal victims’ sensitive data. And finally, we describe how these techniques can be used to detect malicious behavior, so it can be prevented.

Palo Alto Networks customers using Cortex XDR receive protections from such attacks in different layers, including the following:

  • Local Analysis Machine Learning module
  • Behavioral Threat Protection
  • Behavioral indicators of compromise (BIOC) and Analytics BIOCs rules

These layers identify the tactics and techniques that banking Trojans use at different stages of their execution.

Palo Alto Networks customers also receive protections against the attacks discussed here through the WildFire cloud-delivered security subscription for the Next-Generation Firewall.

Indicators of Compromise

  • Trickbot
    • testnewinj32Dll.dll: 4becc0d518a97cc31427cd08348958cda4e00487c7ec0ac38fdcd53bbe36b5cc
    • Webinjects: ef6603a7ef46177ecba194148f72d396d0ddae47e3d6e86cf43085e34b3a64d4
  • Emotet: dd20506b3c65472d58ccc0a018cb67c65fab6718023fd4b16e148e64e69e5740
  • Kronos: aad98f57ce0d2d2bb1494d82157d07e1f80fb6ee02dd5f95cd6a1a2dc40141bc
  • Zeus: 0f409bc42d5cd8d28abf6d950066e991bf9f4c7bd0e234d6af9754af7ad52aa6
  • IcedID: 358af26358a436a38d75ac5de22ae07c4d59a8d50241f4fff02c489aa69e462f
  • Dridex: ffbd79ba40502a1373b8991909739a60a95e745829d2e15c4d312176bbfb5b3e

 

Enlarged Image