Process Injection: Malware Lurking in the Shadows of Legitimate Programs (Part 1)
It's a Saturday afternoon, you're tinkering with your computer, and a random curiosity happens to pique your interest. You start taking a look at the current running processes on your computer as well as the network connections and other general information involving your PC. You happen to notice that explorer.exe, the process responsible for providing you with a graphic user interface (GUI) is responsible for a network connection to an IP address external to your network. You assume it's probably just part of some sort of Windows reporting functionality and move on.
To a threat hunter or incident response analyst, activity as described above would ring some alarm bells and warrant some investigation. At a glance, this would indicate some sort of process injection. In this part 1 of this 2-part blog series, we'll cover what process injection is and the variety of ways it can be achieved.
What is process injection?
As described by MITRE, "Process injection is a method of executing arbitrary code in the address space of a separate live process." There's a plethora of ways this can be achieved, and we'll be going over several of them below.
Dynamic-link libraries, or DLLs, are pre-constructed pieces of code that processes call on to achieve certain functions. Many programs require very similar capabilities, such as access to the Windows registry or certain user-interface components such as scroll bars and buttons. The Windows operating system comes pre-loaded with a set of DLLs that can be accessed and leveraged by Windows programs. This grants software developers a level of time and performance efficiency when it comes to developing and executing their software.
The Practical Malware Analysis book, published by No Starch Press, highlights some of the most common DLLs found in the Windows operating system and a snapshot can be found below:
In a DLL injection, a legitimate process is forced to load a malicious DLL, resulting in malicious code executing in the legitimate process's memory space. Note that in order to be able to manipulate and force the process to execute the DLL, a level of privileged access on the system is required.
There are multiple types of DLL injections, some detailed below:
Classic technique using CreateRemoteThread() and LoadLibraryA(): For this technique, the DLL must be written on disk. Let's say that Process B is the target process for injection. Using Process A, one can allocate memory in process B and provide the path to the malicious DLL. The path provided will be used by the LoadLibrary() function. From there, one will then get the address for the LoadLibrary() function and pass that information as an argument to CreateRemoteThread(). CreateRemoteThread() points to LoadLibrary(), and LoadLibrary() loads the DLL at the path it was provided. Adam Furmanek provides a simple and concise write up on this technique here.
Reflective: Loading the DLL from memory rather than loading from disk. This method does not rely on a Windows loader and is therefore much stealthier than its counterparts.
Loading DLLs via Registry: While this could be considered the "cheap shot" of DLL injection, since it's not really replacing any code or doing anything intricate, it's an effective way to get a program to load malicious code. At startup, Windows uses User32.dll to check the value of the following registry key: HKLM\Software\Microsoft\Windows NT\CurrentVersion\Windows\LoadAppInit_DLLs It does this because, if you recall earlier in the post, User32.dll is responsible for a lot of the graphic components that are loaded into Windows programs. If the value of this registry key is set to 1, then all of the DLLs found at the following registry key location will be loaded: HKLM\Software\Microsoft\Windows NT\CurrentVersion\Windows\AppInit_DLLs From there, every program that uses User32.dll will load the DLLs listed at that registry location. This means that one could simply place the malicious DLL on that list and have it execute within the process memory; however it is worth noting that this would require administrative privileges.
Portable Executable (PE) Injection
"Portable Executable" is the term used for a piece of code that is able to run on all architectures of the Windows operating system. In this injection method, rather than calling a DLL into the process memory for execution, the entire code of a different process is loaded into the memory space of a target process. This is accomplished by invoking WriteProcessMemory() instead of using the LoadLibrary() module. Additionally, this attack method abuses one of the two resources leveraged by portable executables: the base relocation table, which contains all of the pointers for the absolute memory addresses of distinct functions/pieces of code used by the PE (the other resource is the Import Address Table [IAT]).
Atom Bombing Technique
This is a more recent technique and like the previously listed reflective method, also stealthier than some of the older methods. In the atom bombing technique, the threat actor writes malicious code to the global atom table. An atom table is a resource used by applications to store strings. Once the string is stored, the application receives an integer that can be later leveraged to access the string. The global atom table is one that is accessed by all applications on the system. Every string stored in an atom table gets a unique integer identifier (known as an atom), and any application can query the global atom table to access the string associated with it. In this attack method, the attacker forces the target process to access the malicious code stored in the global atom table, therefore executing it within the process memory. More details on this method can be found at the Microsoft blog linked here.
Conclusion for Part 1
As you can see, there's more than one way to achieve the same end result of executing malicious code within the memory space of a benign program. The methods above detail only a couple of the ways that this is possible, and they shed light on the number of exploitation vectors available to threat actors. As an incident responder or threat hunter, it's imperative to be familiar with the basic mechanisms of these techniques in order to understand what is taking place and how in order to crush the threat as close to the root as possible. In a future post, I'll delve into how to identify and characterize injected processes as well as how to reduce the risk of someone performing these techniques on your network.
DLL Injection Attacks in a Nutshell (Circle Ninja)
Windows DLL Injection Basics (Brad Antoniewicz)
Process Injection (MITRE ATT&CK)
Ten process injection techniques (Elastic)