Integrating application whitelisting into an OS’s security stack has forced attackers to find new ways to use their tools and infiltrate a target’s environment without getting detected. Take this incident observed in a Cybereason customer environment when DLL hijacking was used to run Mimikatz using a process that was signed and verified by Oracle.
The Cybereason platform detected unpack200.exe exhibiting behaviors associated with credential theft. In this case, unpack200.exe was running a Mimikatz command line. Mimikatz is a well-known tool used for credential theft. It extracts plaintext passwords, hashes, PIN codes and kerberos tickets from memory. Mimikatz can also perform pass-the-hash, pass-the-ticket or craft golden tickets. Most antivirus tools, among other security products, detect Mimikatz. Attackers usually use different and customized Mimikatz payloads, including obfuscation and packing techniques, to evade antivirus detection.
Unpack200.exe is a common tool for unpacking JAR files. The image file of this process is signed and verified by Oracle and is benign. As the figure below shows, there are no JAR files in it.
This command dumps user information and credentials from the Security Account Managers (SAM) database and from the memory of the lsass.exe process. It contains NTLM, and sometimes LM hash, of users’ passwords.
The attackers used a DLL hijacking vulnerability in unpack200.exe. In this technique, attackers abuse the way Windows looks for DLLs to load into a program.
Windows searches for DLLs needed by executable in a specific order as well as by name and doesn’t verify its signature. If the executable is not looking for some DLL via hard coded path, using DLL redirection or using a manifest, a malicious DLL can be placed in the search order, and the executable will load it. The system searches for the DLL at load time as described :
1. The directory from which the application load
2. The system directory - uses the GetSystemDirectory() function to get the path of this director
3. The 16-bit system directory
4. The Windows directory - uses the GetWindowsDirectory() function to get the path of this director
5. The current directory
6. The directories that are listed in the PATH environment variable
By using this method, attackers can gain persistence by impersonating an OS DLL, in an OS default directory, forcing the malicious DLL to load in the machine’s normal workflow.
Attackers can achieve privilege escalation using this method by forcing their DLL to be loaded into a program that’s configured to run at a higher privilege level, such as administrator or even SYSTEM. This technique can cause an OS process, running with high privileges, to execute the malicious DLL in the OS processes context. In some cases, this type of attack can stay unnoticed. The malicious DLL can redirect the process execution flow back to the original DLL.
In this campaign, which was customized to target this business analytics company, attackers exploited this Windows mechanism to force a legitimate process to load their malicious DLL.
As the images below show, the abused executable was signed and verified by Oracle.
The attacker used the name of the Visual C++ runtime DLL, the first module to be loaded, and placed it under the same directory as the legitimate process “unpack200.exe”, which is a JAR files unpacking tool. Every process that was compiled with CPP using Visual Studio will look for this kind of DLL.This means that every process, even legitimate and signed ones, can be easily abused with this technique.
With only one generic antivirus engine detection, VirusTotal doesn’t flag the malicious DLL
Further investigation by Cybereason’s hunting team revealed that the malicious DLL contained malware-like behavior such as anti-debugging technique and file manipulation capabilities. Simulating this attack in a replicated environment uncovered this malicious DLL’s real nature.
The DLL contains Mimikatz code with some string obfuscation and binary packing. The attackers used the same command syntax as one would use to execute the original Mimikatz tool.
As shown below, when disassembling the DLL, we can see that the DLL will execute its malicious content only when the process that tries to load it is called unpack200.exe. The process needs to be verified by name. Otherwise, the ExitProcess() procedure is invoked.
Eventually, executing unpack200.exe with the malicious DLL, unpacked and deobfuscated the code in the DLL and loaded the Mimikatz interface. In an attempt to avoid standard antivirus detection, the attackers used a custom compiled version of Mimikatz that had some modifications to its strings.
With attackers looking for creative ways to infiltrate a target’s environment (like using a process that was signed and verified by Oracle for malicious activity), behavioral-based detection is critical to detecting adversaries. Signature-based detection would not have flagged the incident described in this post since attackers abused a signed and verified process.
In fact, the attackers attempted to circumvent antivirus detection by using a customized version of Mimikatz that wouldn’t get picked up by antivirus products. The organization detected Mimikatz by looking for how it behaves, not for the tool’s files. With behavioral detection, every lead counts: even the smallest details, when explored, can uncover a full campaign.
Research conducted by Niv Yona, Kohei Fujikawa, Amit Serper, Yuval Chuddy, Oren Ofer and Eran Tamari. For more security research, check out Cybereason's research blog.