Malware Evasion Techniques Part 1: Process Injection and Manipulation
September 15, 2019 | David Krivobokov
Malware developers are perpetually on the look-out for new techniques that will enable their malicious files of "destruction and chaos" to stay undetected. This not only means going undetected on the compromised machine but more importantly, hiding their malicious indicators and behaviors from detection tools. For this reason malware developers invest a lot of time and resources to discover techniques that will enable them to hide malicious files from automated threat analysis systems and detection and response tools by drawing on the latest in evasion techniques.
As solution providers wisen-up to the latest evasion techniques, malware developers are forced to adjust and become even more enterprising in their techniques, effectively creating a perpetual cat and mouse race. In Deep Instinct's Malware Evasion Techniques blog series we reflect back on this series of developments and provide a basic summary for those interested in learning more on the topic.
Often to avoid detection, malware will leverage various evasion techniques that involve process manipulation to execute malicious code, and especially process injection. When malware is running on the infected machine its process can be easily detected by analysts and security programs, by just checking the list of running processes and filtering out the expected processes that are part of the operating system or belong to installed applications. To hide on the infected system, malware can load its malicious payload inside a legitimate process without arousing suspicion.
Process injection and manipulation is a prominent method used by attackers due to the stealth it offers and its ability to evade both cybersecurity analysts and solutions. Attackers are no longer concerned with just loading malware on to victims’ devices but are also innovating the way they embed it into existing processes so that they can remain undetected and launch and execute additional successful attacks. And with so many viable techniques and variations, it becomes increasingly difficult for analysts and software to identify its existence in what appears to be seemingly normal processes running on their systems. Now more than ever it is imperative that cybersecurity companies provide advanced malware detection technologies and capabilities that are effective irrespective of who made the latest move – the cat or the mouse.
In this blog, the first in our series on malware evasion techniques, we present the most widely-used process injection and manipulation techniques, provide examples for malware families that use these techniques, and explain how to detect them.
DLL injection is one of the simplest and most common processes injection techniques. To execute a malicious Dynamic-Link Library (DLL) under another process malware writes the path of a malicious DLL into a remote process’ address space. Then, to invoke the DLL's execution, the malware creates a remote thread from the targeted process. This technique implies that the malicious DLL is stored on a disk before injecting it into the remote process.
Steps for DLL injection:
- Locate the target process by traversing the running processes and call OpenProcess for obtaining a handle to it.
- Allocate the space for injecting the path of the malicious DLL file to the target process with a call to VirtualAllocEx with the targeted process handle.
- Write the path of the DLL into the allocated space with WriteProcessMemory.
- Retrieve the address of LoadLibrary from kernel32.dll, that given the path to DLL, loads it into memory (does not execute it though).
- Call CreateRemoteThread passing it the address of LoadLibrary causing the injected DLL file’s path to be loaded into memory and executed.
The downside of this technique is that the malicious DLL file must be stored on disk, which exposes it to detection by regular security solutions. Nevertheless, this technique is employed by malware developers and is widespread in the wild. For example, Poison Ivy, a popular and long-standing RAT, uses DLL injection. Poison Ivy has been involved in several APT campaigns recommending itself as a tool of choice by APT groups for espionage operations.
Reflective DLL Loading (Injection)
Reflective DLL injection, unlike regular DLL injection described above, is a stealthier technique introduced by Steven Fewer, for injecting and executing a DLL inside another process. For some, this technique might be considered as “self-loading”, rather than process injection. To avoid storing the DLL on disk, malware will have to manually map the DLL’s raw binary into virtual memory, as the Windows loader would do, but without calling the Windows API’s LoadLibrary that might be detected by tools monitoring the LoadLibrary calls. It will be enough to get the correct address of the injected export function that will fully load and map remaining components of the DLL inside the target process, e.g. ReflectiveLoader().
Reflective DLL injection can be summarized in the following steps:
- Locate and open the target process with Read-Write-eXecute permissions using OpenProcess.
- Calculate the size of the DLL data that needs to be allocated in memory.
- Allocate enough space in memory for the DLL with VirtualAllocEx.
- Write DLL’s raw data into the allocated space.
- Calculate the offset to the exported function used for doing reflective loading found in the DLL, e.g. ReflectiveLoader().
- Execute the reflective loader function in the target process using the CreateRemoteThread passing it the offset of the ReflectiveLoader().
- The ReflectiveLoader() will search for the Process Environment Block (PEB) of the target process using the appropriate CPU register. The located PEB will be used to find the address of kernel32.dll in memory and other required libraries.
- Traverse the located kernel32’s exported functions to find the correct addresses of Windows API functions that’ll be used for fixing the addresses of other DLL’s imported functions like LoadLibraryA, GetProcAddress, and VirtualAlloc.
- Using the functions from step 8 load the DLL into memory and call its entry point.
Recent Ramnit variants have been spotted employing a reflective DLL loading to execute its modules under legitimate processes. Ramnit is a widespread banking Trojan that has been active since 2010. In 2015 Europol has brought Ramnit’s C&C servers down, but it didn’t cease its activity and is still one of the popular banking malware in recent years.
Portable Executable Loading (Injection)
Just like with reflective DLL loading, Portable Executable injection and loading does not require the DLL (or executable) to be stored on disk. And similarly, PE injection involves some work to correctly load and execute the injected PE. To load and execute the injected PE, malware needs to calculate the new base address of the injected PE to properly change its fixed addresses. To accomplish this, malware will traverse its relocation table inside the target process to compute the correct addresses.
PE Loading in a nutshell:
- Using the PE header of the current image, get its base address and size.
- In the processes injecting the PE, allocate memory for the image using VirtualAlloc.
- Copy the image into the locally allocated memory using memcpy.
- In the target process, allocate memory for the injected image with VirtualAllocEx.
- In the process injecting the PE, find the relocation table offset from loaded in local memory.
- Fix all the absolute addresses of the image to work with the address returned by VirtualAllocEx, by traversing the relocation table from step 5.
- Inject (copy) the image from the local process to the target process’ allocated memory using WriteProcessMemory.
- Find the correct address of the exported function to be executed inside the target process:
a) Subtract the function’s address in the injecting process from the base address
b) In the target process, add the result from (b) to the address of the allocated memory
9. Execute the injected by creating a new thread with CreateRemoteThread passing it the remote address of the function from step 8.
Note: In addition to calculating the base address and fixing the absolute addresses of the injected PE, it might be necessary to fix the injected IAT to call imported functions from. Check step 8 from “Reflective DLL Loading” shown above.
In practice, PE loading has been employed by several actors, including Turla – a Russian-based APT group. Turla’s espionage platform has employed PowerSploit’s Invoke-ReflectivePEInjection.ps1 for PE loading into random processes.
Another approach for making the legitimate process run the malicious payload is process hollowing. In this technique, a legitimate process is started by malware in a suspended state. Then, while in a suspended state, the target process’ memory is unmapped (hollowed) to contain the malicious payload.
Steps for process hollowing:
- Start a new process in a suspended state by calling CreateProcess with CreationFlags parameter set to CREATE_SUSPENDED=0x00000004.
- Unmap the memory of the target process using ZwUnmapViewOfSection or NtUnmapViewOfSection.
- Allocate space in memory for the malicious payload using VirtualAllocEx.
- Inject the payload in the allocated memory region with WriteProcessMemory.
- Change the execution point of the targeted process to start from the correct point in the injected payload by calling GetThreadContext.
- Resume targeted process execution by calling ResumeThread.
Process hollowing was seen in very popular banking malware – TrickBot. Since 2016 TrickBot has been a major threat compromising online banking (and other services) accounts of thousands of victims. Process Hollowing is only one of several evasion techniques employed by Trickbot over the years.
The Next Level
In the past years new process injection and manipulation techniques have been introduced and are rapidly gaining popularity amongst malware developers as well as security researchers – AtomBombing and Process Doppelgänging.
AtomBombing relates to a set of process injection techniques that utilize Windows’ APC (Asynchronous Procedure Call). It uses the global atom table, used by Windows for sharing and storing data, to store its malicious code and be executed by a legitimate process. This technique has been observed in Dridex – a popular banking trojan.
Process Doppelgänging relies on the Windows Transactional NTFS (TxF), a feature that ensures data integrity by allowing only one transacted handle to write to a file, preventing the write operations by other handles. Other handles may read the version of data stored at the time when the initial write handle was obtained. If the application fails during the write operation, TxF performs a rollback to the initial version of the data. In Process Doppelgänging the TxF transaction created from a legitimate application is used to overwrite file contents visible only within the context of this transaction with malicious data. From here, similarly to other injection and loading techniques, the malicious data is loaded into memory. Then, the overwritten data is rolled back by TxF, removing the evidence of malicious data from disk. Finally, the loaded malicious code gets executed by a newly created process. This technique is becoming popular and is being employed by malware families like AZORult, LokiBot, Pony Stealer and others.
Malware will always seek a way to infect its victims. “Good” malware will infect its victims with minimum impact on the targeted system, disguising its presence as much as possible to avoid suspicion. Here we presented a basic overview of some of the evasion techniques seen in malware that attempts to disguise itself inside legitimate processes. We hope this overview will be a good starting point for understanding malware evasion techniques. Be aware and stay safe.
Read the next blog in the series focused on anti-virtualization malware.