一个 Python 框架,用于构建和利用接口在框架之间传输数据,特别侧重于作为命令与控制(C2)框架的扩展。
目前,这仅作为 Cobalt Strike 的 External C2 规范的实现,如此规范文档所述,但随项目成熟可能会有变化。
特别感谢 xychix。没有他们的宝贵贡献,这个项目根本不可能实现。基本上,本项目是对 Outflank 的 External C2 项目 的重建和扩展。
本项目由以下主要部分组成:
构建器读取配置文件,并根据配置的选项通过替换骨架中的标记来生成构建。
构建器可通过 build_files.py 使用。示例构建器配置在 sample_builder_config.config.sample 中提供。
骨架是代码的不同“骨架”,构建器将动态填充这些骨架以生成完全可用的构建。骨架中包含标记,构建器会用可用值替换这些标记。共有三种不同类型的骨架:
标记可以放置在骨架内的任何文件中,这些标记将被替换为构建器配置中指定的值。在最佳实践中,标记不应直接用于写入变量,而应仅用于设置值。如果需要重复使用标记的值,应选择将值存储在变量中并通过变量引用,而不是重复使用同一个标记。
标记格式为:```[var:::标识符]```
字符串将直接包裹在单引号中写入骨架,数字则原样写入。
如果配置中的字符串被双引号包裹,则该字符串将直接以双引号包裹写入文件,并去除包裹的单引号。
这种关系可以演示如下:
#################
# 骨架代码 #
#################
# 骨架包含以下代码行:
foo = ```[var:::bar]```
##############
# 最终结果 #
##############
# 在配置中存储为:
# foo = bar
# 写入为:
foo = 'bar'
# 在配置中存储为:
# foo = "bar"
# 写入为:
foo = "bar"
# 在配置中存储为:
# foo = 2
# 写入为:
foo = 2
# 在配置中存储为:
# foo = "2"
# 写入为:
foo = "2"
框架是基础应用程序,它决定了传输模块和编码器所使用的数据以及这些数据的使用方式。一个特定框架实际做什么并不重要,只要存在导入并使用编码器和传输模块的逻辑即可。框架的大部分关键部分(主要是客户端逻辑)将以骨架形式存储,并且与服务器部分的接口将作为基础框架对象存储。
通常,一个框架包含服务器和客户端,并利用编码器和传输模块在两者之间中继数据。
构建框架时需要考虑几个基本点:
框架负责确保传输模块可以使用编码器。框架使用客户端-服务器关系,则应适当组织它们。客户端交互,因此如果你想在客户端上实现可重新配置,它必须能够在运行时无需直接交互的情况下完成。服务器的骨架,因为最终用户将直接与框架的服务器交互。相反,应选择从配置中读取选项,并为最终用户提供在运行时修改选项(如阻塞定时器或详细程度)的能力。框架骨架将由构建器处理,遍历其中的每个文件,因此如果某个参数需要在构建时可配置,可以轻松实现。框架的服务器应该能够通过一个公共的框架管理器进行接口交互。服务器是负责在客户端和C2服务器之间进行通信的应用程序。服务器逻辑主要是静态的。对于cobalt_strike框架,其服务器的逻辑(规范中称为“第三方客户端控制器”)如下所示:
编码器模块对stager进行编码传输模块传输stager传输模块从客户端接收元数据响应编码器模块解码元数据传输模块将新任务中继到客户端传输模块从客户端接收响应编码器模块解码响应服务器应支持处理多个客户端(尚未实现),并由框架管理器进行接口交互。
客户端本质上是运行在端点上的有效载荷。对于cobalt_strike框架,客户端的逻辑主要是静态的,如下所示:
传输模块所需的任何准备工作传输模块将beacon的元数据中继到C2服务器传输模块以获取新任务传输模块中继beacon的响应客户端使用指定的编码器和传输模块在自身与其对应的服务器之间中继数据。
编码器接收数据,然后修改数据以准备通过传输模块发送,或者解码通过传输模块接收的数据,使其恢复为原始形式,以便由使用它的框架组件解释。
编码器应期望直接被传输模块接口调用,并以框架和组件无关的方式处理数据。
传输模块的角色是通过通信通道发送和接收数据,并与编码器接口交互,确保数据转换为所需的任何格式。传输模块应期望从框架组件或通过通信通道接收数据,并具有通过通信通道中继数据的能力。传输模块负责调用编码器以根据需要编码或解码数据。
传输模块应期望直接被框架组件接口调用,并以框架和组件无关的方式处理数据。
首先,确定你想使用的传输模块和编码模块。在以下示例中,我们将使用 transport_imgur 和 encoder_lsbjpg。
接下来,根据你的需求创建一个 builder_config.config 文件,参考提供的示例配置和模板来了解如何操作。
使用 build_files.py 生成构建。例如,要使用 encoder_lsbjpg 和 transport_imgur 为 Cobalt Strike 生成构建,并以详细模式输出到 builds 目录,可以使用以下命令:
python build_files.py -b builds -f cobalt_strike -c sample_builder_config.config.sample -e encoder_lsbjpg -t transport_imgur -v
在运行服务器的机器上,执行:
python server.py
如需更详细的输出,可以运行:
python server.py -v
如需更详细的输出以及有助于调试的额外输出,可以运行:
python server.py -d
接下来,在目标端点上执行客户端。
如果一切正常,Cobalt Strike 控制台中将注册一个新的 beacon,你可以与之交互。
你为什么写这个?: Cobalt Strike 规范的已发布实现并不多,而已发布的实现中,要么使用的不是我熟悉的语言,要么不具备我寻求的模块化和抽象性。
为什么用 Python 2?: 我比较懒,而且用它实现新的传输和编码通道很容易。
你的代码很烂: 这不是一个问题。
我可以提交新的传输和/或编码器模块吗?: 当然可以!请提交拉取请求,我很乐意审查。
如何将客户端编译为可分发的可执行文件?:
我已在 Kali 中成功测试过。要重现我的环境,只需确保你已安装 veil-evasion 并完成了其设置。它应该已安装一个包含所需所有依赖项的 Wine 环境并带有 Python。你可能还需要在此环境中安装 pefile 模块。
然后,进入你要生成可执行文件的客户端目录,并运行:
chmod +x compile_dll.sh
./compile_dll.sh
wine "C:\\Python27\\python.exe" /usr/share/veil/pyinstaller/pyinstaller.py -F -r c2file.dll -w --key "ayyyyyyylmao" client.py
将 key 的值替换为你想要的任何值。你将在 dist/ 目录中看到客户端可执行文件。如果你想生成一个提供控制台以便调试的可执行文件,请使用以下命令编译:wine "C:\\Python27\\python.exe" /usr/share/veil/pyinstaller/pyinstaller.py -F -r c2file.dll -c client.py