An open API service indexing awesome lists of open source software.

https://github.com/x0reaxeax/ghostwriting64

PoC implementation of the GhostWriting injection technique for x64 Windows
https://github.com/x0reaxeax/ghostwriting64

defense-evasion ghostwriting injection pentesting poc popcalc process-injection redteam shellcode-execute shellcode-injection windows windows-x64 wpm-less-wpm x86-64

Last synced: 2 months ago
JSON representation

PoC implementation of the GhostWriting injection technique for x64 Windows

Awesome Lists containing this project

README

        

# GhostWriting-x64
## PoC implementation of the GhostWriting injection technique

### What does this do?
The idea behind this technique is to utilize thread context-altering APIs and `MOV` gadgets to achieve process injection, and full execution takeover.
WIN32 APIs [`GetThreadContext()`](https://learn.microsoft.com/en-us/windows/win32/api/processthreadsapi/nf-processthreadsapi-getthreadcontext) and [`SetThreadContext()`](https://learn.microsoft.com/en-us/windows/win32/api/processthreadsapi/nf-processthreadsapi-setthreadcontext) are used for this purpose.
The target thread must be in a `RUNNING` state, and the possibility of other threads interfering with the target thread must be taken into consideration.
This PoC doesn't address either of those issues, however, both can be resolved quite easily.
The injector tries to find a loop gadget (`jmp $`) in the target process as soon as possible, in order to prevent the thread from executing state altering functions, like `Sleep()`.

The injector will also by default completely discard the target's stack and allocate a new one.
It will also by default discard all acquired gadgets and create a **"Hijack Control Gadget"**, which is basically just a package of all required gadgets, in one location.

See [Gadgets](#gadgets) and [Execution Options](#execution-options) for more information.

### RemoteAPI
[`RemoteAPI.h`](https://github.com/x0reaxeax/GhostWriting64/blob/master/GhostWriting-x64/RemoteAPI.h) contains "remote" alternatives to some commonly used WINAPI functions, like `VirtualAlloc()` or `WriteProcessMemory()`.
While most of these are executed simply by crafting a context ready for execution of the target API function residing in the remote process, the `rWriteProcessMemory()` is an exception, as it doesn't rely on it's equivalent API call at all. Instead, to achieve writing to a remote process, a `MOV R/M8, R8` gadget is used as a foundation for off-brand cross-process `memcpy()` clone.

Full list of currently implemented RemoteAPI functions:
* `rVirtualAlloc `
* Equivalent `VirtualAlloc()`.
* `rVirtualProtect`
* Equivalent of `VirtualProtect()`.
* `rVirtualFree`
* Equivalent of `VirtualFree()`.
* `rWriteProcessMemory`
* Custom implementation of an cross-process `memcpy()`.
* `rLoadLibraryA`
* Equivalent of `LoadLibraryA()`.
* `r_puts`
* Equivalent of `puts()`.
* `rDirectInvoke`
* Custom invoker that calls arbitrary functions by their addresses.

### Gadgets
There are two `MOV` gadgets used in this demo - `MOV R/M8, R8` (`MOV8` gadget) and `MOV R/M64, R64` (`MOV64` gadget). These are dynamically searched for in the target process, and can be different each time the PoC is executed, as the injector searches for different possible combinations of the **ModR/M** byte, so the source and destination registers can differ. The search is done using a WIN32 function `ReadProcessMemory()`. ~~In theory, there's a way around this, but since this is not GhostReading, this is simply out of scope for now~~
However, in [`Defs.h`](https://github.com/x0reaxeax/GhostWriting64/blob/master/GhostWriting-x64/Defs.h), there is a functionality that will use hardcoded offsets to gadgets in `NTDLL`. This eliminates the need of `PROCESS_VM_OPERATION` and `PROCESS_VM_READ` access rights.

### Execution Options
There are a few options in [`Defs.h`](https://github.com/x0reaxeax/GhostWriting64/blob/master/GhostWriting-x64/Defs.h) that can be enabled to change some key factors on how the injector works:
* `KEEP_ORIGINAL_STACK`
* `READ_PROC_ADDR_LOCAL`
* `STEALTH`

#### `KEEP_ORIGINAL_STACK`:
* This option, despite it's name only mentioning the stack, will prevent discarding and replacing the original stack with a newly crafted one, but will also disable the use of "Hijack Control Gadget", which replaces all of the 3 necessary gadgets that were previously acquired from the process:
* `MOV8` gadget
* `MOV64` gadget
* Loop gadget

#### `READ_PROC_ADDR_LOCAL`:
* Enabling this will result in function addresses being fetched locally, via `GetModuleHandle()` + `GetProcAddress()` combo, this will also allow for dropping the handle to the target process immediately after hijacking the execution, as the RemoteAPI functions won't enumerate the target's loaded Core DLLs to resolve the function addresses from them. This should be left disabled if any weird hooks/relocations are present, which could cause differences between the Core DLL address mappings between the injector and it's target.

#### `STEALTH`:
* This option automatically enables both `KEEP_ORIGINAL_STACK` and `READ_PROC_ADDR_LOCAL`, with addition of relying on hardcoded `NTDLL` offsets to all required gadgets. This requires manually searching for all required gadgets inside `NTDLL`, and updating the offsets to these gadgets within the injector. This is highly unstable and should be generally avoided.

## FAQ
### Can you please speak English?
Yes, the main purpose of this PoC is to demonstrate a write primitive that doesn't call `WriteProcessMemory`, `NtWriteVirtualMemory`, `CreateRemoteThread`, or simply any APIs commonly used for WPM during process injection. This is utilized to pop a calc.

### Will this crash the target program?
It depends on the actions performed by the target.
Using the [RemoteAPIs](#remoteapi) will generally not crash the program, but will leave it in an internally unusable state, executing infinite loop.

### Can I see how it works without running it?
There is a slightly different implementation of this technique that I demonstrated a while ago, you can [watch it on YouTube](https://www.youtube.com/watch?v=fo3-J4jhuB4)

## Sources
This PoC doesn't reuse any code from the listed or any other sources. I simply wanted to write my own implementation of this technique, because I find it interesting.
I politely borrowed the idea, but all of the code was written from scratch.
http://blog.txipinet.com/2007/04/05/69-a-paradox-writing-to-another-process-without-openning-it-nor-actually-writing-to-it/
https://i.blackhat.com/USA-19/Thursday/us-19-Kotler-Process-Injection-Techniques-Gotta-Catch-Them-All-wp.pdf

## Tested on
* Windows 10 21H2, 22H2
* Windows 10 22H2

## DISCLAIMER
This project is licensed under the **MIT License**. The content of this repository exists purely for **educational purposes**.

> Written with [StackEdit](https://stackedit.io/).