DLL hijacking is not a new technique by any means, but that makes it no less effective. When a common Windows signed PE is set as a scheduled daily task, the average individual or IT staff member likely wouldn’t think anything of it. It would be just another Windows task necessary for the operating system (OS) to perform its normal operations. But that isn't always the case.
Cylance recently took note of malware leveraging SrcTool.exe, a utility signed by Microsoft. SrcTool is susceptible to DLL search order hijacking when a malicious DLL with the same name and exports is found before the legitimate DLL. In particular, SrcTool imports functions from DbgHelp.dll, which is present on all supported versions of Windows.
The malware acts as a trojan, implementing just the needed functions required by SrcTool to hijack the loading process and overwrite the initial instructions of SrcTool with its own malicious code. This maligned pairing is an attempt to hide the malicious DLL from both static and dynamic analysis.
In comparison to the original DbgHelp.dll, the first thing to notice is a drastic size differential. The legitimate DbgHelp.dll from a standard Windows 7 SP1 installation is larger than 800 KB, while the malicious DLLs range in size from 23 to 24 KB (Figure 1).
Figure 1: Size Differential Between Legitimate (Left) and Malicious (Right) Dbghelp.dll
The purpose of the typical DLL is to export functionality to be used in other programs; so the exported functions of a DLL can mean a great deal. When compared to the original, the malicious DLL mimics only a few of the functions. The original DLL contains 206 functions, while the malicious one only has 22, and even contains an export that isn’t shared with the original, ‘DLLMain(x,x,x)' (Figure 2, highlighted in red). This indicates that the malicious code is not made to duplicate the full functionality of the original.
Figure 2: Comparison of Exports Between Original (Left) and Malicious (Right) dbghelp.dll
The functions exported by the malicious DLL can almost act as a fingerprint, leading us to SrcTool as the target of the DLL search order hijack. The exact imports used by SrcTool.exe are those exported by the malicious Dbghelp.dll (Figure 3). So the only functionality that this malicious DLL attempts to duplicate is the code necessary to cause the OS to select the malicious DLL during a search for SrcTool’s dependencies. As we’ll see, SrcTool merely acts as a carrier and is never meant to run its own code.
Figure 3: The Imports of SrcTool.exe from Dbghelp.dll (Left) Compared to Those Exported by Malicious Dbghelp.dll
As with all DLL search order hijacks, the goal is to gain code execution. There are a number of ways to achieve this goal and the malware in this analysis chooses a fairly direct path by overwriting the entry point of the loading process. A comparison of the DLL entry-point functions of the two files shows a simple code flow for both libraries with one important difference. The malicious DLL calls another function before returning execution to the caller. This function (Figure 4) is quite complex, but ultimately will invoke the DllMain function previously highlighted as an additional export.
Figure 4: Comparison of DLL Entry-Point (Malicious DLL on the Left, Real DLL on the Right)
DllMain simply checks that fwdReason equals 1 and if so, sets a stack variable to the offset of MaliciousFunction and then calls OverwriteEntryPoint.
OverwriteEntryPoint was so named because it does exactly that. The function calls a subroutine that finds the entry-point of the loading process and overwrites it with a JMP (0xE9) instruction to the address passed in on the stack, i.e. the address of the malicious function (Figure 6). This essentially hijacks the execution of Srctool to execute the malicious function when the system finishes loading dependencies and passes control to the fully initialized process.
Figure 5: DllMain in the Malicious DLL
Figure 6: Function OverwriteEntryPoint in the Malicious DLL
An inspection of the MaliciousFunction reveals a clear effort to hide malicious activity by getting a handle to the console window (assumed present when running Srctool), minimizing the console and then hiding it. The function then sets a local variable used as a filename to a hardcoded value (Figure 7). The way the malware author sets this value one byte at a time is a further attempt at obfuscation.
Figure 7: Deobfuscation and Execution of Data in the ADS
The hardcoded filename uses an alternate data stream (ADS) nomenclature, which the OS natively handles with the core file I/O routines. This is an excellent hiding technique. Files with alternate data streams are not differentiated in any way from normal files. A user or administrator would never notice the ADS file unless they knew to look for it.
Once the function reads the data from the stream, it deobfuscates the bytes (Figure 8) and eventually allocates memory on the heap and executes code from this data. Obfuscation is necessary because many security tools will automatically check for ADS files and scan their contents if found. The obfuscation employed would throw off any file type and string checks. The malicious code ultimately ends with a call to ExitProcess, supporting the theory that SrcTool merely acts as a carrier to mask the malicious code.
Figure 8: Deobfuscation and Execution of Data in the ADS
While Dbghelp.dll is clearly malicious, it is useless without several key environmental constraints in place. Without SrcTool and the payload in the ADS file, this DLL isn’t capable of malicious activity. The use of SrcTool seems to be purely for camouflage and may be set to run as a scheduled task or at startup. As a signed executable, this would not raise many red flags among most users or IT staff.
While we can’t determine the ultimate goal of this malware without the payload in the ADS file, we can conclude that this is an excellent persistence mechanism able to hide in plain sight.
Unfortunately, DLL hijacking is more of an implementation and logic flaw in the executable itself, so user side mitigation and prevention options are not very effective. The only real configuration method to help prevention is to ensure that SafeDLLSearchMode is enabled. By default, this is enabled on all support versions of Windows. In addition, software developers could help mitigate these attacks by making all their DLL searches a direct path, rather than relying on the DLL search order to find the DLL for them.
Seeming random data in ADS files may also be an indicator that some malicious activity is present. The presence of ADS files themselves is not a strong indicator of malicious activity, since they are used in various ways by the OS as a core feature of the NT file system.
If you use our endpoint protection product CylancePROTECT®,
Indicators of Compromise (IOCs)