Skip to content
KitploitKITPLOIT
工具博客
提交
工具博客
提交

黑客、渗透测试和网络安全工具,武装您的安全武器库!

Kitploit 是一个黑客、网络安全和渗透测试工具的目录。发现最新的项目更新,查找漏洞、分析系统、自动化测试并加强你的安全。

··订阅源·联系·隐私·© 2026 Kitploit

工具目录

分类

查看所有分类
Loading categories
WEASEL — 面向红队的DNS隐蔽信道植入工具。 | Kitploit
工具/GitHubGitHub/facebookarchive/weasel
加密/解密工具持久化机制后渗透利用渗透测试命令与控制红队Payload 开发DNS 分析Archived
GitHubfacebookarchive/weasel

WEASEL

面向红队的DNS隐蔽信道植入工具。

查看仓库
731666年前Kitploit 审核通过

最受欢迎

查看全部 →

发现我们社区最常用的工具。

探索所有工具

浏览我们的工具集合

查看所有工具 →
分享

WEASEL:一种隐蔽的DNS信标

WEASEL是一个小型内存植入程序,使用Python 3,无依赖项。信标客户端会向其控制的DNS区域发送少量主机标识信息。WEASEL服务器可以任务化客户端执行预制或任意命令。

WEASEL是一个阶段1有效载荷,旨在难以检测,并在你那些嘈杂的全功能阶段被捕获时用于重新获得访问权限。

状态

  • 已在操作中成功使用并规避了检测。
  • 客户端可以与服务器建立会话并建立双向通信。
  • 服务器拥有完全可用的CLI。
  • 客户端支持服务器可以任务化的多个功能。
  • 经过压缩+混淆后,客户端大小为5.2KB。
  • 自动混淆功能不足,需要手动修复(参见客户端README中的限制)。
  • 服务器不支持多人(同时多个操作员)协同。

示例

具体使用说明请参见客户端的README和服务器的README。

要启动服务器或客户端,直接执行脚本或将其传递给Python解释器。

确保每个C2域名都有一个指向运行server.py的主机IP地址的NS记录。

要求

WEASEL需要Python 3.6+。

客户端是自包含的,仅使用标准库,因此可以在macOS、Linux等系统上运行。

服务器有一些pip依赖项,包含在服务器的requirements.txt中。服务器应在Linux上运行,但也没有禁止其在macOS或其他类Unix系统上运行。

测试 / 开发环境运行

在这种情况下无需混淆和压缩信标。print语句保留。与上述用法一样,确保servers中的域名的NS记录指向server.py的IP地址。

在服务器主机上:

sudo python3 server.py

在受害者主机上(可以与服务器相同):

python3 beacon.py

架构

你不需要理解这些就能使用WEASEL。

信标通过DNS使用AAAA查询和应答进行通信。它不使用TXT记录,因为TXT记录已知被DNS恶意软件和隧道使用。蓝队通常具有对大型TXT查询告警的DNS隧道检测。

客户端不需要root权限即可运行,不使用原始套接字,也不创建畸形DNS数据包。它使用系统和语言提供的常规接口来发起DNS请求。信息本身在记录中进行了编码+加密。

  • 单个A记录(IPv4地址)可包含4字节信息。
  • 单个AAAA记录(IPv6地址)可包含16字节信息。
  • 查询中使用的CNAME记录和主机名每个子域名最多可包含64字节,根据RFC总长度不应超过255字节。然而,SANS DNS检测指南指出,超过52个字符的子域名值得怀疑。出于这个原因,我们将子域名限制为52个字符(可在代码中配置),并尽量使用不超过所需数量的子域名和请求。
  • 一个响应可以包含多个记录,直到UDP数据报的大小限制(65,507字节)。

这个信标旨在保持低速和隐蔽,带宽占用小。它应告知我们它所在的主机,并提供在需要时启动进一步阶段的方法,仅此而已。虽然它支持任意命令,但不应将其用作常规交互式Shell或通信通道。

WEASEL是一个阶段1,你让它持续运行,确保在功能齐全(因此更嘈杂)的阶段被捕获时仍能保持访问。

持久化

WEASEL最初针对高正常运行时间服务器,我们在那里有可靠的立足点/利用向量。规避取证是高优先级。因此,它没有原生的持久化功能。

你可以通过将其执行添加到你喜欢的持久化技术中来实现持久化,这留给读者作为练习 :)

协议与消息格式

客户端请求

一个**请求(来自客户端)**是一个针对类似以下格式名称的单个AAAA查询:

<preamble><data>.<stream>.<session>.domain.tld

前导码为2字节。Preamble[0]是该数据包的序列号。Preamble[1]是该流中的数据包总数。

数据限制为50字节(可配置),包含有效载荷。有效载荷使用自定义字母表进行base32编码。

有效载荷编码

首先,所有'w'字符替换为'-'。

然后,填充字符从'='替换为'w',以符合DNS字符集:[a-z0-9]和[-]。

