ProcessGhosting
Process Ghosting technique implementation in Rust - Execute PE files from memory without leaving traces on disk
Install / Use
/learn @BlackTechX011/ProcessGhostingREADME
ProcessGhosting 👻
A Rust implementation of the Process Ghosting technique by BlackTechX
Process Ghosting is an advanced code execution technique that allows running executable code without leaving traces on the filesystem. This library provides a safe, easy-to-use Rust API for implementing this technique.
📋 Table of Contents
- What is Process Ghosting?
- How It Works
- Technical Deep Dive
- Installation
- Quick Start
- API Reference
- Examples
- Hex Utilities
- Architecture Support
- Building
- Security Considerations
- Credits
- License
👻 What is Process Ghosting?
Process Ghosting is a technique discovered by Gabriel Landau at Elastic Security. It exploits the Windows file system and process creation mechanisms to execute code from a file that no longer exists on disk.
Key Features
| Feature | Description | |---------|-------------| | 🔒 Fileless Execution | Payload file is deleted before process starts | | 🕵️ Anti-Forensics | No file remains on disk for security tools to scan | | 🛡️ Evasion | Bypasses many file-based security products | | 👤 Stealth | Process appears to run from a legitimate path | | 🦀 Pure Rust | Safe, fast, and memory-efficient implementation | | 📦 Easy API | Simple builder pattern for configuration |
🔬 How It Works
Process Ghosting exploits the Windows NT kernel's handling of delete-pending files:
┌─────────────────────────────────────────────────────────────────┐
│ PROCESS GHOSTING FLOW │
└─────────────────────────────────────────────────────────────────┘
┌──────────────┐
│ START │
└──────┬───────┘
│
▼
┌───────────────────────┐
│ 1. Create temp file │
└───────────┬───────────┘
│
▼
┌────────────────────────┐
│ 2. Set delete-pending │
│ (NtSetInformationFile) │
└───────────┬────────────┘
│
▼
┌───────────────────────┐
│ 3. Write PE payload │
│ to the file │
└───────────┬───────────┘
│
▼
┌───────────────────────┐
│ 4. Create SEC_IMAGE │
│ section from file │
└───────────┬───────────┘
│
▼
┌───────────────────────┐
│ 5. Close file handle │
│ ⚠️ FILE DELETED! ⚠️ │
└───────────┬───────────┘
│
▼
┌───────────────────────┐
│ 6. Create process │
│ from the section │
└───────────┬───────────┘
│
▼
┌───────────────────────┐
│ 7. Setup PEB and │
│ process parameters │
└───────────┬───────────┘
│
▼
┌───────────────────────┐
│ 8. Create thread at │
│ entry point │
└───────────┬───────────┘
│
▼
RUNNING
(No file! 👻)
The Magic Explained
- Delete-Pending State: When a file is marked for deletion but still has an open handle, it enters a "delete-pending" state
- Section Creation: Windows allows creating an image section from a delete-pending file
- File Deletion: Once we close the file handle, the file is deleted from disk
- Process Creation: The section (now without a backing file) can still be used to create a process
🔧 Technical Deep Dive
NT API Functions Used
| Function | Purpose |
|----------|---------|
| NtOpenFile | Open temp file with DELETE permission |
| NtSetInformationFile | Mark file as delete-pending |
| NtCreateSection | Create SEC_IMAGE section |
| NtCreateProcessEx | Create process from section |
| NtQueryInformationProcess | Get PEB address |
| RtlCreateProcessParametersEx | Create process parameters |
| NtAllocateVirtualMemory | Allocate memory in target |
| NtWriteVirtualMemory | Write parameters to target |
| NtCreateThreadEx | Start execution |
| RtlImageNtHeader | Parse PE headers |
Memory Layout
┌───────────────────────────────────────────────────┐
│ TARGET PROCESS MEMORY │
├───────────────────────────────────────────────────┤
│ │
│ ┌──────────────────────────────────────────────┐ │
│ │ MAPPED PE IMAGE │ │
│ ├──────────────────────────────────────────────┤ │
│ │ DOS Header (MZ) │ │
│ │ NT Headers │ │
│ │ └─ OptionalHeader.AddressOfEntryPoint ────┼─┼──► Entry Point
│ │ Section Headers │ │
│ ├──────────────────────────────────────────────┤ │
│ │ .text (Code) ◄── Execution starts │ │
│ │ .rdata (Read-only data) │ │
│ │ .data (Initialized data) │ │
│ │ .rsrc (Resources) │ │
│ └──────────────────────────────────────────────┘ │
│ │
│ ┌──────────────────────────────────────────────┐ │
│ │ PEB │ │
│ │ ├─ ImageBaseAddress │ │
│ │ └─ ProcessParameters | |
│ └──────────────────────────────────────────────┘ │
│ │ │
│ ┌───────────────────────────────────▼──────────┐ │
│ │ RTL_USER_PROCESS_PARAMETERS │ │
│ │ ImagePathName: C:\Windows\System32\svchost │ │
│ │ CommandLine: svchost.exe │ │
│ │ Environment: ... │ │
│ └──────────────────────────────────────────────┘ │
└───────────────────────────────────────────────────┘
Comparison with Other Techniques
| Technique | File on Disk During Execution | Detectable by File Scan | Complexity | |-----------|------------------------------|------------------------|------------| | Process Ghosting | ❌ No | ❌ No | ⭐⭐⭐ | | Process Hollowing | ✅ Yes (legitimate) | ⚠️ Maybe | ⭐⭐ | | Process Doppelgänging | ❌ No | ❌ No | ⭐⭐⭐⭐ | | DLL Injection | ✅ Yes | ✅ Yes | ⭐⭐ | | Reflective Loading | ❌ No | ⚠️ Memory scan | ⭐⭐⭐ |
📦 Installation
Add to your Cargo.toml:
[dependencies]
ProcessGhosting = "0.1"
Or using cargo:
cargo add ProcessGhosting
🚀 Quick Start
Method 1: From File
use process_ghosting::{GhostingBuilder, init};
fn main() -> Result<(), String> {
init(); // Print banner
GhostingBuilder::from_file("payload.exe")?
.x64()
.with_logging()
.execute()
}
Method 2: From Bytes
use process_ghosting::GhostingBuilder;
fn main() -> Result<(), String> {
let payload = std::fs::read("payload.exe").unwrap();
GhostingBuilder::new(&payload)
.x64()
.execute()
}
Method 3: From Hex String
use process_ghosting::GhostingBuilder;
fn main() -> Result<(), String> {
let hex = "0x4D, 0x5A, 0x90, ..."; // Your payload
GhostingBuilder::from_hex_string(hex)?
.x64()
.execute()
}
Method 4: Embedded at Compile Time
use process_ghosting::GhostingBuilder;
const PAYLOAD: &[u8] = include_bytes!("../payload.exe");
fn main() -> Result<(), String> {
GhostingBuilder::new(PAYLOAD)
.x64()
.silent()
.execute()
}
Method 5: Quick Functions
use process_ghosting::{ghost_payload_file, ghost_payload};
fn main() -> Result<(), String> {
// From file
ghost_payload_file("payload.exe")?;
// From bytes
let bytes = std::fs::read("payload.exe").unwrap();
ghost_payload(&bytes)
}
📚 API Reference
GhostingBuilder
Main builder for configuring process ghosting operations.
// Creation methods
GhostingBuilder::new(payload: &[u8]) -> Self
GhostingBuilder::from_file(path: &str) -> Result<Self, String>
GhostingBuilder::from_hex_string(hex: &str) -> Result<Self, String>
GhostingBuilder::from_hex_array(bytes:
