CVE-2023-28252 是一个存在于 clfs.sys(通用日志文件系统驱动程序)中的越界写入漏洞,由 Kaspersky,Mandiant,DBAPPSecurity WeBin Lab 在野发现,成功利用此漏洞能获得 system 权限,发现时其已被用于 Nokoyawa 勒索软件攻击。漏洞信息发布后 360 沙箱云团队第一时间对该漏洞进行了复现与分析,并就此漏洞触发路径和指令在沙箱云检测引擎中增加精确检测规则,帮助用户精确识别该漏洞。
样本信息
MD5:0624FBFA7618628E1EDE80FCC3C36B25
分析环境
- windows 10 版本 10.0.19045.2604
- x64 dbg,windbg,IDA Pro 7.5
样本概述
查看样本信息发现加的有 Themida – Winlicense 壳。
过壳方法:https://github.com/VenTaz/Themidie
样本中存在两种利用方法分别针对 win10 和 win11,一下以 win10 中的利用为例。
漏洞利用分析
clfs 中的结构
base_header:
base_record_header:
CClfsLogFcbPhysical 类与 CClfsBaseFilePersisted 类的部分结构。
typedef struct struct_CClfsLogFcbPhysical{
void* vftable; //offset 0x00 vftable 指针
UCHAR* pLogName; //offset 0x30 存储的是指向日志名称的指针
CClfsBaseFilePersisted,* pCClfsBaseFilePersisted; //offset 0x2a8(windows 11 是 0x2b0) 存储的是指向 CClfsBaseFilePersisted 类的 this 指针
} CClfsLogFcbPhysical,*pCClfsLogFcbPhysical;
typedef struct struct_CClfsBaseFilePersisted{
Heap* pHeap; //offset 0x30 size 0x90,指向 CLFS_CONTROL_RECORD 中的 CLFS_METADATA_BLOCK 数组
CClfsContainer* pContainer; //offset 0x98(windows 11 是 0x1C0) 存储的是指向 CClfsContainer 对象的指针
} CClfsBaseFilePersisted,*pCClfsBaseFilePersisted;
//Heap 的大小为 0x90 bytes
typedef struct struct_Heap{
CLFS_LOG_BLOCK_HEADER *pCLFS_LOG_BLOCK_HEADER; //offset 0x30 存储指向基块的指针
} Heap,*pHeap;
结构参考:
https://github.com/ionescu007/clfs-docs
利用步骤:
1, 获得系统版本,根据系统版本判断是否支持利用,并确定 Token 和 PreviousMode 偏移。
2, 获得一些基础信息。
2.1>当前进程的 EPROCESS 地址,当前线程的 ETHREAD 地址,system 进程的 EPROCESS。
2.2>几个关键函数地址:NtQuerySystemInformation,NtWriteVirtualMemory,ClfsEarlierLsn,ClfsMgmtDeregisterManagedClient,RtlClearBit。
3, 检测当前进程的访问令牌的句柄是否存在于系统句柄列表中。
4, 创建 C:\Users\Public\p_%08d 文件并获得其 _FILE_OBJECT 的地址。
5, 创建基础日志 LOG:C:\Users\Public\MyLog_%08d 并修改其日志文件中的数据,最后为其添加容器。
6, 创建基础日志 LOG:C:\Users\Public\MyLog%d%08d 并修改其日志文件中的数据。
7, 使用匿名管道对内核进行内存布局。
8, 为 LOG:C:\Users\Public\MyLog%d%08d 添加容器,触发漏洞篡改 LOG:C:\Users\Public\MyLog_%08d 日志的 rgContainers[0]。
9, 对 0x5000000 进行内存布局。
10, 打开 LOG:C:\Users\Public\MyLog_%08d 日志,利用漏洞使用 RtlClearBit 函数将当前线程的 PreviousMode 置 0。
11, 替换的当前进程 Token。
11.1>使用 NtWriteVirtualMemory 读取 system 进程的 Token。
11.2>将 system 进程的 Token 写入当前进程的 Token 处。
11.3>还原 LOG:C:\Users\Public\MyLog_%08d 日志的 rgContainers[0]。
11.4>还原当前线程的 PreviousMode。
利用过程
1,通过 HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\UBR 获得系统版本信息判断是否支持漏洞利用,确定 Token 和 PreviousMode 偏移。
Token offset = 0x4b8
PreviousMode offset = 0x232
2,使用 NtQuerySystemInformation 函数的 SystemExtendedHandleInformation 参数泄露当前线程的 EPROCESS,当前线程的 ETHREA,及 system 进程的 EPROCESS 的内核地址。
获得几个关键函数的内核地址,已 ClfsEarlierLsn 为例:
首先获得 clfs.sys 模块在 r0 的基址,然后将 clfs.sys 模块加载到 r3 并获得 ClfsEarlierLsn 函数在 r3 的地址。最终 r0 的模块基址加上 r3 的偏移获得 r0 的函数地址。
获得 clfs.sys 模块的 r0 基址是通过 NtQuerySystemInformation 函数的 SystemModuleInformation 参数实现。
3,使用 NtQuerySystemInformation 函数的 SystemHandleInformation 参数检测当前进程的访问令牌的句柄是否存在于系统句柄列表中。
4,创建 C:\Users\Public\p_%08d 文件并获得其 _FILE_OBJECT 的地址,获得方法是通过的 NtQuerySystemInformation 函数的 SystemExtendedHandleInformation 参数。
5,创建基础日志 LOG:C:\Users\Public\MyLog_%08d 并修改其日志文件中的数据,最后为其添加容器。
创建后修改日志文件基块(base_block)中的一些数据,其中值 0xC1FDF008 是 CLFS_CONTAINER_CONTEXT 结构的标志值。
添加的容器如下,到这里已经可以合理猜测漏洞是通过篡改 rgContainers[0] 进行利用的了,因为只需将 0x1470 篡改为 0x1570 便可将容器指向 offset 0x15E0 (相对基块)处的 fake CLFS_CONTAINER_CONTEXT,而 fake pContainer 便是可以进行内存布局的 0x5000000。
6,创建基础日志 LOG:C:\Users\Public\MyLog%d%08d 并修改其日志文件中的数据。
创建后修改其日志文件中控制块(control_block)和基块(base_block)中的一些数据。
7,使用匿名管道对内核进行内存布局。
创建匿名管道后将 LOG:C:\Users\Public\MyLog_%08d 日志的 base_block + 30 的地址值写入管道。
最终的内存布局。
8,为 LOG:C:\Users\Public\MyLog%d%08d 添加容器,触发漏洞篡改 LOG:C:\Users\Public\MyLog_%08d 日志的 rgContainers[0]。
为 LOG:C:\Users\Public\MyLog%d%08d 添加容器的过程中,由于精心设计了控制块的数据所以出现了以下调用链。
在 CClfsBaseFilePersisted::WriteMetadataBlock 获取 LOG:C:\Users\Public\MyLog%d%08d 正在刷新的元数据块的地址时出现越界访问,由于设计的错误索引使其获得的地址为 LOG:C:\Users\Public\MyLog_%08d 日志的 base_block + 30。
错误的索引导致越界访问,获取数据的地址落在了上步通过匿名管道进行的内存布局处。
最终在以下位置对 LOG:C:\Users\Public\MyLog_%08d 日志的 rgContainers[0] 的高字节进行了增量写入,使其由 14 变为 15。写入位置: base_block + 30 + 369 与 base_block + 398(rgContainers 数组)重叠。
LOG:C:\Users\Public\MyLog_%08d 日志的 CLFS_CONTAINER_CONTEXT 指向的 fake CLFS_CONTAINER_CONTEXT。
9,对 0x5000000 进行内存布局。
10,打开 LOG:C:\Users\Public\MyLog_%08d 日志,利用漏洞使用 RtlClearBit 函数将当前线程的 PreviousMode 置 0。
打开 LOG:C:\Users\Public\MyLog_%08d 日志时会出现以下调用链。
在 CClfsBaseFilePersisted::CheckSecureAccess 中使用了 fake pContainer(0x5000000),并最终调用 RtlClearBit 将当前线程的 PreviousMode 置 0。
11,替换当前进程 Token。
将当前线程的 PreviousMode 置 0 后便可使用 NtWriteVirtualMemory 进行内核地址的任意读写。
最终将当前进程的 Token 替换为 system 进程的 Token。
沙箱云检测
精确检测
基于检测规则的精确漏洞检测,准确识别漏洞编号。
通用检测
基于检测线程 PreviousMode(前模式) 的通用漏洞检测,准确识别 PreviousMode(前模式) 被修改为 KernelMode。
基于检测新进程用户, 用户组, 或完整性等级的通用漏洞检测,准确识别用户, 用户组, 或完整性等级升高。
基于检测进程 Token(令牌) 指针变化的通用漏洞检测,准确识别进程 Token(令牌) 指针被修改。
关于我们
360沙箱云是 360 安全情报中心旗下的在线高级威胁分析平台,对提交的文件、URL,经过静态检测、动态分析等多层次分析的流程,触发揭示漏洞利用、检测逃逸等行为,对检测样本进行恶意定性,弥补使用规则查杀的局限性,通过行为分析发现未知、高级威胁,形成高级威胁鉴定、0day 漏洞捕获、情报输出的解决方案;帮助安全管理员聚焦需关注的安全告警,过安全运营人员的分析后输出有价值的威胁情报,为企业形成专属的威胁情报生产能力,形成威胁管理闭环。解决当前政企用户安全管理困境及专业安全人员匮乏问题,沙箱云为用户提供持续跟踪微软已纰漏,但未公开漏洞利用代码的 1day,以及在野 0day 的能力。
360混天零实验室负责高级威胁自动化检测项目和云沙箱技术研究,专注于通过自动化监测手段高效发现高级威胁攻击;依托于 360 安全大数据,多次发现和监测到在野漏洞利用、高级威胁攻击、大规模网络挂马等危害网络安全的攻击事件,多次率先捕获在野利用 0day 漏洞的网络攻击并获得厂商致谢,在野 0day 漏洞的发现能力处于国内外领先地位,为上亿用户上网安全提供安全能力保障。
发表评论
您还未登录,请先登录。
登录