This is the first entry in the Malware Injection Techniques article series that we will be writing about.
The ultimate goal of any malicious software is to be able to execute its code without any hindrance. In the past, security software such as Anti-Virus applications mostly relied (it is still one of the features today) on signature-based detections. This means that they use a known list of indicators of compromise (IOCs) – these may include specific attack behaviors or as simple as file hash and compare them to the examined sample. This is the biggest limitation of signature-based detections as they can only detect known attack patterns.
This very plain method proved to be very inefficient these days. For instance, let’s assume a very trivial example if AV would rely solely on file hash detection1.
An exceedingly minor change in the malicious code would render a whole new hash value for that same malware, thus making it look like an unknown malware (since the new files hash does not match to any in the list of IOCs). And we are talking about changes like simply changing one of the variables names, as an example. So, it was very straightforward for adversaries to generate new file hashes for the same malware, and the AV providers would need to play Cat & Mouse game to keep up with the latest. This eventually led AV providers to develop more sophisticated tools. One of the most common terms we may spot today is heuristic analysis.
Heuristic analysis executes the suspicious program in an isolated environment where it monitors commands as they are performed, and other activities related to execution of the given file. However, it is still not perfect as the effectiveness relies based on experience, which means that the AV engine still makes some sort of comparison to the other known malicious behavior, but it is not limited to some pre-defined patterns.
Going back to malware injection, malware developers are now tasked to evade this detection. One of the best evasive techniques is to abuse legitimate software or processes to execute malicious content. This is where malware injection techniques come in.
DLL injection technique is perhaps the most basic one to start with. The idea of classic DLL Injection is to put the path of a malicious DLL into the address space of a legitimate process and then establish a remote thread to that process, which can control the execution of the injected code.
So, how does it work? Let us examine a very basic POC of a classic DLL injection.
The goal of this POC code is to inject a DLL into a Notepad process and execute it. Let’s walk through it.
First, we receive a handle to LoadLibraryA function, which we will use to load our malicious DLL into allocated memory of the target process.
Next, we will obtain a handle to our Notepad process, which should be running. In our simple POC we just hardcoded the PID value of a running Notepad process. Note that PID changes with each new execution.
Following that we have allocated some memory in our target process, so that LoadLibrary function will be able to inject our evil DLL into that process. The memory allocation should be the size of the evil DLL’s path.
Then we use WriteProcessMemory to write the DLL’s path name to the allocated memory space of the targeted process.
Finally, we use CreateRemoteThread to create a remote thread starting at the memory address where LoadLibrary was stored. We also provide the function with information on memory address of the DLL path from earlier.
And this is basically it. Now when this POC code executes, it should inject our evil DLL into Notepad’s process and therefore execute the malicious code within it.
Here are the downsides of this specific technique:
Malicious DLL still needs to be saved on disk
Malicious DLL will be visible in the import table
So, why not simply prevent all process injections? Well because Windows and other applications use these mechanisms in legitimate way. For example, AV software itself uses this mechanism to inject itself into applications. Debuggers also inject themselves into applications to allow developers troubleshoot their programs. For these (and many more) reasons, we cannot simply prevent all process injections occurring and that is why it still remains as relevant evasion technique.
Depending on quality of AV tool, it is still possible to determine with high probability which is the malicious injection technique. For instance, performing dynamic analysis in an isolated environment would reveal something like Notepad process loading a random DLL from the disk, typically not associated with Notepad process. This could trigger a suspicion and reason to prevent further execution. Such anomaly-based detections are more advanced and often come with a trade-off with increasing false positive counts.
This is the first entry in the series of Malware Injection Techniques. In the next series we will continue with other types of injection techniques.
1Most of today’s AV products do not check only the hash value