IBM X-Force Research proactively researches financial cybercrime threats on an ongoing basis. In recent activity, X-Force studied some changes made to the IcedID banking Trojan that help the malware act more stealthily on infected devices.

Banking Trojans and the organized crime gangs that operate them have risen in the past decade to become one of the most prominent online threats affecting the financial sector and online service providers at large. These highly evolving malicious programs are often modular and sophisticated and, in most cases, supported by an in-house developer that keeps updating code to evade security controls.

It’s not always easy to keep up with threat evolution in-house. These details about the updated injection method can help security professionals manage risk to their organization and detect updated versions of IcedID that use this injection tactic.

No New Threads to See Here

Before we delve into the reversing of IcedID’s modified injection, let’s summarize it in a few words.

Prior to the Change

Prior to the recent modifications, IcedID would write its shellcode to targeted operating system (OS) processes via ZwWriteVirtualMemory. IcedID used this tactic in cases where it would inject code into either OS processes or when hooking browser processes.

After the Change

IcedID separated the tactics for OS process injection and browser processes. When the malware injects into an OS process, it creates a process in suspend state. It then hooks the RtlExitUserProcess, which is very often called to terminate userland processes. IcedID’s developer counts on legitimate processes to call on this now-infected process, which will make it jump to the shellcode and run it via a seemingly legitimate flow of events that would not get flagged by most controls.

When IcedID injects to a browser process, it hooks the NtWaitForSingleObject function, again by using ZwWriteVirtualMemory.

A Closer Look Under the Hood

To demonstrate how the threat works, let’s begin when the IcedID payload launches its execution routine on a target device. The malware starts by creating a svchost.exe process instance in suspend state and injects its shellcode into that process. After the injection, svchost.exe resumes and the payload terminates itself.

The newly malicious svchost.exe process writes the payload to the %ProgramData% folder with a globally unique identifier (GUID)-like folder naming convention (the GUID is a 128-bit integer number used to identify resources; the term GUID is generally used by developers working with Microsoft technologies). It uses [a-z] [A-Z]{0-9} and the payload, and a name convention of [a-z] {8-9}.exe. The value and file name are generated differently on each operating system running IcedID. However, the name will be the same upon subsequent executions on the same host.

This process also creates a scheduled task so that it will run every time the system reboots to allow IcedID to maintain persistence on the infected device.

The malicious svchost.exe creates three additional svchost.exe subprocesses and injects its shellcode into each one of them. We’ll explain the injection process in further detail in the following section.

Figure 1: Three svchost.exe instances injected with IcedID shellcode.

At this point, with four svchost.exe processes in total, these instances will remain active until the device is shut down at some point. After a reboot, these processes will be tasked with monitoring the OS for the launch of a browser application. The malware will then attack the browser’s process as well and inject it with shellcode.

Two Injection Methods

IcedID injects its shellcode into browser processes with the goal of eventually hooking the process and allowing the malware to begin intercepting and manipulating the victim’s online activity.

The malware uses API hooking to inject and execute its shellcode via different legitimate threads running on the victim’s device. Let’s look at that tactic more closely:

  • IcedID allocates memory in a target process using the NtAllocateVirtualMemory function.
  • The malware writes the shellcode into the target process without suspending that process. To do that, IcedID uses the ZwWriteVirtualMemory or NtWriteVirtualMemory functions.
  • Next, it hooks a frequently called API that’s commonly used by the target process.

There are two different API hooking scenarios we observed IcedID using:

  1. Injecting into a web-browser via svchost.exe; and
  2. Injecting into svchost.exe via its parent process.

The hooked API is called by the targeted process and the shellcode is thus executed.

To wipe its traces, the shellcode fixes the patched library’s function that was used to execute it so that tools that detect hooks and rootkits won’t show any trails of that patch. This injection technique can evade security mechanisms that would otherwise detect suspicious API calls, such as the createRemoteThread (CRT), asynchronous procedure calls (APC) and other common malware tactics.

Remotely setting up a hook in a target process without suspending the target process first can cause unexpected behavior. This can easily result in a crash since two threads can execute the code of the API at the same time.

Deeper Into the Browser Process Injection

The first injection tactic is from a svchost.exe process to a web browser. To begin, the malware needs a detection mechanism to identify that the infected user has launched a browser application. To do that, IcedID takes a snapshot of all the running processes and scans them for browser processes.

Figure 2: IcedID scanning for running browser processes.

The scan creates an infinite loop that calls on IcedID’s function main_func. One of that function’s parameters is a pointer to another malware function: check_target_process. Viewing the details of check_target_process reveals that it gets the process ID (PID) of the svchost.exe it runs inside. Next, it calls NtQuerySystemInformation to fetch a list of all processes currently running on the device.

Figure 3: IcedID fetching process list to scan for open browser applications.

This scheme keeps running in a loop over all the operating system’s processes to allow the malware to detect browser activity. When it encounters a potential browser process, IcedID checks it via the check_target_process.

This last function uses two parameters to check whether a process is of interest or not:

  1. The target process’ ID; and
  2. The target process’ name.

