CobaltStrike逆向学习系列(番外篇)-自定义RDI功能添加

admin 2023年10月25日23:32:51评论18 views字数 2242阅读7分28秒阅读模式

这是[信安成长计划]的第 25 篇文章


0x00 目录
0x01 CS自带方案
0x02 自定义流程实现
0x03 自定义Patch实现

按照之前对RDI功能发布的分析《RDI 任务发布流程分析》,当添加新功能时,只要实现了对应的几个方法便可以完成,但是这样的方法并不便于团队对新功能的增加,功能增加只掌握在了编译的人手中。

0x01 CS自带方案

在CS中有一个类似的方法,可以支持用户对RDI功能的自定义 DllSpawnJob

它是由cna脚本来执行的,通过 bdllspawn 方法来完成,在解析完参数之后会调用 DllSpawn 方法

CobaltStrike逆向学习系列(番外篇)-自定义RDI功能添加

CobaltStrike逆向学习系列(番外篇)-自定义RDI功能添加

最后会调用到 DllSpawnJob 当中,根据已有的名字可以推断出,它可以支持用户自定义几个关键函数的信息

CobaltStrike逆向学习系列(番外篇)-自定义RDI功能添加

然后进行 Spawn

CobaltStrike逆向学习系列(番外篇)-自定义RDI功能添加

就目前来说,有几个比较有局限的地方

首先当前只支持 Spawn 操作,实际对于 Inject 还是有一定需求的,比如注入自身等情况

其次 DllSpawnJob 是继承自 JobSimple ,处理流程与 execute-assembly 是一致的,你所想要追加的内容信息都是通过参数的方式来进行追加的,并不支持进行我们想要的后续 Patch 操作,所有的信息在你编译好 DLL 的时候就需要完成

0x02 自定义流程实现

虽然上面的方案有缺陷,但是我们可以借鉴这样的方式来完成我们自己的处理

我们选择继承 Job ,在实现以后,可以更方便使用 Spawn 和 Inject 两种逻辑,接着实现 abstract 方法, 并且其中的信息通过外部传参获得

CobaltStrike逆向学习系列(番外篇)-自定义RDI功能添加

以 Inject 为例,添加一个 bjobinject 方法,为了能够为上面的几个方法提供内容,先获取这些关键信息,同时因为是注入的关系,也需要有 PID

CobaltStrike逆向学习系列(番外篇)-自定义RDI功能添加

到这里所需要的最基本参数也就完成了,已经可以在 cna 脚本中来进行调用了,当然为了方便,对于 PipeNameCallbackType 等不太会做变动的内容可以设置默认值,如果传入为空就默认使用

bjobinject(%options['bid'], "desc", "shortdesc", "test", "", 0, 0,%options["pid"]);

同理来实现 Spawn 操作时,直接在 new 完以后调用 Spawn 就可以了

0x03 自定义Patch实现

然后就是增加 Patch 操作了,在 CS 中 Patch 的操作还是非常多的

根据 Job 的处理流程可以发现有一个地方能够让我们进行操作,我们可以自己来实现 fix 方法,然后再通过参数来达到控制任务执行流程的目的

CobaltStrike逆向学习系列(番外篇)-自定义RDI功能添加

再这里可以有很多种处理方案,刚开始想偷懒,想在外部直接传入 Python 脚本,内部来执行并替换调返回

但是后来想了想,这样做会带来的风险将直线上升,除非你愿意每次使用前,都看一眼所有的 Python 代码有没有恶意操作

CobaltStrike逆向学习系列(番外篇)-自定义RDI功能添加

为了安全起见,只能是自己来实现了,所以这里也就只支持简单的 Patch 操作(后来发现,再加上CS自带的一些辅助函数,可操作性还是蛮大的)

因为 Patch 主要就需要一个原始字符串和一个新字符串,所以只要一个 Key-Value 格式的数据就足以处理了,将文件中的 Key 值替换为 Value 值

偷懒,直接使用 Java 的 Properties 来完成

依旧通过 cna 脚本将文件名传入,然后我们来获取进行读取

CobaltStrike逆向学习系列(番外篇)-自定义RDI功能添加

接下来就需要讨论参数该如何获得了,因为所有的参数都是从 cna 脚本当中传入的,而我们并不知道调用者会传入多少个参数进来,所以最好的方案就是拿到一个数组,然后传入我们自己的方法里,在 fix 中进行获取,并和文件中所需要的进行匹配

对于 cna 参数的处理就非常简单了,如果一直能获取到参数那就一直取,最后将整个数组都传回来即可

CobaltStrike逆向学习系列(番外篇)-自定义RDI功能添加

对于文件中的信息匹配的话,可能有两种情况,一种是纯字符串的替换,另一种是需要根据实际传入的参数来进行处理

对于第一种就没有什么操作了,直接写就可以了

AAAAAAAAA=balabala

对于第二种需要约定一个方案,以 $arg[x] 为例,如有有就说明想要从参数中来获取

AAAAAAAAA=$arg[0]

然后我们在遍历 Key 的时候,判断一下对应的 Value 是不是包含了这样的字符,如果存在的话,就说明需要进行对应的替换

CobaltStrike逆向学习系列(番外篇)-自定义RDI功能添加

这样就完成了对 DLL 的 Patch 处理操作

但是有个问题,这样岂不是只能直接替换明文在文件中了,刚开始我还在想该怎么去处理这样的问题,后来发现 cna 脚本有一些自带的处理方法能够便于我们进行一些其他的操作,比如 base64gzip 等等

CobaltStrike逆向学习系列(番外篇)-自定义RDI功能添加

虽然不多,但是也足够我们去做一些基本的处理了,这样我们就可以直接在 cna 脚本中来使用了

bjobinject(%options['bid'], "desc", "shortdesc", "test", "", 0, 0,%options["pid"], "config.prop", %options["arg1"]);bjobinject(%options['bid'], "desc", "shortdesc", "test", "", 0, 0,%options["pid"], "config.prop", %options["arg0"], %options["arg1"],base64_encode(%options["arg2"]));

如果还想有其他的一些操作,去添加对应的方法,然后在 cna 脚本中直接调用就好了

-----文章到此结束,欢迎继续探讨-----


往 期 文 章


1. RDI 任务发布流程分析

2. RDI 任务执行流程分析

更多文章 戳此查看


原文始发于微信公众号(信安成长计划):CobaltStrike逆向学习系列(番外篇)-自定义RDI功能添加

  • 左青龙
  • 微信扫一扫
  • weinxin
  • 右白虎
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2023年10月25日23:32:51
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                   CobaltStrike逆向学习系列(番外篇)-自定义RDI功能添加https://cn-sec.com/archives/2143527.html

发表评论

匿名网友 填写信息