
Fileless x64 Assembly C2 framework with dual-channel ICMP/DNS protocol pivoting, direct syscall execution, and ptrace-based process injection for stealthy command execution and data exfiltration.
________ ___ ___ ________ ________ _________ ________ ________
|\ ____\|\ \|\ \|\ __ \|\ ____\|\___ ___\ |\ ____\|\_____ \
\ \ \___| \ \ \\\ \ \ \|\ \ \ \___|\|___ \ \_| \ \ \___|\|____|\ \
\ \ \ __ \ \ __ \ \ \\\ \ \_____ \ \ \ \ \ \ \ ____\_\ \
\ \ \|\ \ \ \ \ \ \ \\\ \|____|\ \ \ \ \ \ \ \___|\____ \ \
\ \_______\ \__\ \__\ \_______\____\_\ \ \ \__\ \ \______\\_________\
\|_______|\|__|\|__|\|_______|\_________\ \|__| \|______\|_________|
\|_________|
Fileless, pure x64 Assembly C2 implant utilizing a Dual-Channel (ICMP / DNS) architecture. Zero libc. Zero disk. Invisible to standard EDR hooks.
⭐️ If you find this research useful, please consider giving it a star to support further development
🚨 FULL TECHNICAL RESEARCH & SOURCE CODE: This repository is a summary. For the complete architectural breakdown, W^X memory evasion details, and VTable implementation, visit the official project page: ICMP-Ghost Technical Breakdown
Ghost-C2 is a command-and-control framework written entirely in pure x64 Linux Assembly with no libc dependencies. Every operation goes through direct syscalls. There are no import tables, no dynamic linker artifacts, and no disk writes.
Originally built as a raw ICMP stealth channel, version 3.6.2 introduces a Dual-Channel Protocol Pivoting architecture. Operators can seamlessly switch the implant's communication channel between silent ICMP Raw Sockets and evasive DNS UDP Tunneling on the fly. The implant lives exclusively in RAM, injected into a running system process via a custom ptrace-based loader.
This project was built to explore how far user-space stealth and network state synchronization can go without touching the kernel.
┌─────────────────────────────────────────────────────────────┐
│ OPERATOR MACHINE │
│ │
│ ┌──────────────┐ │
│ │ client.asm │ ← Terminal UI: Prompt IP/Domain + Cmd │
│ │ (Operator │ Encrypts payload with Rolling XOR │
│ │ Console) │ State Sync: ICMP mode / DNS mode │
│ └──────┬───────┘ │
│ │ │
└──────────┼──────────────────────────────────────────────────┘
│ Channel 1: Raw ICMP (Stateless, Port-less)
│ Channel 2: DNS UDP Port 53 (Asymmetric)
┌──────────┼──────────────────────────────────────────────────┐
│ │ TARGET MACHINE │
│ ▼ │
│ ┌──────────────┐ ┌─────────────────────────────────┐ │
│ │ loader.asm │────▶│ sniff.asm (PIC) │ │
│ │ (Phantom │ │ Lives in RAM only │ │
│ │ Loader) │ │ inside host process │ │
│ └──────────────┘ └────────────────┬────────────────┘ │
│ │ │
│ 1. Scans /proc for target PID │ Listens ICMP/DNS │
│ 2. ptrace ATTACH │ Validates Auth │
│ 3. Force remote mmap (RW) │ Decrypts command │
│ 4. Inject PIC shellcode │ fork+execve │
│ 5. mprotect → RX │ memfd_create │
│ 6. Redirect RIP → shellcode │ Compress(DPCM-RLE)│
│ 7. ptrace DETACH → exits │ Encrypt & Frag. │
│ │ Sends Reply │
└─────────────────────────────────────────┼───────────────────┘
│ Encrypted Traffic
▼
[ client.asm ]
Receives & Validates
Decrypts Payload
Decompresses (Hybrid)
Reassembles & Prints
client.asm — Operator ConsoleThe attacker-side terminal. Handles UI, dynamic memory management, and target state synchronization. Can dispatch packets as either ICMP Echo Requests or DNS TXT queries. Listens for fragmented replies, prevents buffer overflows, and reconstructs the output. Features an "Active Target Reconnection" module to rescue orphaned sessions.
sniff.asm — PIC Implant AgentThe implant running on the target. Compiled as a raw binary (position-independent, no ELF headers) so it can be injected into arbitrary memory addresses. It dynamically updates its internal VTable to switch between ICMP sniffing and UDP DNS binding based on operator pivot commands.
Phantom_Loader/loader.asm — Injection EngineThe delivery mechanism. Scans /proc, finds a target process by comm name, and injects the PIC shellcode into it using a multi-stage ptrace state machine. Exits cleanly after injection — leaves no trace.
Ghost-C2 v3.6.2 allows the operator to hot-swap the network protocol without losing the agent. By sending specific pivot commands, the VTables in both the Master and the Agent are dynamically overwritten:
!D (Pivot to DNS): Both nodes close ICMP sockets and initialize UDP Port 53 communication. Ideal for bypassing strict Layer 3 filtering by blending into corporate DNS traffic.!I (Pivot to ICMP): The Agent closes UDP sockets, kills port bindings, and drops back into silent Raw Socket sniffing. Perfect for "Phantom" stealth mode.Ghost-C2's data transmission engine utilizes a hybrid compression and encoding layer heavily optimized in x86-64 Assembly.
Every outgoing ICMP packet is structured to be indistinguishable from a standard Linux ping:
struct timeval.iputils padding (0x10 to 0x1F) bypasses basic heuristic firewalls.Both directions are encrypted with a progressively shifting QWORD key. This keeps Shannon entropy low (unlike AES, which scores ~8.0 and triggers DPI anomalies). Rolling XOR produces entropy that looks like naturally noisy data. No cryptographic constants, no S-boxes, nothing for YARA to match.
The implant ignores all ICMP packets where ID + SEQ ≠ 45,000. The implant replies with packets where ID + SEQ = 55,000. This prevents OS echo confusion and filters out internet scanners or honeypots.
memfd_createCommand output never touches disk. The shell output is captured via an anonymous RAM file (memfd_create), named [shm] to blend into legitimate shared memory mappings in /proc/PID/fd.
Defeats modern kernel mitigations that forbid RWX memory. The loader uses a two-phase approach (Remote mmap with RW → Inject → Remote mprotect with RX). No page is ever simultaneously W and X.
All syscall numbers are split across two instructions to defeat static analysis and simple grep-based scanners.
To maintain strict OPSEC, the Ghost-C2 agent (sniff.asm) does not use external configurations. You must define your Master C2 IP, Port, and Decoy DNS Domain directly inside the assembly code before compiling and injecting.
Open sniff.asm and scroll to the very bottom of the .text segment. (Note: Because the agent is strictly Position Independent Code (PIC), there is no .data segment. All configuration variables are stored inline).
Modify the following values to match your Master Server:
db 127, 0, 0, 1 to your Master's IP.dw 0xB414 (Port 5300) to your desired port in Network Byte Order (e.g., 0x3500 for Port 53).nasm -f bin sniff.asm -o shellcode.bin
python3 -c "data = open('shellcode.bin', 'rb').read(); lines = ['\tdb ' + ', '.join(f'0x{b:02x}' for b in data[i:i+12]) for i in range(0, len(data), 12)]; open('c2_payload.txt', 'w').write('\n'.join(lines))"
c2_payload.txt.xor.py and replace the raw_asm variable's contents with your copied shellcode.python3 xor.py and copy the encrypted output.loader.asm.c2_payload: label.target db "cron", 10).nasm -f elf64 loader.asm -o loader.o
ld loader.o -o loader
Execute on the target machine with root privileges (sudo ./loader). The agent is now running entirely fileless.
Before compiling the Master Console, you must ensure its listener and target profiles align with your Agent's configuration. Open client.asm and navigate to the section .data area.
Locate master_bind_addr. This is where the Master listens for incoming DNS beacons.
UDP Port: Change dw 0xB414 to match the port your Agent is sending to.
Note: This must be in Network Byte Order. For Port 53, use 0x3500.
Locate target_addr. This port is used when you perform a DNS Pivot (!D) or use the Reconnect module.
Port Alignment: Change dw 0xB414 to match the UDP port the Agent is listening on. If these ports do not match, the (Deadlock) will occur as the Master will be shouting into the wrong void.
Once configured, assemble and link the Master:
nasm -f elf64 client.asm -o client.o
ld client.o -o client
Protip: Always keep a "Profile Sheet" for your operation. If you change the port to 0x3500 (Port 53) in sniff.asm, you MUST update both master_bind_addr and target_addr in client.asm before the operation begins.
Note: The Operator Console requires root privileges to bind raw sockets and UDP port 53.
To ensure persistent access and prevent session loss, always pivot the Agent back to ICMP Mode (!I) before terminating your Master Console session.
The Logic: ICMP is Ghost-C2's "Golden Channel"—it is stateless, passive, and always reachable via the Target IP.
The Risk: DNS mode relies on dynamic UDP port synchronization. If the Master Console is closed while in DNS mode, the Agent remains "trapped" in a UDP listening state. Re-establishing connection would require knowing the Agent's specific ephemeral port, which is lost upon Master restart.
Tested in a controlled lab environment against active traffic inspection:
| Test | Result |
|---|---|
| Suricata v8.0.3 (Emerging Threats ruleset) | ✅ Bypassed |
| Suricata v8.0.3 (Custom ICMP payload rules) | ✅ Bypassed |
| DigitalOcean FRA1 gateway | ✅ 100% exfiltration success |
| Alerts generated during ~25KB exfiltration | 0 |
Ghost-C2 interacts directly with the Linux kernel:
mprotect dependenciesThe absence of a PTY is an architectural decision, not a limitation:
/dev/ptmx and ioctl calls that EDRs heavily monitor.Ghost-C2 is a hyper-stealth command execution and exfiltration implant. Interactivity trades invisibility for convenience — this project chose invisibility.
By design, Pull Requests and Forks are strictly ignored. The architecture of this project is maintained directly by the author. If you find a bug, logic flaw, or have a feature suggestion, please open an Issue. Keep it objective and technical.
Ghost-C2 is built with passion, sweat, and pure x64 Assembly. If this project helped you understand low-level evasion, protocol mimicry, or just made your red teaming operations smoother, consider supporting the development!
Ghost-C2 is developed strictly for educational purposes, reverse engineering, and authorized cybersecurity research.
As of version 3.6.1 and onwards, this project is licensed under the GNU Affero General Public License v3.0 (AGPLv3). Any entity interacting with or modifying this software over a network must disclose their complete source code as mandated by the license. Commercial exploitation or integration into proprietary/closed-source platforms is strictly prohibited.
Copyright (c) 2026 JM00NJ (commSync). All Rights Reserved.
The author is not responsible for any illegal use or damage caused by this tool. Use it at your own risk.
| Syscall | Number | Usage |
|---|
sys_socket | 41 | Raw ICMP / UDP socket creation |
sys_recvfrom | 45 | Passive ICMP/UDP packet capture |
sys_sendto | 44 | ICMP/UDP reply transmission |
sys_bind | 49 | UDP DNS Port binding |
sys_memfd_create | 319 | Anonymous RAM file for output |
sys_dup2 | 33 | stdout/stderr redirection |
sys_execve | 59 | Shell command execution |
sys_fork | 57 | Process isolation |
sys_ptrace | 101 | Process injection + anti-debug |
sys_getdents64 | 217 | /proc directory parsing |
sys_mmap | 9 | Remote memory allocation |
sys_mprotect | 10 | W^X permission switch |