The function encodes the process’ name and compares it with hardcoded strings the developer created, representing the names of browsers IcedID can inject into.

Figure 4: IcedID checking for browser processes to inject its shellcode into.

To compare the process’ name to the preconfigured, hardcoded list, the malware calls the resolveProcessName function. That function receives the target process’ name as a parameter, decodes it and creates a hash of the result. That hash is what’s being compared to a list of precomputed hashes that translate into iexplore.exe, firefox.exe and chrome.exe.

The hash codes for the targeted web browsers are:

  • Firefox.exe — 1EACD83D;
  • Iexplore.exe — 0D31A30C7; and
  • Chrome.exe — 0FA7442ED.

Figure 5: IcedID checking for popular browser processes to inject shellcode into.

If there’s no match, the function returns to its scanning routine, looking for other browser processes.

The next step for the malware is to call decode_target_process_event_name. This function receives the targeted process’ PID as a parameter and generates an event name for the web browser process that’s about to be injected with IcedID’s shellcode.

This part of the injection mechanism is in place to compute the event name that the shellcode will create after the injection process so that it indicates to the malware that a specific web browser’s process has already been injected.

Now, after a match has been found and the validation of the target process is complete, the actual injection process begins by calling the function inject_target_process. Here, again, the parameter is the target process’ PID.

Figure 6: IcedID validates and begins injection of shellcode into browser process.

The inject_target_process function receives a handle to the target process using the OpenProcess API. It then checks whether the process is either 32-bit or 64-bit to prepare the correct code version for injection.

Next up, the function that’s responsible for the injection starts by allocating memory in the target process. We can see the memory allocation call and then writing of the shellcode into the target process using three Windows API functions:

  1. NtAllocateVirtualMemory;
  2. ZwProtectVirtualMemory; and
  3. ZwWriteVirtualMemory.

Figure 7: IcedID injects shellcode into targeted browser process.

After it writes the shellcode into the process, IcedID calls to the next function for patching, depending on which architecture applies:

  • patch_NtWaitForSingleObject_32bit; or
  • patch_NtWaitForSingleObject_64bit

To patch the NtWaitForSingleObject function and make it jump to the shellcode the next time it is called, IcedID begins by modifying the page protection status of that function using ZwProtectVirtualMemory. Then, the malware applies the hook using ZwWriteVirtualMemory, and ends with switching the protection flag back to its normal permission state. From this point on, subsequent calls to the NtWaitForSingleObject function will jump to the malware’s injected shellcode and execute it.

The right-hand part of the image below shows the malware hooking the NtWaitForSingleObject function on the target process, in this case firefox.exe. The left part of the image shows the targeted process with the newly hooked function.

Figure 8: Before and after IcedID’s browser process hooking.

The hooking process does not stop here; it is a perpetual loop that continues for as long as the device is infected with IcedID. If the user opts to launch a different browser, the malware will hook it as well and enable itself to intercept and interfere with the victim’s online banking activities on any of the three browsers it can hook.

A Closer Look at IcedID’s Shellcode

Let’s take a closer look at the shellcode that IcedID injects into browser processes. At the starting point, the newly hooked browser process calls on the NtWaitForSingleObject function. The injected shellcode runs and fixes the hook to make sure the shellcode leading to the main function will only be called once and not loop back repeatedly, especially since NtWaitForSingleObject is a common API and will be called many times. This also wipes the traces of the hook, which can make it harder for researchers to find.

The image below shows the starting address of the shellcode that is executed when the call for NtWaitForSingleObject is launched by a legitimate thread from the hooked process.

Figure 9: Starting address of the shellcode executed when the call for NtWaitForSingleObject is launched.

The function fix_NtWaitForSingleObject will uninstall the hook from NtWaitForSingleObject in the browser process, reinstating the original code that was there before the malware hooked it. Next, the shellcode will install the hooks inside the web browser’s process and then call NtWaitForSingleObject to continue executing the browser’s process.

Figure 10: IcedID restores the NtWaitForSingleObject function code to its original content.

Examining the shellcode in WinDbg, a commonly used Windows debugger, we can see that NtWaitForSingleObject has indeed been restored to its original code.

One of the browser functions hooked by IcedID is Ws2_32:connect. This function redirects the victim’s browsing traffic to the now-malicious svchost.exe process, allowing the malware to identify data the attacker wishes to receive, such as credentials, payment card details, etc. The data is exfiltrated to the attacker’s command-and-control (C&C) sever.

We can see that the malware function hook_connect gets the same three parameters as the connect function. First, it checks for the address family, browser type and port number and uses the information to determine whether to call the original connect function and exit or continue with the hook.

In the next step, the malware calls the original connect function with a new sockaddr object and new parameters: 127.0.0.1 as the IP address, AF_INET as the family address and a new calculated port number. The traffic is ultimately redirected to the malicious svchost.exe process.

Figure 11: Reversing the hook installed on the connect function in the web browser.

This shellcode is what enables IcedID to gain some control and insight into what the victim is doing online and allows the attacker to interfere with that activity.

Deeper Into the OS Process Injection

The second injection method IcedID uses is designed for injecting into processes of the operating system, not the browser.

