A full ghost-thread hijack technique emerges from the code: a 2007 proof-of-concept that injects machine code into explorer.exe’s GUI thread by rewriting its user-mode stack, not by calling traditional injection APIs. The program forces the victim thread to execute attacker-controlled call frames that simulate proper calls to NtProtectVirtualMemory, NtWriteVirtualMemory, and SetThreadContext, all without ever calling those APIs directly on the attacker side. That pattern is the heart of the GhostWriting technique.
The final action: Explorer executes attacker-supplied instructions that invoke a MessageBox, then self-locks by jumping into an infinite loop (EB FE) inside ntdll.dll, ensuring thread stability after the payload executes.
Core concept and offensive intent
GhostWriting forces a remote thread to perform its own memory edits. The attacker:
- suspends the victim thread
- reads its current context
- rewrites its stack to insert forged call frames
- resumes the thread so the victim calls system APIs on itself
No WriteProcessMemory, no CreateRemoteThread, and no explicit injection APIs appear. The target thread becomes the injector. That behavior bypasses user-mode hooks, frustrates EDR tracing, and blends into normal control flow.
The code uses Explorer’s primary GUI thread as the victim since the thread waits on messages, suspends cleanly, and can tolerate temporary hijacking.
Payload and execution goals
The shellcode in InjectionCode contains:
PUSH 0- a call into inline instructions
- preparation for a MessageBoxA invocation
- a final jump to an
EB FEinfinite loop inntdll.dll
When Explorer executes the snippet, a GUI message box appears, then the hijacked thread enters a self-lock state until the attacker restores its original context.
Real attackers would substitute that snippet with:
- reflective loaders
- manual mapping stubs
- shellcode launchers
- token theft or credential scraping logic
The PoC simply proves control over a remote thread.
Stage 1 – Victim selection and thread acquisition
The program identifies Explorer via its shell window:
GetShellWindow()returns the main shell window.GetWindowThreadProcessId()retrieves the GUI thread responsible for the desktop.OpenThread(THREAD_SET_CONTEXT | THREAD_GET_CONTEXT | THREAD_SUSPEND_RESUME)opens that thread for full manipulation.
Explorer’s desktop thread becomes the execution trampoline.
Stage 2 – Context capture and stack hijack
The attacker captures the victim’s register state with GetThreadContext and examines:
- EIP (instruction pointer)
- ESP (stack pointer)
- EBP (frame pointer)
GhostWriting then alters the stack so the next resumed instruction does not follow the real call chain. Instead, the thread returns into forged stack data that simulates valid function call frames.
The forged frames specify:
- a fake return address (safe location)
- arguments for
NtProtectVirtualMemory - arguments for
NtWriteVirtualMemory - arguments for transitioning the memory region to RWX
- arguments for the final SetThreadContext-like restoration
The thread believes it is executing a sequence of nested calls. It follows the attacker-supplied stack entries, passes parameters as if invoked legitimately, and overwrites its own memory accordingly.
No user-mode DLL injection. No remote memory write from the outside. The target thread overwrites itself.
Stage 3 – Victim thread performs its own memory edits
GhostWriting sets up parameters so the victim thread itself:
- Changes page protections on Explorer’s memory using its own call to
NtProtectVirtualMemory. - Writes the attacker’s
InjectionCodeinto that newly writable memory using a simulated internal call frame forNtWriteVirtualMemory. - Switches protections back to executable.
- Adjusts its registers so EIP points to the newly injected shellcode.
The thread then resumes and jumps directly into the attacker’s code.
Every modification is performed by the victim, not the attacker. Hook-based EDR struggles here because the remote thread makes the suspicious API calls, not the injecting process.
Stage 4 – Auto-lock and proof of code execution
The injected snippet runs:
- triggers a MessageBox
- jumps to an
EB FEsequence inside ntdll.dll, which creates a tight infinite loop
This jump stabilizes the thread after the payload executes and prevents UI crashes. The PoC warns that some versions of Windows Server handle zero-sleep yields poorly, so the loop design keeps the thread predictable.
The function WaitForThreadAutoLock() posts several WM_USER messages to ensure Explorer’s message loop wakes at the right moment and executes the hijacked frame chain.
Tradecraft characteristics
Several elements illustrate advanced offensive engineering:
- Stack-rewriting injection — no memory API calls issued by the attacker.
- Victim-executed syscalls — signature-based behavioral EDR fails because Explorer performs the dangerous operations.
- Call-frame forgery — the technique builds complete stack frames, including simulated return addresses and pointer parameters.
- GUI thread abuse — Explorer’s message-pump thread creates predictable scheduling windows for hijack timing.
- DEP bypass — explicit manipulation of page protections ensures RWX availability for shellcode.
- Zero external imports — the technique avoids direct calls to sensitive APIs.
From an adversarial perspective, GhostWriting bypasses:
- inline API hooks
- syscall monitoring in unprivileged EDR
- alerting based on remote thread creation
- detection rules tied to
WriteProcessMemoryorVirtualAllocExpatterns
Capability profile in modern operations
GhostWriting grants an operator the following power:
- inject and execute arbitrary code in high-value processes without calling classic injection APIs
- bypass many user-mode EDR sensors
- run payloads in Explorer, which defenders trust
- maintain thread-level control while avoiding process crashes
The technique echoes later research around:
- APC hijacking
- return-oriented stack injection
- syscall-less memory modification
- direct manipulation of thread scheduling via message pumping
Modern malware families borrow pieces of this approach for stealth injection, often embedded inside reflective loaders or direct-syscall frameworks.
Defensive and analytic implications
Security visibility degrades heavily when the victim thread calls sensitive APIs on itself. Relevant detection anchors:
- unexpected call sequences inside Explorer
- abnormal thread context switches
- irregular stack layouts
- presence of EB FE infinite loops in ntdll execution flow
- GUI thread stalls caused by injected loops
- suspicious NtProtectVirtualMemory / NtWriteVirtualMemory sequences in Explorer
Kernel-mode EDR that validates call stacks and thread-origin integrity increases detection likelihood. User-mode EDR based on API hooking loses visibility entirely.
Memory forensics teams should examine:
- overwritten stack frames
- injected RWX pages near Explorer’s working set
- recently modified memory regions linked to GUI threads
Forensic signature: a shell thread whose EIP points into non-module memory just after receiving crafted message-pump stimuli.
Intelligence assessment
GhostWriting demonstrates an early, elegant, and highly instructive thread-hijack technique that outmaneuvers EDR designs heavily dependent on user-mode hooks. The code shows that once an attacker gains the ability to suspend, read, and rewrite a thread’s stack, the thread itself becomes the weapon system. Analysts studying this PoC gain a view into an important lineage of stealth injection methods used by high-skill operators, including techniques that appear later in APT toolkits, kernel-aware post-exploitation frameworks, and stealthy red-team loaders.
The technique remains relevant because many modern defenses still rely on surface-level detection that expects attackers to invoke classic injection primitives. GhostWriting proves that when the victim performs its own malicious actions, the defender’s perspective collapses unless deeper kernel telemetry or call-stack integrity checks exist.
