Malware Evasion through Injection pt2
In the Previous Episode we started the discussion of Malware Evasion through Injection with some basic PE-Injection Techniques moving from the very simple/ detectable methods to a bit stealthier techniques used by Malware in the Wild.
In this Episode we will continue this discussion with the same incline for each technique from it's basic implementation to more sophisticated variants if available.
DLL-Injection
DLL-Injection used to be the most common Process Injection Method Malware used to inject Malicious Payload into remote processes, it's not the case anymore because it's very easy to detect by AV Scanners. This Method involves having a Malicious File on disk which makes it not stealthy at all, the malicious executable that's responsible for injecting the Malicious DLL either download it by connecting to the C2, or drop it to disk if it exists as a resource in the binary. The Malicious Executable then injects it in a Legitimate Remote Thread it spawns by creating a remote thread from the target process passing it the PATH
to the Malicious DLL, the Dropper/Installer then exits leaving the trojaned binary running to do it's nefarious tasks.
=> Spotting DLL-Injection:
Steps taken to implement this technique is straightforward, it involves having a Malicious Executable and a Malicious DLL. On running the Malicious Executable, it performs the following:
Locating a Target Process by querying the running processes, when found, a call to
OpenProcess()
is made over the target process to obtain a handle to it.The Malicious Executable will then either Download the Malicious DLL by connecting to the C2, or drop it on disk if it exists as a resource inside the binary.
Allocating a region of memory inside the remote process with the size of the PATH to the Malicious DLL.
Calling a remote thread on the target process with
LoadLibraryA()
passed as an argument with the PATH to the Malicious DLL.The Malicious Executable will exit leaving a Trojaned Binary running in the background.
=> Implementing DLL-Injection:
Helpful APIs:
CreateRemoteThread( ... , LoadLibraryA, &allocated_memory)
this implementation of CreateRemoteThread()
is a clear give-away that the sample is performing DLL-Injection
The Famous PoisonIvy RAT been known to use DLL-Injection.
Reflective DLL-Injection
Reflective DLL-Injection is considered more stealthier than regular DLL-Injection, Since DLL-Injection involves having a DLL on disk, Reflective DLL-Injection writes the DLL's Raw Binary into a remote process in an arbitrary memory region directly to avoid storing any file on disk, this technique then doesn't rely on The Windows Loader to load the Injected DLL correctly in memory, but has it's own Custom Loader, this Custom Loader is an exported function of the Injected DLL, and is Position Independent, meaning it can be based / called from anywhere typically called ReflectiveLoader()
but can be of any name , So ReflectiveLoader()
is called either by shellcode or by a call to CreateRemoteThread()
over the target process which is then called the host process passing ReflectiveLoader()
to do the Manual Loading which is done by traversing the PEB, figuring out offsets to important Modules' exported functions to correctly load/map the DLL. This way ReflectiveLoader()
manages to sneak behind known hooked APIs responsible for loading any binary into memory. After successfully loading the DLL, ReflectiveLoader()
will then call it's image's that is correctly mapped now DllMain()
returning execution back to it's host process target process and exits.
=> Implementing Reflective DLL-Injection
In order to achieve Reflective DLL-Injection, a sample needs to go through these steps
Starting with a dropper/installer that on executing will locate a target process, obtain a handle to it, with
OpenProcess()
.With the Malicious DLL's Size, the malicious executable will either download the Malicious DLL/ load it from the resources section if it exists as a resource in the binary.
Allocate enough memory space in the remote process in an arbitrary location for the DLL using
VirtualAllocEx()
, and write the Malicious DLL in it.Figuring out the Offset to the Custom Loader
ReflectiveLoader()
exported function from the Injected DLL.Execution is then passed to
ReflectiveLoader()
in the target process, that will start calculating it's own image's location in memory to parse it's image's headers.ReflectiveLoader()
will use PEB Traversal and parses the export table for Mapped Modules like Kernel32/ ntdll looking for offsets to important functions likeGetProcAddress()
|LoadLibraryA()
/VirtualAlloc()
.With these APIs' offsets in hand,
ReflectiveLoader()
will allocate continuous regions of memory to map it's images' the malicious DLL headers/ sections, resolve it's imports, fix relocations and load any needed additional libraries.Finally
ReflectiveLoader()
will callDllMain()
withDLL_PROCESS_ATTACH
flag passed, then it will return execution to the host process by terminating itself.
To Summarize, Reflective DLL-Injection can be described as an emulation of the Windows image Loader, instead of directly calling LoadLibraryA()
passing the Malicious DLL, an exported position independent function namely ReflectiveLoader()
from the DLL is executed doing all the Manual Loading/ Mapping of the Malicious DLL.
For a full implementation of the Reflective DLL-Injection Technique, check Steven Fewer's github repository, the full code is very well commented and explained.
APC-Injection
APC-Injection is yet another stealthy injection method malware uses to inject their payload into Legitimate Remote Processes, though this also is not stealthy anymore because AV/EDR Products are now actively scanning for the use of APCs to execute functions, but variants of this method could in fact sneak behind these detection and succeed.
Any injection method could be summarized into two parts
Injecting/Writing the malicious payload into a target process.
Executing the malicious payload. What's interesting in APC-Injection is that it forces the target process to execute the malicious injected code on it's behalf, this is done by leveraging Asynchronous Procedure Calls (APC).
For any application, it's threads can execute functions asynchronously by issuing a request to execute a specific function in it's context, which in this case is called The APC Function, tons of requests of this sort are scheduled in an APC-queue that is specific for each thread in a process. In order for a thread to execute any of it's queued APCs it must enter an Alterable State, For Example:
a thread sleeps for 10 seconds by calling SleepEx(50000, bAlertable==TRUE);
then the thread is said to perform an alterable wait operation for a time window of 10 seconds, the thread can then handle any pending APCs in it's APC-queue in an FIFO-Manner, if there are any, the thread will invoke the queued APC and stops sleeping.
In Real-Scenarios what a malware sample will do is inject the malicious payload into a target process that is most likely to enter an alterable state explorer.exe
is the most targeted then it would open multiple threads in the process and queues the malicious payload in each thread using QueueUserAPC();
that takes a pointer to the APC-Function which is the malicious payload obviously, and just waits for any thread to enter an alterable state, only then the malicious payload will be executed.
This method is much better than calling CreateRemoteThread()
/ ResumeThread()
, yet security products are fully aware of this technique nowadays.
=> Implementation of APC-Injections:
Steps taken to perform an APC-Injection:
Starting with a malicious executable that's responsible for this stage's injection, the malicious executable will:
Locate a target process that's most likely to enter an alterable state e.g.
explorer.exe
.With the target process's PID, the executable will allocate a region of memory in the target process with size of malicious code, write the malicious code into the remote process.
Open a couple of threads in the target process.
The sample will then queue an APC pointing to the malicious payload in all opened threads.
The sample waits for any thread to enter an alterable state.
Malware could decide to execute payload in a local process and sets it in an alert-able state by calling any of the Alertable Wait Functions .
Helpful APIs:
VirtualAlloc/Ex()
WriteProcessMemory()
EarlyBird-APC-Injection
Based on the scheme we laid out Injection techniques so far, this technique is obviously better that the previous. In fact there are lots of variants of utilizing APCs to execute injected malicious code without triggering AVs**/EDR**s. The EarlyBird APC-Injection is one sophisticated variant of the original technique, that shows how Threat Actors actually reverse engineer legitimate windows components and APIs to circumvent/ sneak behind common detection.
Instead of firing alarms with QueueUserAPC()
, this technique depends on the normal behavior of Windows OS and how it handles newly created threads/ processes. For newly created/ suspended process, on resuming the main thread with the initialization of the process starting, a call to NtTestAlert()
is executed to check for any queued APCs before the starting of the main thread, if any APCs are found, the thread is set up to call KiUserApcDispatcher()
that leads to the execution of the APC.
=> Implementing EarlyBird APC-Injection
The Malware starts by targeting a process, creating it in a suspended state, writing payload inside it's memory and queuing the payload's address as an APC to the process then resuming the process's main thread. On resuming the main thread of a process suspended process the OS will test for any queued APCs over this process to be executed before the main thread, which guarantees the execution of the malicious injected payload in whatever legitimate binary it's injected into. So it's all the Operating System's work. This gets the malware to sneak behind AV/EDR hooks as they are implemented after the process initialization, which is after the execution of the malicious thread in this case.
=> Spotting EarlyBird APC-Injection
This method is not the easiest to spot, the only API call you can catch is the NtQueueApcThread()
but usually malware authors won't let that an easy catch and would trip analysts away with anti-analysis trick. So the best guess is to watch for a created process as suspended, and maybe attach a debugger on this process looking for an executable region of memory that is possibly the start of a malicious thread.
Practical Example: EarlyBird APC-Injection #Gamaru
Last updated