Process Hollowing implementation in C++ for Windows.
Replace the memory of a legitimate process with a malicious PE payload.
CR: Tg: @BatmanPriv | GitHub: github.com/batmanpriv
Process Hollowing is a technique used to:
- Create a suspended process (e.g.,
notepad.exe) - Unmap its original memory
- Inject a custom PE payload
- Resume execution with the injected code
This POC is minimal, clean, and educational.
g++ -o hollow.exe Process-Hollowing.cppg++ -O2 -s -o hollow.exe Process-Hollowing.cpphollow.exe <host.exe> <payload.exe>hollow.exe notepad.exe payload.exehollow.exe "C:\Windows\System32\calc.exe" "C:\payload.exe"Inside the example/ folder:
// msgbox.go
package main
import (
"syscall"
"unsafe"
)
func main() {
user32 := syscall.NewLazyDLL("user32.dll")
messageBox := user32.NewProc("MessageBoxW")
title, _ := syscall.UTF16PtrFromString("Hollow")
msg, _ := syscall.UTF16PtrFromString("🔥 Payload Executed Successfully!")
messageBox.Call(0, uintptr(unsafe.Pointer(msg)), uintptr(unsafe.Pointer(title)), 0)
}go build -ldflags="-H=windowsgui -linkmode=internal -buildmode=pie" -o payload.exe example/msgbox.go| Step | Description |
|---|---|
| 1 | Create target process in CREATE_SUSPENDED state |
| 2 | Read the payload PE file into memory |
| 3 | Validate DOS and NT headers |
| 4 | Get the target process's base address from the PEB |
| 5 | Unmap the original executable (NtUnmapViewOfSection) |
| 6 | Allocate new memory in the target process |
| 7 | Write the PE headers and sections |
| 8 | Set the entry point in the thread context |
| 9 | Resume the thread to execute the payload |
| OS | Architecture |
|---|---|
| Windows 10 | x64 / x86 |
| Windows 11 | x64 / x86 |
| Windows 7 | x64 / x86 |
| Windows Server 2019 | x64 |
| Windows Server 2022 | x64 |
| Requirement | Description |
|---|---|
| Architecture | Host and payload must match (both x64 or both x86) |
| Privileges | Administrative privileges recommended |
| Payload Format | Position Independent Executable (PIE) |
| Compiler | GCC / MinGW for building the hollowing tool |
| Dependencies | Windows SDK (included with MinGW) |
| Question | Answer |
|---|---|
❓ Why does my payload crash with 0xc0000142? |
Architecture mismatch (32-bit vs 64-bit), payload not compiled as PIE, or missing DLL dependencies. |
| ❓ Does this work with DLLs? | No. This POC is designed for EXE payloads only. |
| ❓ Can I use any EXE as payload? | Yes, but it must be compiled as Position Independent Executable (PIE). |
❓ Why use -buildmode=pie? |
Allows the payload to run from any base address, not just its preferred one. |
| ❓ What if VirtualAllocEx fails with targetBase? | The code automatically retries with NULL to let the system choose an address. |
| ❓ Is this detected by antivirus? | Most AVs detect process hollowing. This is for educational purposes only. |
| ❓ Can I inject into protected processes? | No. Requires administrative privileges and doesn't work with protected processes. |
| ❓ What languages can I use for payload? | Any language that compiles to PE (Go, C, C++, Rust, etc.) with PIE support. |
| ❓ Does it work with GUI applications? | Yes, as long as they are compiled as PIE and have a GUI entry point. |
| ❓ What is the minimum Windows version? | Windows 7 and above. |
| ❓ Does it require Admin rights? | Recommended but not always required for user-mode processes. |
| ❓ Can I inject into 64-bit from 32-bit process? | No, the tool must match the target architecture. |
| ❓ Is there a log file? | Yes, hollow.log is created in the current directory. |
| ❓ What if the payload is too small? | Some AVs detect small payloads. Add padding to increase size. |
| ❓ Does it work with .NET applications? | Yes, but .NET payloads need the .NET runtime available. |
| ❓ Can I use this for malware? | This is for research and education. Misuse is prohibited. |
| ❓ How to debug failures? | Check the log file, verify architecture, and ensure PIE compilation. |
This tool is for educational and research purposes only.
Use only in authorized environments with proper permissions.
The author is not responsible for any misuse or damage caused by this tool.
| Link | Description |
|---|---|
| GitHub Repository | Source code and documentation |
| Telegram | Contact the author |
| IRED Team Writeup | Technical explanation |
| Microsoft PE Format | Official PE specification |
| Feature | Status |
|---|---|
| Minimal code (~150 lines) | ✅ |
| Color-coded console output | ✅ |
| Architecture detection (x64/x86) | ✅ |
| PE validation (DOS + NT headers) | ✅ |
| Error handling with meaningful messages | ✅ |
| Automatic fallback allocation | ✅ |
| Section-by-section PE injection | ✅ |
| Log file generation | ✅ |
| Cross-platform (Windows only) | ✅ |
| PIE payload support | ✅ |
- The log file is saved as
hollow.login the current directory - Both processes must be the same architecture (32-bit or 64-bit)
- For Go payloads, always use
-buildmode=pie - For C/C++ payloads, use
-pieflag with GCC - For Rust payloads, use
-C relocation-model=pic - For .NET payloads, ensure .NET runtime is available
- Always test in a controlled environment first
- The tool works with any PE file that supports relocation
# Clone the repository
git clone https://github.com/batmanpriv/PH-Poc.git
cd PH-Poc
# Compile the hollowing tool
g++ -o hollow.exe Process-Hollowing.cpp
# Build the example payload
cd example
go build -ldflags="-H=windowsgui -linkmode=internal -buildmode=pie" -o payload.exe msgbox.go
cd ..
# Execute
hollow.exe notepad.exe example/payload.exeContributions are welcome! Please:
- Fork the repository
- Create a feature branch
- Submit a pull request
- Keep code minimal and clean
- Add comments where necessary
- Update documentation
- Test on Windows 10/11
When the payload is loaded at a different base address than its preferred address, relocations must be applied. PIE allows this.
The tool reads the PEB to find the current base address of the host process.
Using NtUnmapViewOfSection instead of VirtualFreeEx ensures proper unmapping of the host image.
The thread context is modified to point to the new entry point, allowing the payload to execute.
| Metric | Value |
|---|---|
| Tool size | ~50 KB (optimized) |
| Injection speed | < 1 second |
| Memory usage | ~5 MB |
| CPU usage | Minimal |
| Problem | Solution |
|---|---|
| Compilation fails | Ensure MinGW is installed and in PATH |
| Payload doesn't run | Check architecture mismatch |
| Error 0xc0000142 | Compile payload with PIE |
| Access denied | Run as Administrator |
| Process crashes | Verify PE integrity |
| No message box | Check payload compilation |
| Anti-virus blocks | Add to exclusions (testing only) |
Made with ❤️ for the security research community