I. INTRODUCTION
During red teaming or penetration testing, we often need to perform stealth injection between processes. To do so, we must avoid detection and intervention by Endpoint Detection and Response (EDR) solutions. That makes bypass EDR essential when carrying out stealth injection.
In this article, I’ll introduce a new EDR evasion technique and release a proof of concept (PoC) to demonstrate it.
I tested this bypass EDR technique against a high-end EDR, and it worked smoothly, flying under the radar.
Additionally, this new EDR evasion technique uses a novel method to write the payload into the target process without relying on the well-known WriteProcessMemory API.
I’ve also previously published research on stealth injection without using WriteProcessMemory; you can read it here.
Find me on X to get the latest pentest and red team tricks that I've been researching: Two Seven One Three (@TwoSevenOneT) / X
II. MAIN SECTION
1. An overview of stealth injection for EDR evasion
As the name suggests, when performing process injection, we need to stay out of the EDR’s watchful eye. But there aren’t many ways to bypass EDR, since the process always involves several core APIs:
- OpenProcess to interact with the target process
- Remote allocation/protection APIs to create a memory region for the payload
- Writing the payload into the remote process’s memory
- Executing the payload in the target process
EDR bypass techniques therefore tend to focus on these major steps: either eliminating them or finding new variations on how they’re used. Successfully performing stealth injection means we’ve successfully managed to bypass EDR.
2. A new EDR evasion technique using Windows messages
You’ve probably heard of the Windows API SendMessageW. This function sends the specified message to one or more windows. When used with the WM_SETTEXT message, the target window calls its default window procedure to update its internal caption, title bar, or control contents, such as those of an Edit box or Button.
What if, instead of sending control contents, we sent our payload to the target process? If that’s possible, it would be an effective way to bypass EDR without using WriteProcessMemory.
The contents of Edit controls are stored somewhere in the process’s memory. If we can determine the address of that memory region, we can locate the payload that was sent.
The main steps for sending the payload are:
- Enumerate GUI processes that have a suitable control; in this article, I’ll use an Edit control. Alternatively, create a new process as needed (Notepad.exe on Windows 10 or Regedit.exe on Windows 11).
- Get the control handle.
- Send the payload using the WM_SETTEXT message through the SendMessageW API.
- Search the target process’s memory for the sent message using the ReadProcessMemory function.
This allows us to send our payload to the target process without using WriteProcessMemory; a key step in the overall process of bypass EDR.
3. EDR evasion with PhantomBuffer
To demonstrate this EDR evasion technique, I created a PoC suite called PhantomBuffer. It consists of two small tools.
FindTargetWindows:
This tool searches for processes with suitable GUI controls for injecting a payload. If it doesn’t find any, it can also spawn a process of your choice.
PhantomBuffer
This tool performs the following main steps:
- Reads and parses the payload from a file (Base64).
- Sends the payload to the target by calling SendMessage with WM_SETTEXT.
- Locates the payload in the target’s memory and grants that memory region execute permission.
- Redirects one of the target process’s threads to the payload.
The challenge of using stealth injection to bypass EDR when injecting a payload into a target process:
This is addressed by using SendMessage with WM_SETTEXT.
During testing, I found that payloads containing two null bytes (0x00) weren’t written correctly to the target process. So, 0x00 is a bad character.
The challenge of redirecting a target process’s thread:
Here we run into another major issue: using the SetThreadContext/NtSetContextThread APIs to hijack execution of a remote thread. These two APIs are very well known for their use in EDR bypass techniques.
As a result, Endpoint Detection and Response (EDR) systems closely monitor their use. From indirect syscalls to directly calling NtSetContextThread or using call stack spoofing, it’s an arms race between malware and EDRs.
I won’t go into detail in this article about EDR evasion using SetThreadContext/NtSetContextThread. Instead, I’ll take a different approach.
Have you ever wondered what Microsoft created the SetThreadContext/NtSetContextThread API pair for?
One possible answer is that they’re intended for monitoring programs such as antimalware and EDR tools, as well as debugger programs.
So, what if I let a legitimate debugger perform the injection on PhantomBuffer’s behalf? Which debugger could serve this purpose? Remember, we don’t have a graphical interface, and we can’t manually adjust the debugger.
The answer to these questions is the cdb.exe debugger included in the Windows Debugger Tools.
cdb.exe will perform the following specific tasks:
- Attach by PID
- Select thread by system TID
- Set RIP
- Detach
cdb.exe -p <PID> -c "~~[<TID_IN_HEX>]s; r rip=0x<NEW_RIP>;
qd"
- -p <PID>: Attaches to the process with the given decimal PID.
- -c "...": Runs the quoted command string immediately after the initial attach break.
- ~~[<TID>]s: Selects the thread whose system thread ID is <TID>. The ID must be in hexadecimal, without a 0x prefix (e.g., ~~[1a4]s).
- r rip=0x<NEW_RIP>: Sets the RIP register to the specified address. The 0x prefix is required for hex values.
- qd: Quit and Detach. This ends the debugger session but leaves the target process running.
4. Defensive measures
5. EDR Evasion Demonstration
III. SUMMARY
During EDR evasion, figuring out how to perform stealth injection into other processes without triggering alerts from Endpoint Detection and Response systems is part of the ongoing arms race between attackers and defenders.
EDR bypass techniques typically focus on hijacking a target process or thread so that it runs a payload or shellcode prepared in advance.
PhantomBuff is an EDR evasion technique that takes a different approach. It uses the SendMessage function with the WM_SETTEXT message to send a payload into a target process without using the well-known WriteProcessMemory API.
By combining SendMessage with a trick involving the Windows debugger CDB.exe, we can successfully stealth-inject code into another process, even under the close scrutiny of high-end Endpoint Detection and Response systems.
To prevent this EDR bypass method, we can also monitor the SendMessage API when used with the WM_SETTEXT message, as well as watch for CBD.exe running from an unusual location.
Author of the article: Two Seven One Three

Comments
Post a Comment