intermediatecat/networking~2 min read
DNS Tunneling & Covert Exfiltration
Detect, decode, and analyze data exfiltration hidden inside DNS queries and TXT records using Wireshark and TShark.
// prerequisite reading
What is DNS Tunneling?
DNS (Domain Name System) is rarely blocked by network firewalls or egress filters because it is essential for resolving domain names to IP addresses.
Attacker malware abuses DNS by encoding data inside subdomains of queries sent to a controlled authoritative DNS server:
[ Compromised Host ] ---> DNS Query: 464c41477b646e735f70776e65647d.attacker.com ---> [ Rogue DNS Server ]
The rogue DNS server extracts the base64/hex payload from the query hostname (464c41477b... $\rightarrow$ FLAG{dns_pwned}).
Common DNS Tunneling Signature Indicators
- High volume of DNS requests to a single uncommon parent domain.
- Unusually long hostname labels (near the 63-character sub-label limit or 253-character FQDN limit).
- High entropy / pseudo-random strings in subdomain labels (e.g.,
a8f1b9c4.attacker.com). - Abnormal distribution of query types: High frequency of
TXT,NULL,MX, orCNAMErecords instead of standardAorAAAA.
Extracting DNS Exfiltrated Data with TShark
Given a PCAP file containing exfiltrated DNS queries:
# Filter all DNS query names ending with target domain
tshark -r capture.pcap -Y "dns.flags.response == 0 && dns.qry.name contains 'attacker.com'" -T fields -e dns.qry.name
Sample output:
666c61677b646e73.attacker.com
5f74756e6e656c69.attacker.com
6e675f6674777d.attacker.com
Python Exfiltration Reassembly Script
Write a Python script to strip the parent domain, concatenate hex chunks, and decode the payload:
import pyshark
import binascii
pcap_file = "dns_exfil.pcap"
cap = pyshark.FileCapture(pcap_file, display_filter="dns.flags.response == 0")
hex_payload = ""
for packet in cap:
try:
query_name = packet.dns.qry_name
if "attacker.com" in query_name:
# Extract subdomain prefix
subdomain = query_name.split(".attacker.com")[0]
hex_payload += subdomain
except AttributeError:
continue
# Remove duplicate chunks or non-hex characters if needed
print("Reassembled Hex Payload:", hex_payload)
# Decode hex string to raw bytes
try:
flag = binascii.unhexlify(hex_payload)
print("Decoded Flag:", flag.decode('utf-8', errors='ignore'))
except Exception as e:
print("Decoding error:", e)
Popular DNS Tunneling Tools
- dnscat2: Encrypted command-and-control channel over DNS TXT/MX records.
- iodine: Tunnel IPv4 traffic through a DNS server.
- dns2tcp: Encapsulate TCP connections inside DNS queries.