A comparative analysis performed by IBM Security X-Force uncovered evidence that suggests Bumblebee malware, which first appeared in the wild last year, was likely developed directly from source code associated with the Ramnit banking trojan. This newly discovered connection is particularly interesting as campaign activity has so far linked Bumblebee to affiliates of the threat group ITG23 (aka the Trickbot/Conti group), who are not known to have had a previous connection with Ramnit.
This year has so far proven tumultuous for ITG23 – the group suffered a series of high profile leaks, referred to as the ContiLeaks and TrickLeaks, which resulted in the publication of thousands of chat messages and the doxxing of numerous group members. In addition, the group have seemingly retired two of their most high-profile malware families, Trickbot and Bazar, and shutdown their Conti ransomware operation.
Various reports have suggested that a significant reshuffling of personnel may be occurring, with ITG23 splitting into several factions and some members moving on entirely. The appearance of Ramnit code within Bumblebee may be indicative of this flux and a sign that new alliances are being formed, which could be a prelude to new types of attack campaigns.
This research highlights previously unreported similarities and code overlaps between the Bumblebee and Ramnit malware families. It also examines the links between these two malware families, ITG23’s Trickbot malware, and the retired NeverQuest banking trojan.
The findings include:
- Significant code overlap between Bumblebee and Ramnit, suggesting they may share the same developer
- A custom code library used in both the Bumblebee/Ramnit malware and Trickbot trojan, indicating possible historical code sharing
- Evidence of potential collaboration between the developers of NeverQuest and Trickbot in the early days of Trickbot’s development
The analysis below provides further detail and explanations on the unique aspects observed between Bumblebee and Ramnit, and how they can be connected back to Trickbot and finally traced to their suspected origins within the retired NeverQuest banking trojan.
From Ramnit to Bumblebee
Ramnit is an older malware that originated in 2010 as a worm and swiftly evolved into a modular backdoor and banking trojan. Ramnit spread prolifically over the next few years, growing into a botnet with several million systems infected worldwide until it was subject to a takedown by Europol in early 2015. The impact of the takedown did not last long and by the end of 2015 Ramnit returned and was once again in active development. The malware struggled to regain its previous momentum, however, and the following years were characterised by campaigns of activity followed by periods of quiet.
A notable development occurred in mid-2018, when Ramnit relaunched, infecting 100,000 devices in two months, and demonstrating significant code updates. This included the addition of new loader modules which made extensive use of a custom hooking library for both payload execution and AV evasion; web injects were updated from Zeus-style to Lua-style; and a new name ‘Camellia’ appeared, replacing the original ‘Demetra’ designation. The reason for this overhaul is unknown, but some researchers noted that the code style had changed and speculated that it may have new developers.
Ramnit went through another quieter period during 2019 and 2020, with no significant developments observed. Then in early 2021, new Ramnit samples were observed using the internal name ‘hooker2.dll’, which matched several of the samples observed during Ramnit’s resurgence in August 2018. The sample code was similar to its 2018 counterparts but had gone through several updates, which included the addition of the OpenSSL library.
In August 2021, X-Force spotted a new malware that we shall now refer to as ‘Bumblebee Beta’ being deployed during a campaign exploiting the CVE-2021-4044 Microsoft Office vulnerability. This activity was attributed to the initial access broker “Exotic Lily”, which X-Force tracks as Hive0110, and who have previously distributed BazarLoader. This new malware primarily operated as a downloader and was capable of receiving payloads, such as Cobalt Strike, from the C2, which it would inject into a process randomly chosen from a hardcoded list. It was notable for using the user-agent string ‘bumblebee‘, which overlaps with the full version and is how the malware’s eventual name was derived. During our analysis at the time, we observed a number of significant code overlaps with Ramnit, including identical lists of inject targets, similar hooking and unhooking code, use of the OpenSSL library and the presence of two unused intermediary loader binaries stored in the malware data section, which were almost identical to those used in the 2018 and 2021 variants of Ramnit.
In March 2022, the full version of Bumblebee was released and quickly used in a number of large scale campaigns by distribution affiliates of threat group ITG23 (also known as the Trickbot/Conti group), such as Exotic Lily, TA579, and TA578 (tracked by X-Force as Hive0107). The malware appeared to be being used as a replacement for ITG23’s BazarLoader which had not been seen since February and has been observed downloading payloads including Cobalt Strike, Sliver, and Meterpreter. Bumblebee has also since been linked to ransomware operations involving Conti and MountLocker/Quantum.
Bumblebee had received several updates over the prior six months and now has full C2 communication and task functionality implemented, as well as the inclusion of anti-AV and anti-analysis code. It is capable of gathering system information, installing itself for persistence, and receiving and loading payloads including DLLs and shellcode. The previously unused intermediary loader binaries, observed in Bumblebee Beta, are now used as part of the fully implemented payload injection process.
Bumblebee still bears significant resemblance to Ramnit and in addition to the previously mentioned similarities, such as the inject and hooking functionality, Bumblebee was also found to contain the string ‘Z:\hooker2\Common\md5.cpp‘ suggesting it may have used code from a project called ‘hooker2‘ which is the internal name used in several of the 2018 and 2021 Ramnit samples. An identical string was also then found in a 2021 Ramnit sample.
The NeverQuest connection
While investigating the potential links between Ramnit and ITG23 in an effort to understand the relationship between the groups, we — like several other researchers — also noted the code overlap between Ramnit/Bumblebee and the Trickbot WebInject modules which may indicate that some code sharing has occurred between the two groups. Finally, we were eventually able to trace a significant portion of the code back to an old, now defunct, banking trojan called NeverQuest – also known as Vawtrak.
NeverQuest was a major player in the field of banking trojans from 2013 through to early 2017 when one of its developers was arrested in Spain. It is thought that the IcedID malware, which was discovered by IBM in September 2017, is likely to be the successor of NeverQuest. The NeverQuest group reportedly had a close relationship with Dyre, aka Dyreza, the predecessor of Trickbot, potentially explaining the close relationship between the Trickbot and IcedID groups today.
Dyre was another older banking trojan that operated around the same time as NeverQuest, until it suffered a takedown at the hands of Russian law enforcement at the end of 2015. Its successor Trickbot was released less than a year later, along with a module responsible for performing browser injects. Analysis of module samples reveals that even in its earliest stages of development in 2016, the Trickbot web inject module already contained code associated with NeverQuest. Given the close relationship between NeverQuest and Dyre, it is not hard to imagine that NeverQuest may have offered to share code with their associates in order to help get Trickbot off the ground.
The link between the Trickbot group and Ramnit is less clear, as there has been less observable cooperation between the two groups. However, during our investigation we did note that the NeverQuest code did not seem to be present in any of the older Ramnit samples we analysed; it seems that code may have only been added during Ramnit’s revamp in 2018. It was speculated at the time that the revamp may suggest that Ramnit had new developers, and it’s possible those developers may have had some sort of link with the Trickbot group. Notably, during its upgrade, Ramnit also switched to using LUA-style web injects which is a language favoured by IcedID.
One challenge we faced during this exercise was tracking the provenance of the code used in the myriad of samples analysed. Many banking trojans today are based on the publicly available leaked source code of several older trojans including Zeus, Carberp, and Gozi. When assessing code overlap between malware families, it’s therefore important to determine whether the code in question comes from a public source, as in that instance its presence in both malware families may just be a coincidence rather than indicating any sort of significant relationship.
NeverQuest borrows code heavily from the leaked Gozi source, and parts of this code have also made their way into Ramnit and Bumblebee, so when doing our comparison we were careful to focus on areas that couldn’t be attributed to a public source. To this end, much of our research focuses on a hooking library that is shared across all the malware families analysed in this report, but that we have not been able to trace back to any public source. Our research findings indicate that this library may have been originally created by the developers of NeverQuest, and then later shared with the Trickbot group – eventually ending up in Ramnit and Bumblebee.
A number of samples were analysed for the purpose of this research, the full details of which are presented in the Sample Hashes table at the end of this report. This includes sets of Ramnit samples dating back to 2018 and 2021, Bumblebee Beta samples from 2021, and Bumblebee samples from 2022. In addition, samples including NeverQuest, Karius, and Trickbot’s inject modules, were analysed for the purposes of comparison and provenance tracking.
In 2018, after a brief hiatus, Ramnit relaunched with great potency, infecting 100,000 devices in two months and boasting new loaders and an upgraded code base. Campaigns involving the sLoad dropper were widely reported on and attributed to TA554. At this point, Ramnit was demonstrating a complex multi-component loading mechanism, including a dropper/installer utilising VBS and Powershell scripts.
This research focuses on the unpacked components of Ramnit outlined in the diagram below, specifically the Camellia Loaders, Hook Loaders, and Hooker2 module. The functionality of the Ramnit Core binary, rmnsoft.dll, did not change significantly and is not covered in this report.
Figure 1 — Diagram showing the relationship between different Ramnit components including the Hook Loaders, Ramnit Core, Hooker2 module, and WebInject module.
The Hook loaders
Ramnit’s Hook loaders are small binaries with the primary function to load a payload by hooking the Windows API functions ZwOpenFile, ZwCreateSection, ZwOpenSection and ZwMapViewOfFile. The process of function hooking, as used in this example, involves accessing the target library module in memory and overwriting the code at the start of the target function such that the flow of execution is redirected to a function supplied by the malware.
In this instance, the functions ZwOpenFile, ZwCreateSection, and ZwOpenSection are hooked and redirected to functions within the loader which check the parameters being passed for a file named ‘wups.dll‘, before directing execution back to the original API function.
In the hook function for ZwMapViewOfSection, if the call is determined to be related to the loading of file ‘wups.dll’, then the payload data is retrieved, and a new memory section is created and the payload binary mapped into it. The address of this new section is then copied to the BaseAddress variable which is an output parameter for ZwMapViewOfSection. The result of this is that when ZwMapViewOfSection is called in relation to file ‘wups.dll’, the address of the loaded payload will be returned instead of that of wups.dll.
Once these hooks have been set, the loader calls the Windows API function LdrLoadDll with ‘wups.dll’ as the parameter. The function LdrLoadDll is used for loading DLLs, and it makes use of the APIs ZwOpenFile, ZwCreateSection, ZwOpenSection and ZwMapViewOfFile as part of its loading process. So, when the loader calls LdrLoadDll, this triggers the hooked functions and results in the loading of the payload in place of wups.dll, as described above. As part of the standard DLL loading process LdrLoadDll will also call the loaded DLL’s entrypoint which in this case results in the execution of the payload.
Different versions of the Hook Loader may use DLL names other than wups.dll, and samples using names such as sbe.dll, dimsroam.dll and dimsjob.dll have also been observed.
The main function for the Hook Loader showing the installation of the hooks and execution of LdrLoadDll can be seen in the image below.
Figure 2 — Main function for the Ramnit Hook Loader showing the installation of the hooks and execution of LdrLoadDll
Two variations of the Hook Loader appear to be in use. One is used as a standalone loader and has its payload stored within its data section. The second type we have referred to in this report as an intermediary loader, which is used by a parent loader during the loading process, and require the payload details to be supplied as parameters during execution. The parent executes the intermediary loader and passes the memory address of the payload to it using the DllEntrypoint function’s ‘Reserved’ parameter, and the intermediary loader, in turn, loads the given payload.
Upgraded versions of the intermediary Hook Loaders were observed in the 2021 Ramnit sample set, which could receive an RC4 encrypted payload that the loader decrypted just prior to loading into the allocated memory section. A 4-byte RC4 key would be passed to the intermediary loader by the parent along with the payload address.
This updated variant of the Hook Loader was also observed in Bumblebee samples.
The hooking library
Many of the samples analysed throughout this report all make use of the same custom hooking library for the process of setting hooks and storing information about set hooks. We have not been able to trace this hooking code back to any public source and the code does not match the hooking functions found in the leaked source code for trojans such as Gozi, Carberp, and Zeus. Our analysis indicates that this hooking library was likely developed by NeverQuest, aka Vawtrak in 2013, and since then it has shown up in Trickbot inject modules starting in 2016, Ramnit binaries from 2018, and Bumblebee from 2021.
The hooking library is easily recognisable. It makes use of a hook store that contains information about installed hooks including function addresses and the original code so the function can be restored once the hook is no longer needed. An initialization function, usually run during the start of the malware’s execution, will allocate space for the hook store using VirtualAlloc. The size of each hook store object is 71 bytes in most 32-bit implementations and this constant can be useful in identifying the hook library code. The size of the hook store object in 64-bit implementations appears to be 60 bytes.
Figure 3 — Hook library initialization function, referencing notable 32-bit hook object size of 71 bytes.
Figure 4 — The hook creation function within a 2021 Ramnit sample. At this point several of the library’s other functions have been updated to use control flow flattening code obfuscation, which was not present in the 2018 samples.
Ramnit’s unhooking code
Hooking is not just confined to malware – it has many different applications and is often used by security software to examine the behaviour of processes and look for malicious activity. One piece of code which is seen repeatedly throughout the Ramnit binaries checks a hardcoded list of API functions for any hooks that might already be set, for instance by security applications, and removes them by restoring the code at the start of the function with the original code as found in the corresponding DLL file stored on disk. Note, this functionality does not seem to make use of hooking library referenced above.
Similar code can also be seen within the Hook Loaders used within the Bumblebee samples.
Figure 5 — Ramnit’s API unhooking function
The Camellia loader
The Camellia loader is usually found as a second or third stage loader in the Ramnit loading process and is generally loaded by the standalone version of the Hook Loader such as that described above. The purpose of the Camellia Loader is to load and execute its payload via process injection. A significant amount of the code base of the Camellia Loader can be traced back to source code from the leaked Gozi malware, specifically Gozi’s ‘activdll’ module which contains process injection functions.
Upon execution, the Camellia loader creates a new thread to run its main functionality and uses the same unhooking function described above to check a hardcoded list of APIs for hooks and restore them to their original states. The loader then selects a random process from the following hardcoded list, which will be used as the process injection target. It should be noted that this process list does not appear within the Gozi source and so seems to originate from Ramnit.
Scroll to view full table
The loader uses the Windows Management Instrumentation (WMI) interface to create a new instance of the selected process in suspended mode. It then gets a handle on the newly created process and parses it to identify the address of the process entrypoint or first TLS callback function, if applicable, which will be the address of the first function executed by the process. The loader then patches the code at this address, replacing it with the following code, which calls the Sleep API in an infinite loop.
Scroll to view full table
At this point the loader enters code that closely matches Gozi’s ProcessInjectDll function. The comments in the code for this function also provide a concise explanation for why the process needed to be patched to enter an infinite loop prior to injection:
Scroll to view full table
The code resumes the created process and waits until it is fully initialized, before suspending it again. It then creates a new memory section and maps a view of the memory section in both the current process and the target process. This makes the memory section available to both the loader process and the newly created target process. The loader then takes its payload, which is a DLL file stored within its data section and loads it into the new memory section.
It also copies into the memory section a structure containing information about the payload, as well as a ‘LoaderStub’ function which is responsible for performing the rest of the steps to properly load the payload DLL in the target process. The loader then gets the context for the target thread and updates it to execute an InjectStub function, which in turn executes the copied LoaderStub function. The target process is resumed and the LoaderStub function executes within the target process. The LoadStub function finishes loading the payload DLL within the target process, and finally executes the payload at its entry point.
The payload for the Camellia Loader is often the Ramnit Core module, rmnsoft.dll.
Figure 6 — The main function for the Camellia Loader
Hooker2 is the controller module for Ramnit’s web injection modules. These modules are injected into web browser processes where they can monitor and intercept web requests made through the browser. They may be configured to steal information such as credentials and banking and payment information.
Hooker2 acts as the controller and loader for the web injection binaries, and it is primarily designed to target the web browsers Internet Explorer, Microsoft Edge, Firefox, and Google Chrome. It has two binaries stored within its resources which are the 32 and 64 bit web injection modules. It also contains 32 and 64 bit binaries within its data section, which are intermediary hook loaders, as described earlier in this report.
Hooker2 starts by checking and adjusting the settings for the above listed browsers in order to weaken their security; this includes modifying registry settings and updating command line arguments in shortcut files. It then monitors running processes on the system for any instances of the target web browsers – if found, it proceeds to inject its payloads into the browser process.
Similar to the Camellia Loader, Hooker2 also makes use of code based on the Gozi ProcessInjectDll and AdInjectImage functions in order to accomplish the injection of its payloads into the target browser process. In this case, however, it is injecting two binaries into the target process – the intermediary hook loader and the web inject module (either the 32-bit or 64-bit versions depending on the target process architecture).
Hooker2 goes through the same steps as the Camellia Loader, creating a new memory section, mapping a view of the memory section in both the current process and the target process, and then building the Hook Loader binary within the created memory section. It then repeats this process for the webinject payload.
This procedure is illustrated in the screenshot below.
Figure 7 — Image showing the creation of memory sections and views in current and target processes, and copying payloads into the sections
Hooker2 then creates a ‘Loader Context’ structure which is stored directly after the hook loader in memory and contains information about the web inject payload, as well as a copied Loader Stub function. Finally, a function is called which executes the Loader Stub function within the target process, which in turn loads and executes the Hook Loader binary. The Hook Loader binary then uses its hooking technique, described earlier in this report, to load and execute the final Web Inject module payload.
Figure 8 — Population of Loader Context structure and execution of code within target process.
Ramnit’s 2021 updates
In addition to the 2018 samples, we analysed two sets of Ramnit binaries compiled in early 2021. Overall the structure and functionality of these newer samples hadn’t changed significantly, but we noted the following updates:
- Hooker2 module updated to target the Thunderbird email application in addition to web browsers, and includes code targeting email clients. The web browser targeting code is also updated.
- Addition of the OpenSSL library, which was not included in the 2018 samples.
- Inclusion of string Z:\hooker2\Common\md5.cpp in the Hooker2 binary.
- The LoaderStub function is updated with control-flow flattening obfuscation.
- Several of the functions within the hooking library are also updated to use control-flow flattening obfuscation.
- The Intermediary Hook Loaders are updated with the ability to decrypt the supplied payload using RC4, and now have the internal name RapportGP.dll.
- The list of process injection targets in the Camellia Loader is reduced to the following:
- %PROGRAMFILES%\Windows Photo Viewer\ImagingDevices.exe
- %PROGRAMFILES%\Windows Mail\wab.exe
- %PROGRAMFILES%\Windows Mail\wabmig.exe
At this point, it starts to become noticeable how the state of the malware is shifting closer towards Bumblebee, which contains all the above listed features, except the first.
The birth of Bumblebee
The downloaded file was a previously unknown backdoor but now recognised as an early version of Bumblebee. It incorporates the OpenSSL and Boost libraries and is also notable for using the user-agent bumblebee. Upon execution, it connects to its C2 and receives a JSON-formatted command containing a base64 encoded shellcode payload, which it injects into a process and executes.
Upon first glance, this early version of Bumblebee does not resemble the Ramnit binaries much at all as its main function is almost entirely taken up by large chunks of code from the OpenSSL and JSON libraries used by Bumblebee for connecting to the C2 and generating or parsing the JSON-formatted data being sent and received. However, closer inspection reveals several notable similarities.
Firstly, immediately after entering the DllMain function, Bumblebee initialises a hook store object very similar to those used in the Ramnit samples, indicating that it is likely using the same hooking library.
Figure 9 — Hook store initialisation code indicates Bumblebee is likely using the same hooking code as Ramnit
Later on in the code, once Bumblebee has received its payload from the C2, it selects a process to inject the payload into a hardcoded list that matches exactly the list used in the 2021 version of the Ramnit Camellia Loader.
Figure 10 — The list of process injection targets in Bumblebee Beta
Once a process has been selected, Bumblebee creates a new instance of the process in suspended mode using the Windows Management Instrumentation (WMI) interface, and then patches the entrypoint of the process, replacing it with code that calls the SleepEx API in an infinite loop. This chain of events is also almost identical to that performed by the Camellia Loader.
Figure 11 — Patching code from 64-bit Bumblebee sample (left) compared with the equivalent 32-bit code from a Camellia Loader sample (right)
The function to inject the payload into the target process has some similarities to that used in Camellia Loader and Hooker2 in that it still injects the payload into the target process by creating and mapping views of a shared memory section in both the current and target processes. However, it is much simpler than the version of the injection function used by Ramnit, it does not use the LoaderStub code or loader context structures, and instead executes the payload code by calling the NtQueueApcThread API. This difference may be a result of the payload being shellcode rather than a full DLL binary which requires more complex loading mechanisms.
A final, significant observation is that the Bumblebee Beta binary contains 32 and 64-bit Hook Loader binaries within its data section, despite not using them within its injection function. These Hook Loaders are almost identical to those found in the 2021 Ramnit samples; they include the ability to decrypt a provided payload using RC4 and use the name RapportGP.dll also seen in the 2021 Ramnit versions.
In March 2022, the full version of Bumblebee was released, with full C2 communication and task functionality implemented, as well as the inclusion of anti-AV and anti-analysis code taken from the Al-Khaser Project. It is capable of gathering system information, installing itself for persistence, and receiving and loading payloads including DLLs and shellcode. The intermediary Hook Loaders are still present and are now used as part of the fully implemented payload injection process.
A full analysis of the campaigns involving Bumblebee is outside the scope of this report but detailed write-ups can be found here, here and here.
Like its predecessor, the full version of Bumblebee still uses the OpenSSL library for network communication, and requests and responses between itself and the C2 are JSON formatted, albeit with a much more detailed structure. Bumblebee gathers basic system information about the infected host which it converts to JSON and sends to the C2, and in return receives a JSON formatted response containing task data.
Bumblebee is currently capable of carrying out the following tasks:
Scroll to view full table
The shi command instructs Bumblebee to inject a shellcode payload, and this procedure is very similar to the one seen in Bumblebee Beta. Bumblebee selects a target process from the following hardcoded list of processes, which is noted to be the same as Bumblebee Beta and Ramnit:
- %PROGRAMFILES%\Windows Photo Viewer\ImagingDevices.exe
- %PROGRAMFILES%\Windows Mail\wab.exe
- %PROGRAMFILES%\Windows Mail\wabmig.exe
It then uses the same injection and execution method observed in Bumblebee Beta to inject the payload into the target process and execute it using the NtQueueApcThread API.
The dij command instructs Bumblebee to inject a DLL payload into a process chosen from the same hardcoded list as above. This method more closely resembles the Gozi-based injection method used in the Ramnit Hooker2 module, including the use of the intermediary hook loader binary and loader stub code. The injection function first creates a new memory section for the hook loader, maps views to the section in both the current and target process, and then builds the hook loader within the section. A second memory section is created and the payload DLL copied into it. The function then creates the ‘Loader Context’ structure directly after the hook loader in memory and populates it with information about the payload, as well as the copied Loader Stub function. Finally, the Loader Stub function is executed within the target process using the NtQueueApcThread API, which in turn loads and executes the Hook Loader binary. The Hook Loader binary then uses its hooking technique, described earlier in this report, to load and execute the final payload.
The below image shows the DLL injection function within Bumblebee and similarities can be seen with the equivalent function within Hooker2, illustrated previously.
Figure 12 — Bumblebee DLL Injection function showing similarities to the Gozi-based injection function used in Hooker2
The LoaderStub function used by Bumblebee is very similar to that used in the 2021 Ramnit samples and also includes the control flow flattening obfuscation. The below image shows the execution of the Hook Loader by the Loader Stub function. Information about the payload is passed as a parameter to the Hook Loader, including the payload address, size, entrypoint export name, and RC4 key for decryption.
Figure 13 — Execution of the Hook Loader within the Loader Stub function.
The dex command saves the received payload to disk at the path %LocalAppData%\wab.exe and then executes it using the WMI interface. The use of WMI for process creation was also observed in Ramnit.
For persistence, Bumblebee copies itself to the %AllUsersAppData% folder and creates a VBS file using WScript designed to execute the copied binary. Finally, a scheduled task is created which executes the VBS script when run.
For deletion, Bumblebee executes a Powershell command designed to delete itself from disk and then exits.
Comparisons with Ramnit
Overall, the similarities between Bumblebee and Ramnit appear quite stark, despite the functional differences. They both make use of the same hooking library and injection code, and they both contain the same lists of injection targets. Even though the injection code can be traced back to the publicly available Gozi source, both Bumblebee and Ramnit use a customised version of it which includes control flow flattening obfuscation within the LoaderStub function.
Both malware families make use of the intermediary Hook Loader binaries, and both specifically use the same version of the Hook Loader which has the internal name RapportGP.dll and the ability to decrypt the payload using RC4.
The string Z:\hooker2\Common\md5.cpp appears in the 2021 Ramnit Hooker2 binary and Bumblebee, and the Ramnit samples also use the internal name hooker2.dll. Based on analysis of the code, it appears that Bumblebee is likely derived from the Ramnit Hooker2 project but combined with code from the Camellia Loader.
We also looked at the PE Rich Headers present within the headers of the Bumblebee and Ramnit binaries and found some interesting similarities. The Rich Header is a chunk of data present near the start of every PE binary built using Microsoft Visual Studio; it contains information about the build environment and the products and versions used during the compilation of the malware. This can be used as a fingerprint for the malware’s build environment and provide interesting insights during comparison between samples.
Comparing the Rich Headers of the Bumblebee samples with the Ramnit Hooker2 samples showed a remarkably similar collection of compiler products and versions, despite the significant functional differences, indicating that both may have been built in the same environment.
Figure 14 — A comparison of the PE Rich Header contents for a Ramnit Hooker2 sample (left) and Bumblebee (right)
Following the hooks
As previously discussed, much of the injection related code within Ramnit and Bumblebee can be traced back to the leaked source code for the Gozi trojan. However, we were curious about the hooking library used in both, as it did not seem to match the hooking code found within Gozi nor any other publicly available code we could find. It does share some similarities with the hooking code from the leaked Zeus trojan code, and may have been based on that originally, but has been modified significantly since.
Searching for the hooking code within malware repositories such as VirusTotal revealed some interesting connections.
The Trickbot banking trojan was released towards the end of 2016, less than a year after the take down of its predecessor Dyre. Trickbot was originally released in conjunction with two modules, GetSystemInfo and InjectDLL, with the former gathering information about the infected system, and the latter providing web inject functionality.
Examination of Trickbot samples relating to its injectDLL or browsers_engine module uncovered use of the same hooking library found within Bumblebee and Ramnit samples. These hooking functions are found even in the very earliest iterations of the modules dating back to 2016. The version of the code used in the Trickbot modules is almost identical to that used in Ramnit/Bumblebee, and some examples are shown in the images below.
Figure 15 — The hook store initialisation function used in an early version of the Trickbot web inject module
Figure 16 — The hook creation function within an early version of the Trickbot web inject module bears a strong resemblance to the version used in Ramnit and Bumblebee
Interestingly our investigations also led us to several NeverQuest, aka Vawtrak samples, and it is here that we finally reach the end of our trail and potentially the origin of this hooking library.
NeverQuest is an older banking trojan which was active from 2013 through to early 2017 and is thought to be the predecessor of IcedID. The group behind NeverQuest were thought to have close ties to the Dyre/Dyreza group, which was the predecessor of Trickbot, and IcedID and the Trickbot group continue to share that close relationship.
We analysed a cross section of NeverQuest samples generated in 2013, 2014, and 2016, and were able to observe the active development and evolution of the hooking library. The latest NeverQuest sample we analysed was created in May 2016, five months prior to the release of Trickbot and its web inject module. The state of the hooking code in this 2016 NeverQuest sample is a very close match to that then used in the Trickbot modules several months later. Several other code overlaps were also observed between the two, which can’t easily be explained by coincidence or traced to publicly available code. This suggests that there may have been some code sharing, or potentially even a sharing of developers between the two groups at this time. Given the reported ties between NeverQuest and Dyre at the time, it’s possible that the former may have shared code or resources with the latter in order to help get Trickbot up and running after Dyre’s takedown.
The below images show an example of the evolution of one of the functions within the hooking library from 2013 to 2016. The version found in the 2016 sample bears close resemblance to the Trickbot equivalent above, and to the versions used in Ramnit and Bumblebee later on. The size of the 32-bit hook item structure used by library also changes over this time, from 75 bytes in the earlier NeverQuest samples to 71 bytes in the 2016 sample. The size remains at 71 bytes throughout its later use in Trickbot, Ramnit, and Bumblebee.
Figure 17 — The hook creation version as found within a 2013 variant of NeverQuest. At this point the hooking library was still in development.
Figure 18 — The hook creation version as found within a 2014 variant of NeverQuest. At this point the function appears to have been expanded to manage different use cases.
Figure 19 — The hook creation version as found within a 2016 variant of NeverQuest. Here the function has been simplified again, and the hook item structure size reduced to 71 bytes. This version of the code closely resembles that used in Trickbot, Ramnit and Bumblebee.
In June 2018, CheckPoint reported on a new banking Trojan named Karius that was under development and noted code overlap between Karius and Ramnit, Trickbot and Vawtrak (NeverQuest). We analysed a Karius sample as part of this investigation and found it to contain the same hooking code as the other samples discussed in this report. The structure of the code was also observed to bear a striking resemblance to that of the Trickbot web inject module, and it seems likely that Karius was developed by someone who had access to that source code.
Scroll to view full table
- Ensure anti-virus software and associated files are up to date.
- Search for existing signs of the indicated IOCs in your environment.
- Keep applications and operating systems running at the current released patch level.
- Do not install unapproved apps on a device that has access to the corporate network.
- Exercise caution with attachments and links in emails.