我们不直接将'='替换为'-',因为填充总是出现在字符串末尾,以'---'结尾的主机名既可疑又违反DNS RFC。这样,当字符串确实有填充时,它会以'www'结尾,这既不太可疑也符合RFC规范。

服务器响应

一个**响应(来自服务器)**由一个或多个AAAA答案组成。

每个AAAA答案是一个16字节的加密有效载荷,使用socket.inet_ntop表示为IPv6地址。DNS响应中的答案不保持其在传输中的顺序,因此它们像客户端请求一样被排序和重组。

传输有效载荷是一个由^字符分隔的数据元素字符串。

传输格式

请求和响应遵循以下格式:

<type>|<data>

会话

会话是长期存在的:客户端在第一次执行信标时发起一个会话,该会话应持续到信标在该客户端上活动的整个时间。请注意,由于信标在内存中且不持久,会话数据存储在该Python进程的内存中。任何信标的新调用都将发起一个新会话。

发起会话时,客户端会构建一个包含唯一标识非数据前导码的消息(以向服务器表明这是一个新会话):该前导码是32字节的Diffie-Hellman公钥与16字节随机AES IV的拼接。

服务器收到此消息后,回复自己的32字节公钥。此时,客户端和服务器已建立共享的会话密钥,该密钥将在该会话的生命周期内用于使用AES-128-CTR模式加密数据有效载荷。Diffie-Hellman临时交换确保每个客户端-服务器连接使用唯一的会话密钥,并具有前向保密性。

加密的弱点

加密是故意设计得弱小,原因如下:

  • 我们模拟真实攻击者,他们通常对构建健壮加密系统知之甚少,并且喜欢自己动手。
  • 信标的带宽尽可能低,这意味着我们的DHE交换必须保持非常小。
  • 非归因性很重要,我们不验证服务器。
  • 对于响应者来说,如果我们使用他们无法破解的最先进加密技术,那就没意思了。

以下是加密方案的一些已知问题:

  1. Diffie-Hellman模数p是RFC 3526 Group 5截断为前32字节。这不仅将公钥和私钥限制为32字节,而且Group 5已经被弃用且不推荐使用。我把这个糟糕的决定称为"Group 1"。
  2. 我们使用random.randint()作为指数a,而不是CSPRNG。
  3. 我们使用少量来自os.urandom()的数据来生成会话ID和流ID,而不是UUID,这意味着碰撞的可能性很大。我们通过重试直到获得一个未被使用的ID来解决这个问题。
  4. AES-CTR密码对每个流都使用相同的IV(与会话密钥一样长期存在)重新初始化。这意味着不同流中相同位置处的相同明文将产生相同的密文。
  5. 在AES-CTR中,IV正确地被称为nonce,但在我们的实现中,我们没有使用"一次性的数",所以这样称呼它有点不礼貌。

流

客户端和服务器之间发送的每条消息都必须被分组为最大50字节的数据包,以便保持在常见DNS隐蔽通道检测的52字节限制以下。特定消息的所有数据包都属于同一个流。消息 == 流。

流由一个2字节的随机十六进制数字标识。回顾一下客户端请求格式: <preamble><data>.<stream>.<session>.domain.tld

流中每个数据包的2字节前导码包含序列号和该流中数据包总数。这使得服务器能够知道所有数据包是否已到达。

由于这是通过UDP进行的DNS,而UDP不保证数据报到达的顺序。这就是为什么WEASEL必须处理来自许多信标的多个流的排序、重组和跟踪。

每个流重新初始化全局共享的AES-128-CTR密码以加密/解密有效载荷。

有效载荷只能在流完成(所有数据包已到达)后才能被解密。如果不是因为base32,即使缺少数据包,我们也可以解密我们所拥有的消息部分(因为AES-CTR是流密码),但我们无法base32解码部分流。不过,由于DNS客户端的特性,请求会被多次发出(通常2或4次),直到收到响应,因此我们有很好的概率收到流中的所有数据包,因为每个数据包至少会被客户端发送两次。如果我们确实丢失了数据包或流,那也没什么大不了的,信标稍后会再次签到,那时运气可能会更好。

加入WEASEL社区

有关如何提供帮助,请参见CONTRIBUTING文件。

许可证

WEASEL采用MIT许可证,详见LICENSE文件。

下载工具
类型含义(发送者)别名数据
0已确认ACK随机十六进制
1签到(客户端)PING随机十六进制
2终止自身(服务器),正在终止自身(客户端)FIN
3初始化消息(客户端)SYNversion|hostname|kernel
4重新连接(服务器)RST
5设置回调间隔(服务器)秒数
6获取网络接口数据eth0 1.2.3.4/24\neth1 fe80:::/64\n...
8评估最多666字节的任意Python3代码(服务器),返回输出前400字节(客户端)EVALpython3单行脚本
9执行最多666字节的任意命令(服务器),返回输出前400字节(客户端)EXECbash命令