The four primary code injection techniques — classic DLL injection, reflective DLL injection, process hollowing, and APC injection — with API sequences, detection indicators, and analyst countermeasures.
Sign in to mark this article as read and track your progress.
Code injection forces another process to execute code it did not originally contain. The goal is to run malicious code inside a legitimate, trusted process — hiding it from Task Manager, AV scanners, and firewall rules that whitelist by process name.
svchost.exe is trusted and whitelisted.
If malware injects into svchost.exe, its network traffic
appears to come from a legitimate Windows service.
The most common injection technique. Forces the target process to load a malicious DLL using LoadLibraryA as the thread start address.
; Step 1: Open target process
push PROCESS_ALL_ACCESS
push FALSE
push dwTargetPID ; obtained from CreateToolhelp32Snapshot
call OpenProcess ; returns hProcess in EAX
; Step 2: Allocate memory in target for DLL path string
push PAGE_READWRITE
push MEM_COMMIT
push dwPathLength
push 0
push hProcess
call VirtualAllocEx ; returns remote address in EAX
; Step 3: Write DLL path into allocated memory
push 0
push dwPathLength
push offset szDllPath ; "C:\malware.dll"
push remoteAddr
push hProcess
call WriteProcessMemory
; Step 4: Create remote thread calling LoadLibraryA
push 0
push 0
push remoteAddr ; DLL path as argument to LoadLibraryA
push LoadLibraryA ; thread start address
push 0
push 0
push hProcess
call CreateRemoteThread
Detection indicators:
OpenProcess with PROCESS_ALL_ACCESS targeting a system processVirtualAllocEx creating a writeable region in another processWriteProcessMemory writing a file path stringCreateRemoteThread with LoadLibraryA as start addressMITRE ATT&CK: T1055.001 — Process Injection: Dynamic-link Library Injection
The DLL loads itself using a custom loader embedded within it — without calling LoadLibraryA. No import table entry is created. The DLL does not appear in the target process's PEB module list.
WriteProcessMemoryReflectiveLoader function inside the DLL bytesReflectiveLoader performs its own PE loading: fixes relocations, resolves imports, calls DllMainThe DLL is not in the PEB module list — EnumProcessModules and Task Manager's DLL tab will not show it. However, Volatility's malfind plugin detects it: a private, executable, allocated (not mapped) memory region containing an MZ header is exactly what reflective injection produces.
vol -f memory.dmp windows.malfind
# Shows: svchost.exe 0x00340000 PAGE_EXECUTE_READWRITE MZ header
MITRE ATT&CK: T1055.001
Creates a legitimate process in suspended state, replaces its executable image with malicious code, then resumes it. The process appears legitimate to every user-mode tool.
; Step 1: Create target in suspended state
push CREATE_SUSPENDED
push ...
push offset szLegitApp ; "C:\Windows\System32\svchost.exe"
call CreateProcessA ; creates suspended process
; Step 2: Unmap legitimate image from process memory
push baseAddress ; from reading PEB of suspended process
push hProcess
call NtUnmapViewOfSection ; removes svchost.exe code from memory
; Step 3: Allocate and write malicious payload
push PAGE_EXECUTE_READWRITE
push MEM_COMMIT | MEM_RESERVE
push payloadSize
push preferredBase
push hProcess
call VirtualAllocEx
push ...
push payloadSize
push pPayload
push remoteBase
push hProcess
call WriteProcessMemory
; Step 4: Set entry point and resume
; Update thread context EIP/RIP to point to payload entry point
call SetThreadContext
call ResumeThread ; payload now executes
Detection indicators:
CreateProcessA with CREATE_SUSPENDED flagNtUnmapViewOfSection call on a process other than selfWriteProcessMemory writing a full PE into another processSetThreadContext followed by ResumeThreadMITRE ATT&CK: T1055.012 — Process Injection: Process Hollowing
Queues an Asynchronous Procedure Call (APC) to a thread in the target process. The APC executes when the thread enters an alertable wait state.
; Queue APC to all threads of target process
push remoteShellcodeAddr ; APC routine address
push 0
push 0
push hThread ; thread handle
call QueueUserAPC
Requirement: the target thread must be in an alertable wait state for the APC to execute. Functions that put threads into alertable wait: SleepEx, WaitForSingleObjectEx, MsgWaitForMultipleObjectsEx.
Variant — Early Bird APC: Queue the APC to a process created suspended, before any security product hooks are installed. Resume the process — the APC executes immediately as the first action before any user code runs.
Detection indicators:
OpenThread followed by QueueUserAPCVirtualAllocEx and WriteProcessMemoryCREATE_SUSPENDED + QueueUserAPC + ResumeThreadMITRE ATT&CK: T1055.004 — Process Injection: Asynchronous Procedure Call
| Technique | Key API Sequence | Volatility Plugin |
|---|---|---|
| Classic DLL injection | OpenProcess → VirtualAllocEx → WriteProcessMemory → CreateRemoteThread | dlllist (DLL appears) |
| Reflective DLL injection | OpenProcess → VirtualAllocEx → WriteProcessMemory → CreateRemoteThread (no LoadLibrary) | malfind (RWX + MZ) |
| Process hollowing | CreateProcessA(SUSPENDED) → NtUnmapViewOfSection → WriteProcessMemory → SetThreadContext → ResumeThread | malfind, pslist (image path mismatch) |
| APC injection | OpenThread → QueueUserAPC | malfind |
In x64dbg:
CreateRemoteThread, NtUnmapViewOfSection, QueueUserAPC