Following on from the previous post, Daniel continues exploring the Gootkit banking trojan, revealing its persistence techniques and other capabilities.
The Gootkit Banking Trojan was discovered back in 2014, and utilizes the Node.js library to perform a range of malicious tasks, from website injections and password grabbing, all the way up to video recording and remote VNC capabilities. Since its discovery in 2014, the actors behind Gootkit have continued to update the codebase to slow down analysis and thwart automated sandboxes.
In the previous post, I explored Gootkit’s Anti-Analysis features. In this post, we’ll take a look into the first stage of Gootkit and figure out how it achieves persistence on an infected system, as well as reveal some other tricks it has available.
MD5 of Packed Sample:
Before we get into the persistence and C2 communication routines, let’s first take a look at the onboard configuration, and how it is stored.
The first time that the configuration is “mentioned” in the sample is immediately after the anti-analysis mechanisms that were covered in the previous post. A quick glance at the code may leave you thinking that Gootkit is decrypting some shellcode to be used by the sample – but running this in a debugger shows otherwise. The decryption routine is fairly simple; a basic
XOR loop with a differentiating key based on
idiv calculations. The base key value is
0x22, and the
imul values are constant throughout each iteration;
0x03 respectively. A Python script of this decryption routine can be seen in the image below.
After decrypting the data manually, we can easily distinguish that this is in fact the configuration used by Gootkit to retrieve the next stage:
me.sunballast.fr koohy.top 2700 svchost.exe
Each value is split by multiple null bytes, meaning pretty much all of this configuration is null bytes. The first two values are obviously URLs, and the final value is the name of the process that the downloader could inject into. The last two values are also set as environment variables – specifically
vendor_id variable is given the value
mainprocessoverride is given the value
svchost.exe. These variables are not used in the downloader aside from setup, and so it can be assumed that it is used in the final stage. Once the environment variables have been created and assigned values, four important threads are kicked off; a C2 Retrieve thread, a Browser Injection thread, a Persistence thread, and a Kill Switch thread. Let’s start off with the Persistence thread.
In this sample of Gootkit, there are two persistence options available. First, there is the usual method of achieving persistence through a created service. In this case, Gootkit will generate a random filename, using the Mersenne Twister, based off of filenames in
System32, and then proceed to create a file under the same name in the
%SystemRoot%. Upon testing this function, a file called
msfearch.exe was created. A service is then created under the same name, and then executed. Finally, the original executable cleans up by deleting itself from disk and exiting, leaving the created service running.
The second persistence routine is a lot more interesting, and has been covered quite often before. This routine is most commonly used in Gootkit infections, as creating a service requires administrator privileges – this does not.
It starts by creating a simple
.inf file, which is given the same name as the running executable, and placed in the same directory. The contents of the file can be seen below:
Then, the sample will create a registry key located at:
And then create three values inside this key:
Count is assigned the value
0x1, Path1 is assigned the path to the INF file, and
Section1 is assigned the string
[DefaultInstall], which is also present inside the INF file. And that is the setup complete.
The way this functions is
explorer.exe will load Group Policy Objects (GPO) whenever it is loaded – specifically at runtime. What Gootkit does is it creates a Pending GPO for the Internet Explorer Administration Kit (IEAK), which points directly at the INF file. When
explorer.exe is loaded at runtime, it will execute the
[DefaultInstall] inside the created file, which will execute the Gootkit executable.
Loader Update Thread
With the persistence thread covered, let’s move onto analyzing the C2 Receive thread. This was particularly difficult to analyze due to the fact that the command and control server went offline very quickly, and so at first glance it looked like the thread was responsible for downloading the final stage and constantly updating it, but as I dug deeper, this was proven incorrect.
The function is not extremely complex – to put simply, Gootkit will check if a variable is set to 0 or 1, and if it is set to 1, it will exit the thread. This variable is only activated inside the
Kill Switch function, which we will look at soon.
Continuing on, the sample appends
/rpersist4/-1531849038 to the URL, where the
-1531849038 is the CRC32 hash of the binary – converted to decimal. Then, depending on the architecture,
rbody64 will be appended to the URL.
Then the actual connection takes place. Interestingly, there are two means of communication as well – it can either occur through WinInet functions such as
InternetOpenW, or it can occur through WinHTTP functions such as
WinHttpOpen, although I have yet to see it call the WinHTTP functions – regardless of privileges.
Before reaching out to the C2, Gootkit will first add to the headers of the GET request. These additions can be seen below:
X-File-Name: Filename X-User-Name: Username X-ComputerName: Computername X-OSVersion: 6.1.7601|Service Pack 1 1.0|1|0x00000100 X-VendorId: 2700 X-IsTrustedComputer: 1 X-HTTP-Agent: WININET X-Proxy-Present: False X-Proxy-Used: False X-Proxy-AutoDetect: False
The X-IsTrustedComputer is only set to 1 if the
crackmeololo environment variable is set, otherwise it is set to 0. This could be seen as another anti-analysis/anti-sandbox/anti-VM mechanism, although it’s difficult to say without seeing the backend.
If the connection between the sample and the C2 fails, it will attempt to connect to the other C2s found in the configuration. If the connection is successful and the server returns an executable, Gootkit will create a randomly named file in the Temporary directory, and execute it with the
--reinstall argument, using
CreateProcessW. As a result of this, we can fully understand that this thread is in fact an “updater” thread, which will continuously check in with the C2 server, waiting for any updates to the loader.
Now that this function has been covered, let’s move over to the Kill Switch function briefly, before going onto the Browser Injection function.
The Kill Switch thread is only triggered if
uqjckeguhl.tmp is located in
..Local SettingsTemp. If the file exists, then Gootkit begins to clean up after itself – it will kill all running threads, and restart the computer. It’s quite unclear as to why this is a feature, as persistence is established before the Kill Switch thread is executed, and so simply restarting the computer will end up executing the loader again – however, if a loader update is issued and installed on the infected system, causing a reboot could be helpful in preventing several instances from running at once.
And finally, on to the Browser Injection function.
The Browser Injection function is quite interesting, as it is responsible for two tasks; executing itself with the
--vwxyz argument, and injecting two DLLs into running browsers. We’re going to focus on the second task.
In order to inject a DLL into a browser, there must already be a DLL residing somewhere – which there is. In fact, there are 2 encrypted DLLs stored in the binary; an x86 DLL and an x64 DLL, which are decrypted with a simple
XOR. What is also interesting is that there seems to be possible placeholders in other variants, as this sample checks for
0x55667788 in both DLLs, in order to replace the values with
With both executables decrypted, Gootkit alters the values to
0x3 for the following registry keys:
SoftwareMicrosoftWindowsCurrentVersionInternet SettingsZones02500 SoftwareMicrosoftWindowsCurrentVersionInternet SettingsZones12500 SoftwareMicrosoftWindowsCurrentVersionInternet SettingsZones22500 SoftwareMicrosoftWindowsCurrentVersionInternet SettingsZones32500 SoftwareMicrosoftWindowsCurrentVersionInternet SettingsZones42500 SoftwareMicrosoftWindowsCurrentVersionInternet SettingsZones52500
This results in disabling Internet Explorer Protected Mode for each security zone in use. From there, Gootkit will move onto scanning all running processes until it locates an active browser. In order to do this, it will import and call
NtQuerySystemInformation(), requesting System Process Information. This returns a list of running processes. Using this list, Gootkit will open each process, check the process architecture using
IsWow64Process(), and then CRC-32 hash the (uppercase) process name. This hash is then passed onto a function responsible for detection and injection. A list of targeted browsers and their corresponding hashes can be seen below.
Microsoft EdgeCP: 0x2993125A Internet Explorer: 0x922DF04 Firefox: 0x662D9D39 Chrome: 0xC84F40F0 Opera: 0x3D75A3FF Safari: 0xDCFC6E80 Unknown: 0xEB71057E
The injection technique used by Gootkit is nothing special, and is quite common. The sample calls
NtCreateSection, and will then map that section into the Browser using
NtMapViewOfSection. Both DLLs seem to be mapped into memory as well, regardless of architecture. Once the files have been injected, the function will return back to the Process Searching function, until another browser is detected. And that brings an end to the browser injection!
MD5 of x86 DLL:
MD5 of x64 DLL:
From a quick glance at the injected DLLs, they seem to contain a few hooking functions that seem to hook
CertGetCertificateChain, as well as potentially acting as some form of proxy to intercept requests and redirect them based on information from the C2 server or the Node.js payload – my main reasoning behind this is that infecting a VM with Gootkit and trying to browse the internet using Internet Explorer is unsuccessful, as if connections were being prevented by a proxy, although this does require further analysis.
In the next post, we will take a look at what happens when Gootkit is called with the
--vwxyz argument, and then take a quick peek into the final Node.js payload that is retrieved from the Command and Control server!