What is Threadless Injection and how it enables red team trade-craft?
Learn what is Threadless Process Injection and how to use it for red team trade-craft.
The classic process injection technique involves the following steps:
Find a process to inject into. It can be an already running process or a new sacrificial process (fork & run).
Allocate memory into it.
Change permissions of the memory region to RWX or RW.
Write shellcode to that memory region.
Change permissions back to RX.
Execute the shellcode by using CreateRemoteThread or QueueUserAPC Windows APIs.
The problem with this technique is that it has patterns that can be used to detect it. These patterns include
use of common Windows APIs such as VirtualAllocEx(), CreateRemoteThread(), QueueUserAPC() etc. in a specific order,
writing code into the process address space with out an image file backing it on the disk, and
threads displaying behavior that is out of character for it’s process (for example, explorer reaching out to a URL on the internet).
Endpoint detection solutions leverage these patterns heavily and have put this technique to rest, for all intents and purposes. This has given rise to several alternate process injection techniques which eliminate one or more of these patterns.
Threadless process injection, discovered by Ceri Coburn, is one such technique. This technique leverages memory writing and function hooking to inject and execute malicious code. Function hooking means to write certain instructions at the beginning of the function to redirect the execution to the malicious code. So whenever that function will be called, the malicious code will be executed first. The malicious code may (or may not) return the execution flow back to the hooked function.
This technique does not create a new process or thread. The malicious code is executed as part of application’s functionality (hence, the name Threadless Injection). It works as follows:
Identify a DLL/Export to hook.
Write the hook code and shellcode within the memory hole of the target DLL (whenever Windows loads DLLs in memory it leaves a buffer space between two DLLs, known as memory hole.)
Patch / hook a non-busy function / API in this DLL (non-busy means a function that this not used by the application frequently) to call the hook code.
Wait for the legitimate application activity to call the hooked function / API.
The hook code saves the state of registers on the stack, removes the hook from the function / API, executes the shellcode and restores the execution back to the hooked function / API.
Red Team Notes
- Threadless process injection technique leverages memory writing and function hooking to inject and execute malicious code. The malicious code is executed as part of application's functionality without creating a new thread.
Follow my journey of 100 Days of Red Team on WhatsApp or Discord.
If you want to dive deep into the technical details of how threadless process injection works, below is the recording of the presentation, Needles Without The Thread: Threadless Process Injection by Ceri Coburn, presented at Bsides Cymru 2023.
Ceri has also published a PoC for this technique which is available in his GitHub repository.
Jordan Jay (iilegacyyii) has created a Beacon Object File, ThreadlessInject-BOF, that implements this technique and makes it available to Command and Control (C2) software that support BOFs.
Daniel Santos has adapted this technique to run .NET assemblies via threadless process injection. He has created the CLRInjector tool based on his adaptation.
S1lky has further adapted Daniel’s technique to execute various enumeration tools in the context of a Powershell process in a stealthy manner.