This second tactic relies on the familiar method of creating a new process with the CREATE_SUSPEND flag and then hooking the RtlExitUserProcess API. Once the new process starts executing, it will fix the function back to its original state.

This injection method is an interaction between the different svchost.exe processes and the malware’s payload.

Figure 12: Before and after IcedID’s hooks on targeted OS processes.

The left-hand part of the image above shows the svchost.exe process where a hook was installed on the RtlExitUserProcess API, making it jump to the shellcode the next time it is called by a legitimate thread from the svchost.exe process.

We can also see the start of the shellcode in the Interactive Disassembler (IDA), and we can see that the first function being called fixes the hook that was installed on the RtlExitUserProcess API.

Figure 13: Starting address for the shellcode that’s executed upon a call to RtlExitUserProcess.

Examining the code of the RtlExitUserProcess API after the removal of the malware’s hook, we can see that the code was restored to its original state:

Figure 14: RtlExitUserProcess code restored to original content after uninstalling the hook.

This sums up IcedID’s split injection tactics. It appears that the malware’s operators are getting advice from other coders, likely those working on the TrickBot project. These modifications can make the malware’s activity stealthier, yet effective.

IcedID Keeps It Moving

IcedID emerged in 2017 as a modular banking Trojan with advanced capabilities to automate fraudulent transactions and control user devices to take over their bank accounts. Since its initial analysis, it has been evolving gradually over time and showing explicit collaboration with the TrickBot Trojan by ways of common distribution and feature similarity.

In August 2018, our researchers noted that IcedID had been upgraded to behave in a similar way to the TrickBot Trojan in terms of its deployment. The binary file had been modified to become smaller and no longer featured embedded modules. The malware’s plugins were being fetched and loaded on demand from a remote server after the Trojan was installed on infected devices. These changes made IcedID stealthier, modular and also more similar to TrickBot.

In addition to its increased stealth level, IcedID started encrypting its binary file by obfuscating file names associated with its deployment on infected devices. Another TrickBot-inspired modification saw IcedID add event objects, which are a means to coordinate multiple threads of execution in Windows-based operating systems. IcedID began using named events to synchronize the execution between its core binary and the modular plugins it could fetch from its control server.

Although malware authors do sometimes copy from one another, these modifications were not coincidental. Even if we only looked at the fact that TrickBot and IcedID fetch one another into infected devices, that would be indication enough that these Trojans are operated by teams that work together.

X-Force data from 2018 placed IcedID in the top five most active banking Trojans on a global scale. The malware’s operators have links to other key cybergangs in the threat arena, and they have been using IcedID to actively target the customers of major banks, payment card providers, e-commerce companies and cryptocurrency platforms. X-Force researchers expect this malware to continue targeting banks and payment platforms as we move into the second quarter of 2019.

Figure 15: Top most active banking Trojan families in 2019 (source: IBM Trusteer).

More from Malware

Ransomware Renaissance 2023: The Definitive Guide to Stay Safer

2 min read - Ransomware is experiencing a renaissance in 2023, with some cybersecurity firms reporting over 400 attacks in the month of March alone. And it shouldn’t be a surprise: the 2023 X-Force Threat Intelligence Index found backdoor deployments — malware providing remote access — as the top attacker action in 2022, and aptly predicted 2022’s backdoor failures would become 2023’s ransomware crisis. Compounding the problem is the industrialization of the cybercrime ecosystem, enabling adversaries to complete more attacks, faster. Over the last…

2 min read

BlackCat (ALPHV) Ransomware Levels Up for Stealth, Speed and Exfiltration

9 min read - This blog was made possible through contributions from Kat Metrick, Kevin Henson, Agnes Ramos-Beauchamp, Thanassis Diogos, Diego Matos Martins and Joseph Spero. BlackCat ransomware, which was among the top ransomware families observed by IBM Security X-Force in 2022, according to the 2023 X-Force Threat Intelligence Index, continues to wreak havoc across organizations globally this year. BlackCat (a.k.a. ALPHV) ransomware affiliates' more recent attacks include targeting organizations in the healthcare, government, education, manufacturing and hospitality sectors. Reportedly, several of these incidents resulted…

9 min read

Ex-Conti and FIN7 Actors Collaborate with New Backdoor

15 min read -   April 27, 2023 Update This article is being republished with modifications from the original that was published on April 14, 2023, to change the name of the family of malware from Domino to Minodo. This is being done to avoid any possible confusion with the HCL Domino brand. The family of malware that is described in this article is unrelated to, does not impact, nor uses HCL Domino or any of its components in any way. The malware is…

15 min read

When the Absence of Noise Becomes Signal: Defensive Considerations for Lazarus FudModule

7 min read - In February 2023, X-Force posted a blog entitled “Direct Kernel Object Manipulation (DKOM) Attacks on ETW Providers” that details the capabilities of a sample attributed to the Lazarus group leveraged to impair visibility of the malware’s operations. This blog will not rehash analysis of the Lazarus malware sample or Event Tracing for Windows (ETW) as that has been previously covered in the X-Force blog post. This blog will focus on highlighting the opportunities for detection of the FudModule within the…

7 min read