Reconstructing IRC Sessions via Protocol PCAP Analysis and Channel Message Content Recovery
Theory
Why This Matters
IRC remains the protocol of choice for legacy botnets (Storm, Conficker, Mirai precursors) and underground communities. Forensic captures from compromised systems in APT investigations and CTF challenges frequently contain IRC sessions where attackers issued commands, exfiltrated data in PRIVMSG payloads, or coordinated activity through shared channels. The plaintext nature of standard IRC makes captures highly readable once filtered — analysts who know the protocol's command structure can reconstruct an entire attacker interaction from a TCP stream in minutes.
Core Concept
IRC (Internet Relay Chat) is a plaintext line-oriented protocol typically running on port 6667 (unencrypted) or 6697 (TLS). Each line is a message terminated by . Key commands:
NICK <nickname>— client sets its display name.USER <username> <mode> * :<realname>— client registration.JOIN #<channel>— client joins a channel.PRIVMSG #<channel> :<message>— client sends a message to a channel or user.PART #<channel>— client leaves a channel.QUIT :<reason>— client disconnects.MODE #<channel> +o <nick>— grant operator status.TOPIC #<channel> :<topic>— set channel topic (often used by bots for C2 commands).
Server responses use numeric codes: 001 (RPL_WELCOME), 332 (RPL_TOPIC), 353 (RPL_NAMREPLY — channel member list), 433 (ERR_NICKNAMEINUSE).
Bot behaviour indicators: identical PRIVMSG content sent to multiple channels in rapid succession; automated NICK registration with a pattern (e.g., bot_[random]); JOIN immediately followed by PRIVMSG to the channel without any human typing delay; TOPIC changes carrying commands (e.g., !exec cmd, !flood target); multiple TCP sessions from the same IP with different nicknames.
Technical Deep-Dive
# Display all IRC traffic from a PCAP
tshark -r capture.pcap -Y "irc"
-T fields -e frame.number -e frame.time_relative
-e ip.src -e ip.dst
-e irc.request -e irc.response
-E header=y
# Extract PRIVMSG content specifically
tshark -r capture.pcap
-Y "irc.request contains "PRIVMSG""
-T fields -e frame.time_relative -e ip.src
-e irc.request
# Extract all client commands (requests only)
tshark -r capture.pcap -Y "irc.request"
-T fields -e frame.time_relative -e ip.src -e irc.request
| sort
# Follow a specific IRC TCP stream to read the full session
# First identify the stream index:
tshark -r capture.pcap -Y "tcp.port == 6667"
-T fields -e tcp.stream | sort -u
# Then export that stream as text:
tshark -r capture.pcap -q -z "follow,tcp,ascii,<stream_index>"
# Extract all channel names and nicknames
tshark -r capture.pcap -Y "irc.request contains "JOIN""
-T fields -e irc.request | grep -oP "JOIN KS+"
tshark -r capture.pcap -Y "irc.request contains "NICK""
-T fields -e irc.request | grep -oP "NICK KS+"
# Detect bot timing: measure inter-PRIVMSG delta for same source IP
tshark -r capture.pcap
-Y "irc.request contains "PRIVMSG""
-T fields -e frame.time_epoch -e ip.src
| awk 'BEGIN{prev=0; previp=""}
{
if ($2==previp && prev>0) printf "delta=%.3fs src=%s
", $1-prev, $2
prev=$1; previp=$2
}'
#!/usr/bin/env python3
"""
Parse IRC TCP stream (raw text extracted via tshark follow) and
reconstruct per-channel conversation with timestamps.
"""
import re, sys
# Input: output of tshark -q -z "follow,tcp,ascii,N" piped to stdin
PRIVMSG_RE = re.compile(r':(?P<nick>[^!]+)![^s]+ PRIVMSG (?P<target>S+) :(?P<msg>.+)')
JOIN_RE = re.compile(r':(?P<nick>[^!]+)![^s]+ JOIN :?(?P<channel>S+)')
TOPIC_RE = re.compile(r':(?P<nick>[^!]+)![^s]+ TOPIC (?P<channel>S+) :(?P<topic>.+)')
channels = {} # channel -> list of (nick, msg)
nicks_seen = set()
for line in sys.stdin:
line = line.rstrip()
m = JOIN_RE.match(line)
if m:
channels.setdefault(m.group("channel"), [])
nicks_seen.add(m.group("nick"))
continue
m = PRIVMSG_RE.match(line)
if m:
target = m.group("target")
channels.setdefault(target, []).append((m.group("nick"), m.group("msg")))
continue
m = TOPIC_RE.match(line)
if m:
print(f"[TOPIC] {m.group('channel')} set by {m.group('nick')}: {m.group('topic')}")
print(f"
Nicknames observed: {sorted(nicks_seen)}")
for channel, msgs in channels.items():
print(f"
=== {channel} ({len(msgs)} messages) ===")
for nick, msg in msgs:
print(f" <{nick}> {msg}")
Analytical Methodology
- Apply Wireshark display filter
ircortcp.port == 6667to isolate IRC traffic. If the capture contains TLS on port 6697, first apply SSLKEYLOGFILE decryption. - Identify the NICK and USER commands at the start of each session to determine the nickname(s) and username(s) used by the client. Multiple sessions with different nicks from the same IP are a strong bot indicator.
- Follow each distinct IRC TCP stream using Wireshark → Right-click → Follow → TCP Stream. The plain-text conversation appears in the stream window. Read the JOIN commands to identify channels the client entered.
- Extract all PRIVMSG commands. For each, note: sender nick, target (channel or user), message content, and timestamp. Messages arriving at precise intervals (< 500ms variance) suggest automation.
- Examine TOPIC commands. Botnets frequently encode C2 commands in channel topics — the bot master sets the topic to
!attack 1.2.3.4 80and all connected bots read the topic on join and execute the command. - Identify bot command-response patterns: a PRIVMSG from the master containing
!<command>followed by multiple PRIVMSG replies from different nicks within seconds. Each reply represents a separate infected host reporting back. - Reconstruct the attacker interaction timeline: NICK/USER (connect), JOIN (enter C2 channel), TOPIC/PRIVMSG (issue commands), responses (bot activity), PART/QUIT (disconnect). This forms the incident narrative.
- Correlate IRC nicknames with source IPs. If multiple IPs share a nickname pattern (e.g.,
victim_prefix) and all join the same channel, enumerate all IPs — each represents a compromised host.
Common Analytical Errors
- Filtering only on port 6667: IRC servers commonly run on non-standard ports (7000, 8080, 31337) to evade port-based filtering. Use the
ircprotocol dissector filter rather thantcp.port == 6667alone; Wireshark heuristically detects IRC on arbitrary ports. - Missing server numeric responses: IRC server responses (numeric codes like
001,332,353) contain valuable information — channel topic at join time, member list, server name. Analysts focused only on client commands miss this context. - Confusing NOTICE with PRIVMSG for bot commands: Some botnets use
NOTICErather thanPRIVMSGto issue commands (NOTICE is not echoed back to the sender in standard IRC, making it more stealthy). Filter forirc.request contains "NOTICE"as well. - Overlooking DCC (Direct Client-to-Client): DCC SEND in a PRIVMSG establishes a direct TCP file transfer. A
DCC SEND <filename> <ip_decimal> <port> <size>message in a PRIVMSG indicates a file transfer offer — extract the IP, port, and filename from the DCC parameters and correlate with other TCP streams in the PCAP.
NICE Framework Alignment
| Code | Knowledge/Skill/Task Statement | How This Card Develops It |
|---|---|---|
| K0046 | Knowledge of intrusion detection systems and methodologies | IRC C2 channel detection is a foundational botnet IDS detection use case |
| K0093 | Knowledge of network protocols | Understanding IRC message format, numeric codes, and client-server exchange structure |
| K0221 | Knowledge of OSI model and network layers | IRC operates at layer 7 over TCP at layer 4; stream reassembly is required for complete message recovery |
| S0046 | Skill in performing packet-level analysis | Applying IRC-specific tshark filters and TCP stream following to reconstruct bot command interactions |
| T0023 | Collect intrusion artifacts for use in forensic analysis | IRC channel logs and bot command records are forensic artifacts establishing attacker objectives and botnet scope |
Further Reading
- RFC 1459: Internet Relay Chat Protocol — original IRC specification with full command reference
- SANS ISC: "IRC Botnet Traffic Analysis" handler diary entries
- Wireshark Wiki: IRC protocol dissector documentation
- Mandiant/FireEye: "IRC Botnets — Anatomy of a Classic C2 Infrastructure" (threat report)
- CTF Wiki: IRC protocol challenge techniques and common encoding patterns in PRIVMSG payloads
Challenge Lab
Reinforce your learning with a hands-on generated challenge based on this card's competency.