Identifying IRC Botnet C2 via PRIVMSG Command Pattern Analysis and Bot Fingerprinting
Théorie
Why This Matters
IRC-based botnets dominated the threat landscape from 2003 to 2012 and remain in operational use today, particularly in the criminal underground managing DDoS-for-hire services. The Storm Worm botnet at its peak in 2007 had an estimated 1–10 million infected hosts receiving commands via IRC channels. Although modern botnets often use HTTP or peer-to-peer C2, IRC-based bots are simpler to analyse — their cleartext protocol makes PCAP forensics extremely direct. Every analyst should be able to extract bot commands from an IRC C2 capture without specialised tools.
Core Concept
IRC (Internet Relay Chat) is a text-based protocol defined in RFC 1459. Bots connect to an IRC server (typically TCP port 6667 for plaintext, 6697 for TLS), authenticate with a password, choose a nickname, and join one or more channels. The botmaster posts commands as PRIVMSG messages to the channel; each bot reads the channel and executes commands matching its parser.
Key IRC protocol messages in botnet context:
- NICK <botname> — bot sets its nickname (often random or OS-derived)
- JOIN #<channel> <key> — bot joins the C2 channel, optionally with a password
- PRIVMSG #<channel> :<command> — botmaster sends a command to all channel members
- PRIVMSG <botnick> :<reply> — bot reports results via private message to the botmaster
- MODE #<channel> +s +i — channel is set secret and invite-only to hide it from channel listings
Detection signatures: connections to port 6667/6697 from internal hosts, IRC keyword sequences in TCP stream (NICK, JOIN, PRIVMSG), multiple internal hosts connecting to the same external server and channel, repeated identical PRIVMSG messages (broadcast command).
Technical Deep-Dive
# Detect IRC protocol: filter on port 6667 or IRC keyword presence
tshark -r capture.pcap
-Y "tcp.port == 6667 || tcp.port == 6697"
-T fields -e frame.number -e ip.src -e ip.dst
-e tcp.srcport -e tcp.dstport -e tcp.stream
-E header=y -E separator="," | head -30
# Follow all IRC streams and dump to text
tshark -r capture.pcap -q
-z "follow,tcp,ascii,0" 2>/dev/null | head -100
# Extract all IRC PRIVMSG commands (bot commands and replies)
tshark -r capture.pcap -Y "irc"
-T fields
-e frame.time_relative
-e ip.src
-e irc.request
-e irc.response
-E header=y -E separator=","
# List all unique IRC channels joined
tshark -r capture.pcap -Y "irc.request contains "JOIN""
-T fields -e irc.request | sort -u
# Count PRIVMSGs per channel to identify highest-traffic C2 channels
tshark -r capture.pcap -Y "irc.request contains "PRIVMSG""
-T fields -e irc.request
| awk '{print $2}' | sort | uniq -c | sort -rn
from scapy.all import rdpcap, TCP, Raw, IP
import re
IRC_PATTERNS = {
"nick": re.compile(r'^NICKs+(S+)', re.MULTILINE),
"join": re.compile(r'^JOINs+(S+)', re.MULTILINE),
"privmsg": re.compile(r'^PRIVMSGs+(S+)s+:(.*)', re.MULTILINE),
"mode": re.compile(r'^MODEs+(.*)', re.MULTILINE),
"pass": re.compile(r'^PASSs+(S+)', re.MULTILINE),
}
def analyse_irc_stream(raw_tcp_payload: bytes) -> dict:
try:
text = raw_tcp_payload.decode("utf-8", errors="replace")
except Exception:
return {}
findings: dict = {}
for key, pattern in IRC_PATTERNS.items():
matches = pattern.findall(text)
if matches:
findings[key] = matches
return findings
packets = rdpcap("capture.pcap")
streams: dict = {}
for pkt in packets:
if pkt.haslayer(TCP) and pkt.haslayer(Raw):
if pkt[TCP].dport in (6667, 6697) or pkt[TCP].sport in (6667, 6697):
sid = pkt[TCP].stream if hasattr(pkt[TCP], "stream") else 0
streams.setdefault(sid, b"")
streams[sid] += bytes(pkt[Raw])
for sid, payload in streams.items():
results = analyse_irc_stream(payload)
if results:
print(f"
=== IRC Stream {sid} ===")
for key, values in results.items():
for v in values:
print(f" {key.upper():10s}: {v}")
Analytical Methodology
- Apply display filter
tcp.port == 6667 || tcp.port == 6697to isolate potential IRC traffic. If the botnet uses a non-standard port, look for TCP streams where payload content begins withNICKorUSER— IRC connection handshake keywords. - Right-click any packet in the suspected IRC stream → Follow → TCP Stream. The entire IRC session appears as cleartext ASCII. Identify: server welcome message (lines starting with numeric codes like
001,372,376), bot nick (NICKcommand), channel join (JOIN), and command reception (PRIVMSG). - Extract all PRIVMSG lines from the stream. These contain the botmaster's commands and the bots' responses. Note the channel name (first PRIVMSG argument) and the command content (after the colon).
- Identify the bot command vocabulary. Common IRC bot command prefixes:
!ddos <target> <duration>,!download <url>,!exec <command>,!update <url>. Parse these to reconstruct the attacker's operational orders. - Map all internal hosts joining the same C2 channel. Filter
irc.request contains "JOIN #<channel>"to enumerate the botnet membership visible in the capture. Each joining IP is an infected host. - Check for identical PRIVMSG commands received by multiple bots in quick succession — this is the broadcast command pattern. The time delta between duplicate PRIVMSGs indicates server fan-out speed.
- Document: C2 server IP and port, channel name and password, botmaster nick, all commands issued with timestamps, all responding bot nicks and their source IPs, and any URLs or external resources referenced in commands.
Common Analytical Errors
- Missing IRC on non-standard ports: Botnets rarely use port 6667 in modern deployments — they use ephemeral ports (8080, 443, 12345) to evade simple port-based filtering. Search for IRC protocol keywords (
NICK,JOIN,PRIVMSG) in all TCP streams, not just port 6667. - Ignoring bot responses: PRIVMSG replies from bots to the botmaster are as forensically valuable as commands. Bot replies include DDoS target confirmations, download success/failure, exec output, and system information. Read the full bidirectional stream.
- Underestimating the MODE command:
MODE #channel +s +i(secret, invite-only) andMODE #channel +k <password>(key-protected) are used to hide C2 channels. These appear early in the session log and confirm deliberate operational security. - Conflating IRC server and botmaster traffic: The IRC server sends numeric response codes and relay messages. The botmaster is identified by their nick and the
PRIVMSG #channelpattern. Distinguish server protocol traffic from botmaster operational traffic when reconstructing the timeline. - Missing TLS-wrapped IRC: Port 6697 uses TLS. If the PCAP contains the TLS handshake but no session keys, the stream content is unreadable. Check for exported session keys in the PCAP (Wireshark can load a keylog file) or look for pre-negotiation NICK/USER if the connection starts before TLS upgrade.
NICE Framework Alignment
| Code | Knowledge/Skill/Task Statement | How This Card Develops It |
|---|---|---|
| K0046 | Knowledge of intrusion detection systems and methodologies | Identifying IRC botnet C2 signatures — port 6667 connections, IRC keyword sequences, broadcast PRIVMSG patterns — that IDS rules detect |
| K0093 | Knowledge of network protocols | Understanding IRC protocol mechanics: connection handshake, channel join/key, PRIVMSG broadcast, numeric response codes |
| K0221 | Knowledge of OSI model and network layers | IRC operates at layer 7 over TCP; understanding how application-layer protocol analysis reconstructs attacker intent from packet captures |
| S0046 | Skill in performing packet-level analysis | Following TCP streams, parsing IRC protocol messages, extracting command/response pairs, and mapping botnet membership from PCAP |
| T0023 | Collect intrusion artifacts for use in forensic analysis | Documenting C2 server details, channel names, botmaster commands, bot membership, and command timeline as structured forensic evidence |
Further Reading
- RFC 1459: Internet Relay Chat Protocol — J. Oikarinen & D. Reed (IETF) — protocol specification
- SANS Reading Room: "IRC Botnet Analysis" — technical walkthrough of IRC C2 packet analysis
- Botnets: The Killer Web App — Craig Schiller et al., Chapter 4: IRC-Based Botnet Architecture (Syngress)
Challenge Lab
Renforcez votre apprentissage avec un défi généré basé sur la compétence de cette carte.