Double Your Threat Blocking in 90 Days
Suleyman Ozarslan, PhD & Picus Labs | February 23, 2022
The Top 10 MITRE ATT&CK Techniques Used by Adversaries
Picus Labs analyzed millions of adversary techniques and published the Red Report 2023 and the Top Ten MITRE ATT&CK techniques used by adversaries. We are continuing our blog series on the techniques in the Top Ten list. This is the fourth blog of the series, and we explained MITRE ATT&CK T1055 Process Injection in detail. In the Red Report 2023, this technique is the fourth most used MITRE ATT&CK technique.
The Red Report 2023
Process Injection is a Defense Evasion and Privilege Escalation technique that adversaries utilize to achieve persistence, stealth, and privilege in their advanced cyber attacks. Attackers use this technique to disguise their malicious activity as legitimate operations and abuse privileges of the legitimate processes. As a technique that can provide these features, Process Injection gets fourth place in the Top Ten MITRE ATT&CK techniques list of the Red Report 2023.
Process injection is a technique of running malicious code in the address space of separate processes. After the malicious code is injected into a legitimate process, attackers can access legitimate processes' resources such as process memory, system/network resources, and elevated privileges. Since malicious code execution is masked under the legitimate process, the attackers’ action may evade detection. If the legitimate process has administrative privileges in the victim system, attackers may execute their malicious code as administrators of the victim system.
Detection of malware is easy when you can list the running processes and filter out legitimate ones that are part of the OS or installed software. However, if the malware can encapsulate its malicious code within a legitimate process, it will hide on the infected system. Process injection is the tried and true technique consisting of running arbitrary code within the address space of another process. This technique allows access to the target process’s memory, system, and network resources.
Process injection gives three significant benefits for adversaries:
Code execution under a legitimate process may evade security controls. The legitimate process, which is whitelisted, camouflages the malicious code to evade detection.
Disk forensics can be evaded because the malicious code is executed inside the legitimate process’s memory space.
If the target process has administrator access to system resources, process injection may lead to privilege escalation. For example, if the target process has privileges to access the Internet, the malicious code can bypass security control to communicate legitimately over the Internet.
Security controls may quickly detect custom processes. Therefore, threat actors use common Windows processes such as:
Adversaries use the following methods when choosing their target process for injecting malicious code:
A specific target process is called out in the code.explorer.exe and svchost.exe are the most commonly used ones.
A list of target processes is defined in the code. For instance, the Turla cyberespionage group’s Carbon backdoor includes a configuration file consisting of a list of target processes for injection . A typical list includes native Windows and browser processes.
In some attack scenarios, the target process is not previously defined, and a suitable host process is located at runtime in this type of attack. For example, the CopyKittens group used Windows API functions to extract a list of currently active processes and to get a handle on each target process in its campaign .
As the name implies, Dynamic-Link Library (DLL) Injection is a technique that involves tricking a program into calling a malicious DLL file that is then run as part of the target process. The main goal of this technique is to bypass process-based defenses and elevate privileges as in other process injection methods .
A DLL is a Windows file that contains code and data that can be utilized concurrently by multiple programs . For instance, the Comdlg32 DLL provides typical dialog box related functions in Windows OSs. Each program may implement an Open dialog box by utilizing the features supplied in this DLL. It contributes to code reuse and memory efficiency. Therefore, numerous applications utilize DLL files to perform their essential functions. As a result, it becomes vital to verify whether legitimate DLL files are being called or whether malicious DLL files are being used by malware.
In the DLL injection technique, briefly, the malware writes the path to its malicious DLL into another process's virtual address space and ensures that the remote process loads it by creating a remote thread in the target process .
In general, adversaries utilize DLL injection in malware by employing the following steps:
1. Identify the target process: The malware must first identify a process to inject itself into (e.g., explorer.exe, svchost.exe, regsvr32.exe ). This is typically accomplished by performing a process search via three Application Programming Interfaces (APIs) :
a. CreateToolhelp32Snapshot returns a snapshot of the heap or module states of a particular process or all processes.
b. Process32First collects information on the snapshot's initial process.
c. Process32Next iterates through them in a loop.
2. Attach to the process: After locating the target process, the malware obtains the target process's handle via a call to OpenProcess .
3. Allocate memory within the process: The malware invokes VirtualAllocEx to allocate memory to write the path to its DLL.
4. Copy DLL or the DLL path into process memory: The malware calls WriteProcessMemory to write the path in the memory allocated. It also requires calling the LoadLibraryA function for writing the DLL path or determining offset for writing full DLL. LoadLibraryA is a kernel32.dll function that is used during runtime to load DLLs, executables, and other supporting libraries. It accepts a filename as the single parameter.
5. Execute the injected DLL: Due to the complexity of managing threads within another process, it is preferable to construct your own thread with the CreateRemoteThread function. Besides, NtCreateThreadEx or RtlCreateUserThread can also be used to execute the code in another process. The general concept is to pass the LoadLibrary address to one of these APIs, requiring a remote process to execute the DLL on the malware's behalf .
Although DLL injection is a very effective technique, it also has some challenges for attackers. For example, LoadLibraryA registers the loaded DLL with the program so it can be detected quickly. However, LoadLibraryA can be replaced by loading the whole DLL into memory then determining the offset to the DLL's entry point. This approach allows you to inject the DLL into a process without registering it with the program (stealthy) .
Moreover, most endpoint security products monitor and flag the CreateRemoteThread function used in the last step. Additionally, this technique requires the presence of a malicious DLL on a disk that may be identified. Given that attackers frequently inject code to evade defenses, sophisticated attackers are unlikely to adopt this technique.
Portable Executable (PE) is a file format used by Windows executables, object code, and DLLs. PE Injection technique is similar to DLL Injection, but rather than passing the address of the LoadLibrary, the malware injects its malicious code into an already-running process and causes it to execute via a small shellcode or by calling CreateRemoteThread.
Using the PE Injection technique, malware does not need to drop a malicious DLL on the disk. Similar to the DLL Injection technique, the malware allocates memory in the host process with VirtualAllocEx, and instead of writing a DLL path, it calls WriteProcessMemory to write its malicious code.
However, PE injection has a disadvantage, the change in the base address of the copied image. When malware injects its PE into another process, it acquires an unpredictable new base address, forcing it to dynamically recompute its PE's fixed addresses. To circumvent this, the malware must locate the host process's relocation table address and resolve the cloned image's absolute addresses via a loop over its relocation descriptors .
Thread Execution Hijacking is frequently carried out by suspending an already running process and then unmapping (hollowing) its memory, which can then be replaced with malicious code or the path to a DLL. This is very similar to Process Hollowing, but instead of creating a suspended process, it targets an existing one.
Generally, adversaries employ threat execution hijacking in malware by using the following steps:
1. Using native Windows API functions like OpenThread, a handle to an existing victim process is initially generated.
2. At this point, the process can be suspended using SuspendThread.
3. Then, the malware allocates memory in the process using VirtualAllocEx.
4. The shellcode is written to the allocated memory with WriteProcessMemory.
5. Retrieve the target thread’s context with GetThreatContext.
6. Update the target thread’s instruction pointer to point to the written shellcode in step 4. Then, commit the hijacked thread’s new context with SetThreadContext.
7. Resume the hijacked threat with ResumeThread.
Asynchronous procedure calls (APCs) are functions that run asynchronously within the context of a specific thread. When the system queues an APC to a thread, it generates a software interrupt. When the thread is scheduled again, it will execute the APC function. A malware can force the target threat to execute its malicious code by attaching the code to the thread’s APC Queue.
Adversaries abuse APCs in malware by employing the following steps:
1. Identify the target process ID: The malware must first identify a process to inject itself into (e.g., explorer.exe, svchost.exe, regsvr32.exe ).
2. Allocate memory within the process: VirtualAllocEx is called by the malware to allocate memory for the purpose of writing the path to its DLL.
3. Write malicious code into process memory: The malware calls WriteProcessMemory to write the path in the memory allocated.
4. Identify threads of the target process: Each thread has an associated queue of APCs, which are processed whenever the thread enters an alertable state, such as when it calls WaitForSingleObjectEx, WaitForMultipleObjectsEx, or SleepEx. These functions simply allow the thread to process the APCs that are currently waiting.
5. Queue an APC to execute the malicious code: QueueUserAPC can be used to invoke a function at this point (such as LoadLibraryA pointing to a malicious DLL).
Thread Local Storage (TLS) callback injection is a technique that entails manipulating pointers within a portable executable (PE) in order to redirect a process to malicious code before it reaches the code's legitimate entry point. The OS typically uses TLS callbacks to initialize and/or clean up data used by threads .
TLS is used by malware to execute code that initializes every thread (which runs prior to the thread's actual code being executed). This enables the malware to evade debugging and possibly run the malicious code while having benign code at the entry point .
Other Process Injection techniques, such as Process Hollowing, can be used to manipulate TLS callbacks by allocating and writing to specific offsets within a process' memory space. For example, researchers found that TrickBot uses TLS Callbacks with Process Hollowing . As another example, Ursnif/Gozi-ISFB malware manipulated TLS callbacks while injecting the child process .
The ptrace() system call in Linux platforms enables one process (the "tracer") to monitor and control the execution of another (the "tracee"), and examine and modify the tracee's memory and registers. It is primarily used for debugging breakpoints and tracing system calls . Ptrace system call injection is a technique for attaching to and modifying a running process .
Ptrace system call injection is often accomplished by writing arbitrary code into a running process (for example, malloc) and then calling that memory with PTRACE SETREGS to set the register containing the next instruction to execute. Ptrace system call injection is also possible with PTRACE POKETEXT / PTRACE POKEDATA, which copies data to a specified address in the memory of the target processes (for example, the current address of the next instruction). It may not be possible when attempting to target processes with elevated privileges or those that are not child processes on some systems .
An example flow of Ptrace System Call Injection:
1. Identify the target process ID.
2. Use PTRACE_ATTACH to attach to the process. The callee is stopped, and the caller is now in control.
3. Get the registers of the running process using PTRACE_GETREGS. This also returns the instruction pointer, indicating the callee's current position in terms of instruction execution.
4. Inject the shellcode at the location of the RIP (a reference to the instruction pointer). You can use the PTRACE POKETEXT call, which accepts as input the callee's PID, the target location (which will be the callee's RIP), and the source (shellcode). This call can write to the debugged process's memory. This is how the code is really injected into the target process.
5. After modifying the target process's memory to contain the code we want to run, we simply need to give back control to the process and allow it to continue running . This can be accomplished in a variety of ways. For example, we can simply detach the target process with PTRACE_DETACH, which means we will stop debugging it. This action effectively terminates the debug session and resumes the target process's execution.
Proc is a pseudo filesystem that provides access to kernel data structures . It is commonly mounted in the /proc directory and is used to provide information about processes. Proc memory injection enumerates a process's memory via the proc filesystem (/proc/[pid]) and then constructs a return-oriented programming (ROP) payload .
Each process that is currently running has its own directory, which includes memory mappings. Proc memory injection is accomplished by overwriting the stack of the target process with memory mappings provided by the /proc directory . This information can be used to enumerate offsets and gadgets (or instructions within the application that can be exploited to construct a malicious payload) that are otherwise masked by process memory safeguards such as random address space layout (ASLR). Once enumerated, dd can be used to overwrite the target processes' memory map in /proc/[pid]/maps.
When registering a window class, an application can specify a certain amount of additional memory, referred to as Extra Window Memory (EWM). Extra Windows Memory Injection (EWMI) is a technique that involves injecting into the EWM of the Explorer tray window.
There is limited space in EWM. In order to bypass this restriction, the virus adds code to a shared region of explorer.exe and then uses SetWindowLong and SendNotifyMessage to create a function pointer to the shellcode which is then executed.
When it comes to writing into a shared section, the malware has two alternatives . It can either construct a shared section and map it to both itself and another process, or it can open an existing shared section. Due to the overhead associated with creating heap space and calling NTMapViewOfSection, as well as a few additional API calls, the latter option is more frequently utilized.
After the malware writes its shellcode to a shared section, it utilizes GetWindowLong and SetWindowLong to access and modify the Shell_TrayWnd's EWM. GetWindowLong returns the 32-bit value at the provided offset from the EWM of a window class object, whereas SetWindowLong changes the value at the specified offset. By doing so, the malware can simply modify the offset of a function pointer in the window class to point to the shared section's shellcode .
As with the majority of the Process Injection sub-techniques, the malware must execute the code it has written. It accomplished this through the use of APIs such as CreateRemoteThread, QueueUserAPC, or SetThreadContext in other techniques. Instead, the malware triggers the inserted code via a call to SendNotifyMessage in the Extra Windows Memory Injection (EWMI) technique. Shell_TrayWnd receives and transfers control to the address specified by the value previously set by SetWindowLong during the execution of SendNotifyMessage.
To bypass process-based defenses, adversaries may inject malicious code into suspended and hollowed processes. Process hollowing is generally accomplished by creating a process in a suspended state then unmapping/ hollowing its memory, which can then be replaced with malicious code.
1. Create a new process with CreateProcess with the CREATE_SUSPENDED option in the fdwCreate flag to suspend the process’ primary thread. The host program has now been loaded, but no code has been executed since it was suspended.
2. The malware unmaps (hollows out) the legitimate code from memory in the host process using APIs calls such as ZwUnmapViewOfSection or NtUnmapViewOfSection.
a. The ZwUnmapViewOfSection routine unmaps a view of a section from the virtual address space of a subject process.
b. If the call to this function occurs in user mode, you should use NtUnmapViewOfSection instead of ZwUnmapViewOfSection .
3. Then, the malware allocates memory in the process using VirtualAllocEx. It must use the flProtect parameter to ensure that the code is marked as writeable and executable.
4. The shellcode is written to the allocated memory with WriteProcessMemory.
5. The malware then modifies the adjusted code and data sections to appear normal using VirtualProtectEx's Read/Execute or Read-only protections.
6. The malware retrieves the target thread’s context with GetThreatContext.
7. Then, the malware updates the target thread’s instruction pointer to point to the written shellcode in step 4. Then, commit the hijacked thread’s new context with SetThreadContext.
8. Finally, using ResumeThread, the malware loader simply resumes the suspended process.
Transactional NTFS (TxF) in Windows is a method that enables safe file operations on an NTFS file system volume to be performed in a transaction . TxF transactions improve application reliability by ensuring data integrity across failures. Adversaries abuse TxF to replace the memory of a legitimate process with a malicious code, which is Process Doppelgänging.
As reported in December 2007 , the Process Doppelgänging technique is relatively newer than other process injection techniques. It is similar to Process Hollowing, but it involves a fileless code injection that abuses a built-in Windows function and an undocumented implementation of the Windows process loader. Briefly, with the help of this technique, attackers can masquerade malicious actions as harmless, legitimate processes by manipulating how Windows handles file transactions. Process Doppelgänging leaves no trace of the intrusion, making it extremely difficult to detect.
Process Doppelgänging is a four-step process :
1. Transact – Overwrite legitimate executable with a malicious one
a. Create a transaction with CreateTransaction()
b. Open a “clean” file transacted with CreateFileTransacted()
c. Overwrite the file with malicious code with WriteFile()
2. Load – Load malicious executable
a. Create a section from the transacted file with NtCreateSection()
i. The created section will point to our malicious executable.
3. Rollback – Rollback to original executable
a. Rollback the transaction with RollbackTransaction().
i. Effectively removes our changes from the file system.
4. Animate – Bring the Doppelgänger to life
a. Create process and thread objects with NtCreateProcessEx() and NtCreateThreadEx().
b. Create process parameters with RtlCreateProcessParametersEx().
c. Copy parameters to the newly created process’s address space with VirtualAllocEx() and WriteProcessMemory().
d. Start execution of the doppelgänged process with NtResumeThread().
Process doppelgänging's use of TxF also avoids the use of highly-monitored API functions such as NtUnmapViewOfSection, VirtualProtectEx, and SetThreadContext.
The Virtual Dynamic Shared Object (vDSO) is a small shared library that is automatically allocated in the address space of all user-space applications by the Linux kernel . VDSO hijacking occurs when calls are redirected to dynamically linked shared libraries for executing arbitrary code in the address space of a separate live process in Linux systems .
Memory protection mechanisms in Linux systems may prevent Ptrace System Calls from writing executable code to a process. Therefore, the T1055.008 Ptrace System Calls technique may not work. However, an adversary can use the Virtual Dynamic Shared Object (vDSO)’s syscall interface code stubs to execute syscalls to open and map a malicious shared object. This code can then be invoked by rerouting the process's execution flow via patched memory address references stored in the global offset table of the process (which stores the absolute addresses of library functions that have been mapped) . VDSO hijacking injects code into ELF binaries during runtime via manipulated code stubs mapped in from the linux-vdso.so shared object.
 ESET Research, “Carbon Paper: Peering into Turla’s second stage backdoor | WeLiveSecurity,” WeLiveSecurity, 30-Mar-2017. https://www.welivesecurity.com/2017/03/30/carbon-paper-peering-turlas-s econd-stage-backdoor/.
 Minerva Labs LTD, ClearSky Cyber Security, “CopyKittens Attack Group.” https://s3-eu-west-1.amazonaws.com/minervaresearchpublic/CopyKittens/ CopyKittens.pdf.
 “Process Injection: Dynamic-link Library Injection.”
 Deland-Han, “Dynamic link library (DLL) - Windows Client.”
 B. Hosseini, “Ten process injection techniques: A technical survey of common and trending process injection techniques,” 18-Jul-2017. https://www.elastic.co/blog/ten-process-injection-techniques-technical-sur vey-common-and-trending-process.
 “Windows DLL Injection Basics.” http://blog.opensecurityresearch.com/2013/01/windows-dll-injection-basics .html.
 “Process Injection: Thread Local Storage.” https://attack.mitre.org/techniques/T1055/005/.
 https://subscription.packtpub.com/book/security/9781789610789/7/ch07lvl 1sec07/tls-callbacks.
 N. Hegde, “Malware Analysis – TrickBot – Part 1 – Nikhil Hegde.” https://nikhilhegde.com/index.php/2019/10/24/malware-analysis trickbot-p art-1/.
 A. Vaish, “Newly Observed Ursnif Variant Employs Malicious TLS Callback Technique to Achieve Process Injection.” https://www.fireeye.com/blog/threat-research/2017/11/ursnif-variant-malici ous-tls-callback-technique.html.
 “ptrace(2) - Linux manual page.” https://man7.org/linux/man-pages/man2/ptrace.2.html.
 “Process Injection: Ptrace System Calls.” https://attack.mitre.org/techniques/T1055/008/.
 0x00pf (pico), _py, pry0cc (Leader & Offsec Engineer & Forum Daddy), Bowlslaw, REal0day, and S. (system) Closed, “[Linux] Infecting Running Processes,” 16-Sep-2016. https://0x00sec.org/t/linux-infecting-running-processes/1097.
 “proc(5) - Linux manual page.” https://man7.org/linux/man-pages/man5/proc.5.html.
 “Process Injection: Proc Memory.” https://attack.mitre.org/techniques/T1055/009/.
 barrygolden, “ZwUnmapViewOfSection function (wdm.h).” https://docs.microsoft.com/enus/windowshardware/drivers/ddi/wdm/nfw dm-zwunmapviewofsection.
 mikben, “Transactional NTFS (TxF).” https://docs.microsoft.com/en-us/windows/win32/fileio/about-transactional-ntfs.
 T. L. E. Kogan, “Lost in Transaction: Process Doppelgänging.” https://www.blackhat.com/docs/eu-17/materials/eu-17-Liberman-Lost-In-Tr ansaction-Process-Doppelganging.pdf.
 “vdso(7) - Linux manual page.” https://man7.org/linux/man-pages/man7/vdso.7.html.
 “Process Injection: VDSO Hijacking.” https://attack.mitre.org/techniques/T1055/014/.