Asynchronous Procedure Call (APC) is a process injection technique that allows adversaries to execute malicious code by queuing it as an APC routine within a legitimate process. This technique exploits Windows' built-in APC mechanism, which enables functions to be executed asynchronously in the context of a specific thread. By injecting malicious code into a process and forcing an existing thread to execute it, attackers can evade detection and execute payloads stealthily.
In this blog post, we explain the T1055.004 Asynchronous Procedure Call of the MITRE ATT&CKĀ® framework and explore how adversaries employ Asynchronous Procedure Call with real-world attack examples in detail.
|
|
Asynchronous procedure calls (APCs) are functions executed asynchronously within a specific thread's context. When an APC is queued to a thread, it is added to the thread's APC queue. When the thread is scheduled to run again, it checks its APC queue for any pending APCs and executes them before continuing with its normal execution. Malware developers often exploit this mechanism by attaching malicious code to the APC queue of a target thread.
APCs are queued to a thread's APC queue, and the thread is notified when an APC is ready to be executed. The thread can then execute the APC by calling the function KeWaitForSingleObject with the APC object as a parameter.
There are two types of APCs: kernel APCs and user APCs. Kernel APCs are executed in the context of the system kernel, while user APCs are executed in the context of a user-mode process. APCs are often used in the implementation of Windows device drivers to perform tasks such as reading and writing data to a device. They are also used by system libraries and applications to perform tasks asynchronously, such as waiting for the completion of an I/O operation.
One way that adversaries may use APCs is by queuing a kernel APC to the APC queue of a system thread, such as a thread that is running with elevated privileges. When the APC is executed, the code will be executed in the context of the system thread, allowing the adversary to perform actions with the privileges of the thread.
Another way that adversaries may use APCs is by injecting a PE into a process and using an APC to execute code from the injected PE within the context of the process. This can be used to evade security measures that are designed to prevent the injection of code into a process, as the APC is executed in a way that is transparent to the process itself.
Unlike the previous methods, which involve direct manipulation of thread contexts or PE images that may be detected by security defenses, APC injection queues a function to be executed when the thread is in an alertable state. Here's an overview of the APC injection attack lifecycle:
Process and Thread Handle Acquisition: The attacker obtains a handle to a target process using OpenProcess with necessary privileges, such as PROCESS_VM_OPERATION and PROCESS_VM_WRITE. Then, a thread within the target process is targeted. A handle to this thread is obtained via OpenThread, with access rights that allow APC queuing (e.g., THREAD_SET_CONTEXT).
Memory Allocation in Target Process: Using VirtualAllocEx, the attacker allocates memory within the target process's address space, where the malicious payload (shellcode) will be placed. The memory permissions are set to allow read, write, and execute actions, often PAGE_EXECUTE_READWRITE.
Writing Shellcode: The attacker writes the malicious code into the allocated memory section within the target process via WriteProcessMemory.
Queueing the APC: An APC is queued to the target thread using QueueUserAPC. The APC points to the shellcode in the allocated memory area. APCs will only run when the thread enters an alertable state, which can be achieved by calling certain functions such as SleepEx, SignalObjectAndWait, or WaitForSingleObjectEx with the appropriate flags to put the thread in an alertable state.
Triggering Execution: The attacker waits for the thread to enter an alertable state or triggers such a state themselves. When the thread becomes alertable, the queued APC is executed, and consequently, the malicious shellcode runs within the context of the target thread.
Asynchronous Procedure Shell (APC) also had its share among adversaries in 2024. PythonRatLoader malware uses APC injection to deploy XWORM malware [1]. Adversaries used an obfuscated Python code to create a notepad.exe process and inject the payload into it before thread execution started. The decrypted Python code used for APC injection is given below.
key = 'evr8pl5K'.encode('ascii') # Allocate memory with executable permissions ) # Execute the shellcode execute_shellcode () |
[1] Cofense, "PythonRatLoader: The Proprietor of XWorm and Friends," Cofense. Available: https://cofense.com/blog/pythonratloader-the-proprietor-of-xworm-and-friends