| name | analyzing-network-covert-channels-in-malware |
| description | Detect and analyze covert communication channels used by malware including DNS tunneling, ICMP exfiltration, steganographic HTTP, and protocol abuse for C2 and data exfiltration. |
| domain | cybersecurity |
| subdomain | malware-analysis |
| tags | ["covert-channels","dns-tunneling","icmp-exfiltration","malware-analysis","network-forensics","c2-detection","data-exfiltration"] |
| version | 1.0 |
| author | mahipal |
| license | Apache-2.0 |
| d3fend_techniques | ["File Metadata Consistency Validation","Certificate Analysis","Application Protocol Command Analysis","Content Format Conversion","File Content Analysis"] |
| nist_csf | ["DE.AE-02","RS.AN-03","ID.RA-01","DE.CM-01"] |
Analyzing Network Covert Channels in Malware
Overview
Malware uses covert channels to disguise C2 communication and data exfiltration within legitimate-looking network traffic. DNS tunneling encodes data in DNS queries and responses (used by tools like iodine, dnscat2, and malware families like FrameworkPOS). ICMP tunneling hides data in echo request/reply payloads (icmpsh, ptunnel). HTTP covert channels embed C2 data in headers, cookies, or steganographic images. Protocol abuse exploits allowed protocols to bypass firewalls. DNS tunneling detection achieves 99%+ recall with modern ML-based approaches, though low-throughput exfiltration remains challenging. Palo Alto Unit42 tracked three major DNS tunneling campaigns (TrkCdn, SecShow, Savvy Seahorse) through 2024, showing the technique's continued prevalence.
When to Use
- When investigating security incidents that require analyzing network covert channels in malware
- When building detection rules or threat hunting queries for this domain
- When SOC analysts need structured procedures for this analysis type
- When validating security monitoring coverage for related attack techniques
Prerequisites
- Python 3.9+ with
scapy, dpkt, dnslib
- Wireshark/tshark for PCAP analysis
- Zeek (formerly Bro) for network monitoring
- DNS query logging infrastructure
- Understanding of DNS, ICMP, HTTP protocols at packet level
Workflow
Step 1: DNS Tunneling Detection
"""Detect DNS tunneling and covert channels in network traffic."""
import sys
import json
import math
from collections import Counter, defaultdict
try:
from scapy.all import rdpcap, DNS, DNSQR, DNSRR, IP, ICMP
except ImportError:
print("pip install scapy")
sys.exit(1)
def entropy(data):
if not data:
freq = Counter(data)
length = (data)
-((c/length) * math.log2(c/length) c freq.values())
():
packets = rdpcap(pcap_path)
domain_stats = defaultdict(: {
: , : , : [],
: Counter(), : (),
})
pkt packets:
pkt.haslayer(DNS) pkt.haslayer(DNSQR):
qname = pkt[DNSQR].qname.decode(, errors=).rstrip()
qtype = pkt[DNSQR].qtype
parts = qname.split()
(parts) >= :
base_domain = .join(parts[-:])
subdomain = .join(parts[:-])
stats = domain_stats[base_domain]
stats[] +=
stats[] += (qname)
stats[].append((subdomain))
stats[][qtype] +=
stats[].add(subdomain)
suspicious = []
domain, stats domain_stats.items():
stats[] < :
avg_subdomain_len = ((stats[]) /
(stats[]))
unique_ratio = (stats[]) / stats[]
all_subdomains = .join(stats[])
sub_entropy = entropy(all_subdomains)
score =
reasons = []
avg_subdomain_len > :
score +=
reasons.append()
unique_ratio > :
score +=
reasons.append()
sub_entropy > :
score +=
reasons.append()
stats[].get(, ) > :
score +=
reasons.append()
score >= :
suspicious.append({
: domain,
: score,
: stats[],
: (avg_subdomain_len, ),
: (stats[]),
: (sub_entropy, ),
: reasons,
})
(suspicious, key= x: -x[])
():
packets = rdpcap(pcap_path)
icmp_stats = defaultdict(: {: , : [], : []})
pkt packets:
pkt.haslayer(ICMP) pkt.haslayer(IP):
src = pkt[IP].src
dst = pkt[IP].dst
key =
payload = (pkt[ICMP].payload)
icmp_stats[key][] +=
icmp_stats[key][].append((payload))
(payload) > :
icmp_stats[key][].append(payload[:])
suspicious = []
flow, stats icmp_stats.items():
stats[] < :
avg_size = (stats[]) / (stats[])
avg_size > stats[] > :
suspicious.append({
: flow,
: stats[],
: (avg_size, ),
: ,
})
suspicious
__name__ == :
(sys.argv) < :
()
sys.exit()
()
dns_results = analyze_dns_tunneling(sys.argv[])
r dns_results:
()
reason r[]:
()
()
icmp_results = analyze_icmp_tunneling(sys.argv[])
r icmp_results:
()