Last week the Bromium Labs team was contacted by a Fortune 1000 customer that detected an interesting attack via one of their installed LAVA sensors. We get such events frequently from our customers; however this attack was a bit different. The attack was a classic waterhole attack targeting potential viewers of a technology startup in the Oil and Gas sector. Interestingly, this attack occurred days after the company announced a sizable funding grant. It’s likely that the attackers were expecting more traffic to the website and hoped to increase their chances of a successful infection. The names of the companies involved are redacted and they have confirmed that the infection has been remediated and both have confirmed that no sensitive information was leaked.
Attacks on the ONG sector are not new and attacks targeting companies in this sector might be premeditated. Bromium Labs is working with the target and we’ll update the blog if there’s any significant development.
The event we received was dated 09/04/2014. The alert produced the following malware graph which confirms the infection, at a glance (click to enlarge):
After analyzing the captured forensic evidence, we found some interesting traits.
Anatomy of the Attack
The malware was leveraging the CVE-2013-7331, which was unpatched at that time. There have been several reports of malware exploiting this vulnerability in the wild. If the ‘low’ severity from Microsoft is not motivating to patch, then hopefully some of these details are useful to jump over that hoop. It’s obvious that various exploit kits are using this vulnerability actively in the wild.
In this case, the script on the compromised web server looked for the presence of Kaspersky and Trend Micro drivers on the victim machine by leveraging the XMLDOM vulnerability. It would appear that they tested their malware with these two popular engines and found they were able to detect the malware used.
Let’s look at the sequence of redirects. One of the .JS files on the server was modified with the following cookie based code:
This led to another redirect (this time just plain iframe) and then to yet another one. The latter “hijacks” onmouseover and onhover events of the page DOM:
Then an iframe is created pointing first at google.com but later its SRC property is overwritten with the malicious URL. The popup_open function checks if the page referrer is in the blacklist. In our case the blacklist was empty. After that setTimeout is called. The handler of this timeout is the function overriding the src property of the iframe.
This finally leads a victim to the drive-by-download page (which actually is a version of the Sweet Orange exploit pack). The attacking code is fairly small – just 17 KB. It doesn’t use PluginDetect library, which became a de facto standard for exploit kits. Instead it goes with isVersionSupported and trial and error via try…catch.
Here’s the list of exploit CVE’s that we’ve confirmed from the forensics capture:
- Flash – CVE-2014-0497
- Java – CVE-2012-1723
- IE– CVE-2013-2551
The exploits code seems to be taken from Metasploit Framework which is also quite typical.
Dropper and Obfuscation
The dropped Trojan (MD5 = a4f10d4ed6253bad9fff4687ed6b8c94) disguises itself as the Windows folder, which can evade most people at first glance:
Its dropper is written in VB5 and uses a common obfuscation technique. It creates the instance of itself and modifies the code section. The payload is self-contained and does not rely on any import functions. Instead it resolves process names on the fly using the hash technique. First it gets the base address of NTDLL.DLL in PEB->LoaderData->InLoadOrder, then it looks up the address of an undocumented function LdrGetDllHandler. Using this function it gets the base address of KERNEL32.DLL.
Here’s the hash function implemented in python:
if not funcname:
hashval = 0
for c in funcname:
hashval ^= (ord(c)|0x21)
hashval = rol(hashval,0x0B, 32)
hashval &= 0xFFFFFFFF
def rol(a,b, bits=8):
The second stage payload is de-obfuscated into memory. It’s not a PE file, but a binary blob, which has the following structure.
- Table of API calls containing addresses of the functions
- Strings used in the program
- Executable code
The executable code is also self-contained and resolves the necessary functions on the fly.
The second stage is responsible for code injection:
- Check if it is a 32 or a 64 bit system
- In the former case choose system32\wuauctl.exe as injection target, in the latter – syswow64\svchost.exe
- Set environment variable ‘src = <injection target>‘
- Launch the injection target and replace its image with the copy of itself
- Modify the entry point of the target process so that it follows another routine
The injected code then de-obfuscates yet another chunk of code using the same de-obfuscation function resulting in the same structure. You can find the list of the imported functions and strings in the end of the article.
The Trojan looks for several processes in the system (using CreateToolhelp32Snapshot) and won’t run if any of them is found. It doesn’t contain the names of this processes, only hash values that are:
- 0x4CE5FD07 – vmwareuser.exe
- 0x8181326C – vmwareservice.exe
- 0x31E233AF – vboxservice.exe
- 0x91D47DF6 – vboxtray.exe
- 0x0E8CDDC54 – sandboxiedcomlaunch.exe
- 0x8C6D6C – sandboxierpcss.ex
- 0xA8D0BA0E – procmon.exe
- 0x0A4EF3C0E – wireshark.exe
- 0x5CD7BA5E – netmon.exe
The malware tries to further verify if the victim is running inside Sandboxie by calling GetModuleHandleA(“sbiedll.dll”).
Finally, it queries the values stored in HKLM\SYSTEM\CurrentControlSet and looks for the virtualization software artifacts:
These methods are not the smartest ones, but they do great job evading automated analysis tools such as Cuckoo Sandbox (which usually runs on Virtual Box or VMWare). It also won’t show malicious activity in presence of some monitoring tools. So dynamic analysis alone is not very useful in this case.
The resulting payload can be described as malware installation tool. It’s a type of Trojan that persists on the infected system and install another malware send from the command and control server. Its workflow goes like this:
- Get system and volume information
- Relocate itself to %allusersprofile%\Local Settings\Temp\<random name>
- Start the thread that runs malicious code stored in the HKLM\Software\Microsoft registry (if any hence on the first run it won’t do anything, since all the malcode is fetched from the Web)
- Start the thread that malicious DLLs stored in the registry (if any)
- Send system information to the C&C
- Extract command code from the response and perform one of the following functions:
- Write on disk and execute the received PE file
- Execute the received PE in memory and write its encrypted contents to \Software\Microsoft\<%08X>%checksum as REG_BINARY value
- Load the received DLL and run the entry point; then save it’s name in the registry
- Delete previously loaded files
- Delete previously set registry values
- Replace itself with newer version, set up autorun and execute
- Delete all binary values in HKLM\Software\Microsoft and execute whatever is inside the ‘Load’ subkey in the same key
What interesting about this Trojan is that it stores the malicious executable code in HKLM\Software\Microsoft registry key. This is not the first time we have heard about this trick though. The user named EP_X0FF first reported similar specimen on kernelmode.info forum in the Malware section.
There are two types of data it stores in the registry:
In this case the data has the following structure:
- Signature 04034B50 (that’s how it knows it’s actually executable code)
- Size of unpacked data
- Size of packed data
- Checksum of the unpacked data
These values are only executed in memory and are not written on disk. The encryption used is a Vigenere cipher mod 256 with the hardcoded key. Before encryption some simple compression algorithm was used.
So in order to execute this kind of payload the Trojan checks the signature, decrypts and unpacks the data and verifies the checksum. The checksum algorithm is very simple and similar to the hash function mentioned above.
Next addresses of all the imported functions are resolved and the program calls the entry point (looked up in the PE header).
In this case the name of the value is the name of the DLL previously saved at %allusersprofile%\Local Settings\Temp and the data is one of the exported functions. So to execute this payload the program calls LoadLibrary, GetProcAddress and calls the exported function.
Malware installation tools like this are widely used to install bank Trojans and more recently crypto-ransomware. This explains the peculiar choice of where to store the executable code. Perhaps according to their tests most AVs do not scan the registry thoroughly enough. Clearly it is an attempt to improve user level persistence and overall stealthiness. It’s difficult to say how effective this method is, but surely it makes a good marketing point for advertising this malware on underground message boards.
Water hole attacks have been around for some time and attackers are continuing to use this tried and true attack vector while staying ahead of the defenders detection techniques. This attack is yet another example of the ongoing game between the defenders efforts to detect attacks and the attackers’ efforts to evade detection and collect the buried treasure. The authors of this attack paid a lot of attention to stealthiness, starting from the cookie-based redirect and driver fingerprinting to monitoring tools detection. This might narrow down the target audience of the attackers but improve the success rate. Which makes perfect sense – there are plenty of vulnerable machines out there – why bother infecting protected ones?
Appendix A. List of Imported Functions
Appendix B. List of Strings
/%s HTTP/1.1,0Dh,0Ah ; DATA XREF: sub_3D14B5+12Eo
GET /%s HTTP/1.0,0Dh,0Ah ; DATA XREF: sub_3D14B5+146o