CVE-2024-26229 BOF:Windows CSC驱动本地提权漏洞原理与红队实战利用
1. 项目概述
最近在整理一些内部红队工具库时,又翻到了这个挺有意思的玩意儿——CVE-2024-26229-BOF。这是一个将CVE-2024-26229漏洞利用代码封装成Beacon Object File(BOF)格式的项目。简单来说,它就是一个可以直接在支持BOF的命令与控制(C2)框架(比如Cobalt Strike、Sliver、Havoc等)中运行的本地提权模块。其核心是利用Windows CSC(客户端缓存)驱动中的一个漏洞,通过直接内核对象操作(DKOM)窃取SYSTEM进程的令牌,从而让当前进程获得SYSTEM权限。对于做内网渗透测试和红队评估的兄弟来说,这种“轻量化”、“无文件落地”的提权工具,在特定场景下往往能起到奇效。今天我就结合自己的实操经验,把这个项目的原理、用法、坑点以及如何适配不同环境,掰开揉碎了跟大家聊聊。
2. 漏洞原理与利用链深度解析
2.1 CVE-2024-26229漏洞本质
这个漏洞的根源在于Windows CSC驱动(csc.sys)对某个特定IOCTL(输入输出控制码)的处理存在缺陷。CSC驱动负责“脱机文件”功能,也就是我们常说的“脱机文件”或“客户端缓存”。漏洞点在于驱动在处理IOCTL 0x001401a3(对应CSC_DEV_FCB_XXX_CONTROL_FILE)时,对用户传入的输入缓冲区指针缺乏充分的验证。
攻击者可以通过NtCreateFile打开一个指向CSC驱动的特殊路径(\Device\Mup\;Csc\.\.)来获取一个驱动句柄。然后,通过这个句柄发送精心构造的IOCTL。关键在于,构造的输入缓冲区可以指向内核空间的一个特定偏移地址——当前线程的KTHREAD结构体中的PreviousMode字段之前的一个位置。由于缺乏验证,驱动会向这个地址写入数据,从而意外地修改了PreviousMode字段。
PreviousMode这个字段至关重要,它告诉内核当前的操作是来自用户模式(UserMode)还是内核模式(KernelMode)。许多内核API(如NtReadVirtualMemory、NtWriteVirtualMemory)会根据这个标志来决定是否对用户提供的指针进行严格的探针(probe)和边界检查。通过这个漏洞,我们可以将PreviousMode从UserMode(1)覆写为KernelMode(0)。
注意:这里有一个精妙的偏移计算。代码中指向的是
KTHREAD->PreviousMode - 0x18。这是因为驱动写入操作可能有一定的结构或对齐要求,直接指向PreviousMode字段本身可能无法成功触发内存破坏,需要找到一个能通过驱动检查且最终能影响到目标字段的相邻可写地址。这通常是通过逆向分析驱动代码确定的。
2.2 DKOM令牌窃取技术
一旦PreviousMode被设置为KernelMode,当前进程就获得了一种“伪内核”能力。最直接的利用方式就是调用NtWriteVirtualMemory这类函数,向内核地址空间任意写入。这个BOF项目采用的策略是经典的DKOM令牌窃取。
每个进程在Windows内核中都有一个EPROCESS结构体,其中有一个Token成员,指向一个_TOKEN结构体,它代表了该进程的安全上下文和权限。SYSTEM进程(PID 4)的令牌拥有最高权限。
利用步骤如下:
- 定位内核对象:首先需要在内核内存中找到当前进程的
EPROCESS和SYSTEM进程的EPROCESS。这通常通过遍历进程活动链表或利用一些未导出的内核函数(如PsLookupProcessByProcessId)的地址来实现。在这个BOF中,它可能通过固定的偏移或特定的内存扫描模式来定位。 - 覆写令牌:使用获得内核写入能力的
NtWriteVirtualMemory,将SYSTEM进程EPROCESS中的Token值,复制到当前进程EPROCESS的Token位置。 - 权限生效:完成覆写后,当前进程的安全令牌就变成了SYSTEM令牌,立刻拥有系统最高权限。
这种方法的优势是“干净”,它不创建新的进程、不注入Shellcode到其他进程(除非你后续主动操作),只是修改了当前进程内核数据结构中的一个指针。
2.3 BOF格式的优势与局限
Beacon Object File是一种特殊的COFF(通用对象文件格式)文件,它可以直接被C2框架在内存中加载和执行,无需在磁盘上生成可执行文件(EXE/DLL)。这带来了几个好处:
- 无文件落地:减少了被终端检测与响应(EDR)基于文件扫描检测的风险。
- 内存执行:所有代码逻辑在Beacon进程内存空间内完成,行为更贴近合法进程活动。
- 即插即用:可以很方便地集成到现有的C2框架中,作为一条命令调用。
但BOF也有其局限性:
- 依赖框架:必须在支持BOF API的C2框架中运行。
- 功能受限:BOF运行在RDI(反射式DLL注入)类似的上下文中,不能直接调用某些需要特定初始化的Windows API或C运行时库函数,通常需要借助框架提供的
Beacon API(如BeaconPrintf输出、BeaconDataExtract解析参数)或使用动态函数解析(DFR)。 - 单次执行:BOF代码执行完毕后,其占用的内存通常会被释放,不适合需要持久驻留的任务。
这个CVE-2024-26229-BOF项目就利用了DFR技术来解析CreateProcessA这样的API,使其能在BOF环境中正常使用。
3. 环境准备与编译实操
3.1 目标系统与依赖检查
这个漏洞有特定的适用范围,不是在任何Windows电脑上都能成功。
- 操作系统版本:主要影响Windows 10 19041至19045版本,以及Windows Server 2019(17763)。其他版本的内核结构体偏移可能不同。
- 补丁状态:该漏洞已在2024年4月的微软月度安全更新中修复。因此,目标系统必须未安装2024年4月及之后的累积安全更新。
- CSC服务状态:漏洞利用需要CSC驱动处于运行状态。在默认的Windows 10工作站上,该服务通常是启用的。但在服务器系统上,可能默认禁用。
- 检查命令:
sc query csc - 查看注册表:
HKLM\SYSTEM\CurrentControlSet\Services\CSC,Start值需要为1(自动)或2(自动(延迟启动))。
- 检查命令:
在实战中,第一步永远是信息收集。通过systeminfo、wmic qfe list查看补丁,通过sc query确认服务状态,可以快速判断目标是否可能易受攻击。
3.2 编译工具链与过程
项目源码是C语言,需要编译成.o(对象文件)供C2框架加载。编译环境推荐使用mingw-w64。
- 安装编译环境(以Kali Linux或Ubuntu为例):
sudo apt update sudo apt install mingw-w64 -y - 获取源码和头文件:
- 从GitHub克隆项目或直接下载
cve-2024-26229.c和beacon.h。beacon.h是关键,它定义了BOF与C2框架交互的API。不同C2框架(Cobalt Strike, Sliver, Havoc)的beacon.h可能有细微差别,务必使用与你C2框架匹配的版本。通常框架的安装目录或开发工具包中会提供。
- 从GitHub克隆项目或直接下载
- 执行编译:
这个命令会生成一个64位的对象文件x86_64-w64-mingw32-gcc -c -o cve-2024-26229.x64.o cve-2024-26229.ccve-2024-26229.x64.o。-c参数表示只编译不链接,因为BOF是对象文件,最终的链接由C2框架在内存中完成。
实操心得:编译时如果遇到
beacon.h找不到或者函数未定义的错误,大概率是头文件不匹配。确保你的beacon.h来自你正在使用的C2框架。有时直接使用项目自带的头文件可能不行,需要替换为框架官方提供的。
3.3 内核偏移量的确认与调整
这是该利用工具最需要关注的地方。源码中硬编码了两个关键偏移:
#define OFFSET_EPROCESS_TOKEN 0x4B8 #define OFFSET_KTHREAD_PREVIOUS_MODE 0x232这两个偏移量(EPROCESS.Token和KTHREAD.PreviousMode)是特定于Windows内核版本(构建号)的。作者给出的偏移适用于Win10 19041-19045和Server 2019 17763。
如果你的目标系统是其他版本(比如Win10 1809、21H2等),直接使用会导致蓝屏(BSOD),因为写错了内存位置。
如何获取正确偏移?
- 离线查询:如果你有目标系统版本的内核调试符号(
ntoskrnl.pdb),可以在WinDbg中使用命令:
查看输出中dt nt!_EPROCESS Token dt nt!_KTHREAD PreviousModeToken和PreviousMode字段相对于结构体起始地址的偏移(+0x???部分)。 - 在线参考:一些开源项目(如
Sysinternals的WinObj原理、或ReactOS源码)以及安全社区的漏洞利用代码中,经常会整理不同版本的内核偏移。可以多方比对。 - 动态探测(高风险):在高度可控的测试环境中,可以编写一个小型测试程序,尝试读取自身进程的
_EPROCESS地址(例如通过NtQuerySystemInformation的特定信息类),然后计算字段偏移。但这需要深厚的底层知识,且极易导致系统不稳定。
修改源码:一旦确定了新偏移,需要修改cve-2024-26229.c文件开头的#define值,然后重新编译。
4. 在C2框架中的集成与使用
4.1 Cobalt Strike集成与调用
对于Cobalt Strike,集成BOF非常简单。
- 放置文件:将编译好的
cve-2024-26229.x64.o文件放入Cobalt Strike客户端的BOF目录下(例如~/cobaltstrike/BOF/)。 - 通过Aggressor Script调用:你可以编写一个
.cna脚本方便调用,或者直接在Beacon控制台使用execute-assembly(对于.NET工具)或inline-execute(对于BOF)的变体。更常见的是使用bof命令。- 直接使用
bof命令(需要提前将.o文件上传到目标):beacon> upload /path/to/cve-2024-26229.x64.o beacon> bof cve-2024-26229.x64.o --path C:\Windows\System32\cmd.exe --args "/c whoami > C:\temp\out.txt" - 或者,在Aggressor Script中封装一个命令:
然后在Beacon中运行alias cve2024 { local('$path $args $bof_data'); $path = "C:\\Windows\\System32\\cmd.exe"; $args = "/c whoami"; // 按照BOF期望的格式打包参数:两个C字符串 $bof_data = bof_pack($path . "\x00" . $args . "\x00"); btask($1, "Executing CVE-2024-26229 BOF..."); // 假设.o文件已位于团队的BOF目录,并被同步到Beacon beacon_inline_execute($1, "cve-2024-26229.x64.o", $bof_data, "go"); }cve2024。
- 直接使用
4.2 其他框架(Sliver/Havoc)集成示例
Sliver框架对BOF的支持也很友好。通常你需要将.o文件放在服务器的~/sliver-client/bofs/目录下,或者通过generate命令链使用。
- 使用
bof命令:
Sliver的sliver > use [beacon-id] sliver (BEACON) > bof cve-2024-26229.x64.o --path C:\loader.exe --args "--local-shellcode"bof命令会自动处理参数传递和内存执行。
Havoc框架同样支持BOF。你需要将编译好的.o文件放入Havoc团队的data/目录下的相应位置,然后在Demon控制台使用bof或inline-execute命令。
Demon> inline-execute cve-2024-26229.x64.o --path C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe --args "-ep bypass -c Get-Process"注意事项:不同框架的BOF加载器和API实现可能有细微差异。务必查阅你所使用框架的官方文档,了解其BOF支持的具体语法、参数打包方式(
BeaconDataExtract的调用约定)以及beacon.h的兼容性。一个在Cobalt Strike上编译的BOF,可能需要在Sliver的mingw环境下用Sliver提供的头文件重新编译才能正常工作。
4.3 参数详解与实战用例
该BOF接受两个参数:
--path:必需。指定在提权成功后,要以SYSTEM权限启动的可执行文件路径。--args:可选。传递给上述可执行文件的命令行参数。
为什么要有--path参数?因为令牌窃取成功后,当前Beacon进程本身已经拥有了SYSTEM令牌。--path参数指定的进程是一个“子进程”,它会继承父进程(即已提权的Beacon)的令牌,从而也以SYSTEM身份运行。这个设计提供了灵活性:
- 启动新代理:可以启动一个新的、以SYSTEM权限运行的Payload(如Meterpreter、Cobalt Strike Beacon的
execute等),建立一个新的高权限会话。 - 执行单次命令:可以启动
cmd.exe或powershell.exe执行一个命令(如添加用户、转储哈希),命令执行后子进程退出。 - 作为持久化跳板:可以启动一个合法的系统服务或计划任务程序。
实战用例:
- 直接获取SYSTEM命令行:
运行后,会弹出一个具有SYSTEM权限的cve-2024-26229 --path C:\Windows\System32\cmd.execmd.exe窗口(如果会话有图形界面)。在无界面的C2会话中,这通常用于执行后续命令。 - 执行PowerShell命令并获取输出:
这条命令会以SYSTEM权限运行PowerShell,执行cve-2024-26229 --path C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe --args "-ep bypass -c \"whoami; hostname\" > C:\Temp\result.txt"whoami和hostname,并将结果输出到文件。之后你可以用Beacon的cat或download命令读取结果。 - 注入到稳定进程(更隐蔽的方式):通常,我们不会直接让Beacon进程长期保持SYSTEM权限,那样太显眼。更佳实践是: a. 利用此BOF将Beacon提权至SYSTEM。 b. 立即使用
psinject或shinject等命令,将你的Payload Shellcode注入到一个以SYSTEM运行的稳定进程(如lsass.exe,services.exe,svchost.exe)中。 c. 然后让原始的Beacon进程退出或降权。这样,高权限的持久化访问就转移到了一个更不易被怀疑的系统进程中。
5. 操作安全(OPSEC)考量与规避
在红队行动中,利用漏洞不是目的,不被发现才是关键。使用此类工具时必须考虑OPSEC。
5.1 行为特征分析与检测点
- 文件路径访问:利用第一步是
NtCreateFile打开\Device\Mup\;Csc\.\.。这个路径非常罕见,正常的用户态程序几乎不会访问。高级的EDR/ETDR系统如果监控了底层的文件系统调用(例如通过ETW的FileIO事件),可能会将此视为可疑行为。 - 异常的IOCTL调用:向
csc.sys驱动发送0x001401a3这个IOCTL码,是一个极强的指示器。任何非微软官方组件进行此类调用都极其可疑。Sysmon(如果配置了DriverLoad和ProcessAccess事件并关联)或内核回调监控可能捕获此行为。 - 直接内核对象修改(DKOM):修改
EPROCESS.Token是典型的恶意内核内存篡改。具备内核态防护能力的解决方案(如Windows Defender Credential Guard、受保护的进程、某些EDR的内核驱动)可能会检测或阻止此类操作。不过,通过篡改PreviousMode来间接实现写入,绕过了某些用户态钩子,但内核层的内存写操作本身仍可能被监控。 - 进程创建:利用成功后通过
CreateProcessA创建子进程。这是最常见的监控点(Sysmon Event ID 1)。子进程的路径、命令行参数、父进程关系(从可能权限较低的进程突然生出SYSTEM进程)都是分析重点。
5.2 规避建议与战术调整
- 路径与IOCTL的伪装:几乎无法伪装。这两个是漏洞利用的固有特征。因此,这个漏洞利用的核心OPSEC价值在于其“一次性”和“本地性”。它不依赖网络下载、不释放文件到磁盘、不注册服务。攻击窗口短,痕迹相对较少。关键在于快速利用,快速转移。
- 规避进程创建监控:
- 不创建新进程:修改BOF代码,移除或注释掉
CreateProcessA相关的部分。提权成功后,Beacon进程自身已是SYSTEM,可以直接使用execute、run等C2命令执行操作,或者使用psinject注入到已有的SYSTEM进程中。这避免了新的进程创建事件。 - 伪装父进程:如果必须创建进程,可以考虑使用
CreateProcess的CREATE_SUSPENDED标志创建挂起的进程,然后通过进程镂空(Process Hollowing)或模块篡改等技术,将目标映像替换为更合法的系统进程(如svchost.exe),然后再恢复执行。但这会引入更多复杂操作。 - 使用合法的系统工具:子进程路径尽量使用系统目录下的合法工具,如
cmd.exe、powershell.exe、rundll32.exe、regsvr32.exe等。命令行参数也应模仿正常管理行为。
- 不创建新进程:修改BOF代码,移除或注释掉
- 清理与恢复:该BOF在利用完成后会将
PreviousMode恢复为UserMode。这是一个很好的做法,避免了因PreviousMode异常而导致后续进程行为异常(可能触发检测)。确保利用代码的这一部分成功执行。 - 结合环境变量:在决定是否使用此漏洞前,务必做好侦察。确认目标系统版本、补丁、CSC服务状态都符合条件。盲目尝试可能导致蓝屏,造成攻击中断和警报。
6. 常见问题排查与实战心得
6.1 利用失败原因分析
| 现象 | 可能原因 | 排查方法 |
|---|---|---|
| 运行后无任何输出,Beacon无反应或断开。 | 1. 目标系统已打补丁(2024年4月后)。 2. CSC驱动未运行或禁用。 3. 内核偏移量不正确,导致写入错误地址引发蓝屏(BSOD)。 | 1. 检查系统补丁号(wmic qfe get HotFixID)。2. 运行 sc query csc查看服务状态。3. 在测试环境中用WinDbg双机调试确认偏移,或检查系统版本是否在支持列表内。 |
输出类似[+]的前几步成功,但令牌替换失败或进程创建失败。 | 1. 权限不足(需管理员权限运行初始Beacon)。 2. 防病毒或EDR拦截了内核内存写操作或进程创建。 3. --path指定的可执行文件路径不存在或访问被拒绝。 | 1. 确保Beacon是以管理员权限运行的(getuid返回高完整性)。2. 尝试在禁用实时防护的测试环境中运行。 3. 检查路径是否正确,特别是转义字符(如 C:\\Windows\\...)。 |
编译失败,提示beacon.h相关错误。 | 使用的beacon.h头文件与C2框架不兼容。 | 从你所用的C2框架官方安装包或GitHub仓库中获取正确的beacon.h文件替换。 |
| 在C2框架中执行BOF时,参数传递错误。 | 参数打包格式与BOF代码中的BeaconDataExtract不匹配。 | 查看BOF源码,它期望两个C字符串(cstr)。确保在Aggressor Script或框架命令中,参数被打包为两个以空字符结尾的字符串拼接。 |
6.2 进阶技巧与扩展思路
- 自动化偏移获取:硬编码偏移是最大的限制。可以尝试在BOF中集成一个简单的“偏移探测”功能。例如,通过
NtQuerySystemInformation枚举内核模块基址,然后解析ntoskrnl.exe的PE头,寻找特定导出函数(如PsInitialSystemProcess)的地址,再结合一些特征码搜索来动态计算EPROCESS和KTHREAD结构体的字段偏移。这能极大提升工具的通用性,但会显著增加代码复杂度和体积。 - 备用利用路径:CVE-2024-26229的本质是获得了任意内核写原语。除了DKOM令牌窃取,这个原语还可以做很多事情:
- 禁用驱动签名强制(DSE):修改
Ci.dll相关的内核全局变量。 - 清除进程回调:移除EDR注册的进程创建回调,实现进程隐藏。
- 修补内核函数:在内核函数开头打补丁(jmp到自己的代码),实现更底层的钩子绕过。 你可以基于这个BOF的初始利用部分(设置
PreviousMode),编写新的Payload来实现上述功能。
- 禁用驱动签名强制(DSE):修改
- 与其它本地提权漏洞结合:在实战中,一个目标可能打了这个补丁但存在另一个漏洞。维护一个本地提权漏洞工具集是必要的。这个BOF格式轻便,非常适合集成到这样的工具集中。
- 后利用阶段的隐蔽:成功提权到SYSTEM后,应尽快将权限“转移”或“沉淀”。例如,立即转储
lsass.exe的内存获取凭证,或者向一个受信任的、以SYSTEM运行的Windows服务进程(如services.exe)注入一个后门DLL。然后让当前这个刚刚执行了可疑内核操作的Beacon进程安静退出。这样,高权限访问得以维持,而明显的攻击进程已消失。
这个CVE-2024-26229-BOF项目是一个很好的例子,展示了如何将一个复杂的本地提权漏洞,封装成适合红队作战的、即插即用的轻量级工具。理解其背后的原理,远比单纯会使用命令更重要。在实战中,结合精准的情报收集、对目标环境的深入理解以及严格的OPSEC纪律,这类工具才能发挥出最大的价值,帮助你在网络的攻防对抗中,于无声处听惊雷。
