做个记录,文章写的不好,建议直接看参考链接里的文章
参考文章:
https://mp.weixin.qq.com/s/Qlst6CX_z1A698Tvvx-bIQ
https://www.anquanke.com/post/id/288808
https://github.com/fortra/CVE-2023-28252
https://www.zscaler.com/blogs/security-research/technical-analysis-windows-clfs-zero-day-vulnerability-cve-2022-37969-part2-exploit-analysis
https://bbs.kanxue.com/thread-278241.htm
样本
MD5:0624FBFA7618628E1EDE80FCC3C36B25
样本有 Themida – Winlicense 壳
过壳方法:https://github.com/VenTaz/Themidie
##利用步骤
0, 清空对应的工作目录
1, 通过HKEY_LOCAL_MACHINE\Software\Microsoft\Windows NT\CurrentVersion获得系统版本,根据系统版本判断是否支持利用,并确定 Token 和 PreviousMode 偏移。
2, 获得一些基础信息。
获取系统版本
之后获取对应系统及当前进程的内核偏移,并初始化一系列内存。
通过动态地址获取的方式分别从clfs.sys/ntoskrnl.exe中获取函数ClfsEarlierLsn,ClfsMgmtDeregisterManagedClient,RtlClearBit/ PoFxProcessorNotification,SeSetAccessStateGenericMapping
3, 检测当前进程的访问令牌的句柄是否存在于系统句柄列表中。
之后在0x5000000位置分配0x1000000长度的内存
4, 创建 C:\Users\Public\p_%08d 文件并获得其 _FILE_OBJECT 的地址。
之后获取NtFsControlFile函数地址,并通过ZwQuerySystimeInformation获取PipeAttributer的内核对象地址,在0xFFFFFFFF上分配长度为4096的内存,并以此部署system Process token。这个位置使用于辅助ClfsEarlierLsn/SeSetAccessStateGenericMapping进行最终的内存写入。
与CVE-2022-37969相似
5, 创建基础日志 LOG:C:\Users\Public\MyLog_%08d 并修改其日志文件中的数据
通过CreateLogFile创建第一个log file
修改文件中的位置
最后调用AddLogContainer增加一个log container,需要注意对应的trigger clfs base block 内核地址para_clfsKerneladdress通过ZwQuerySystemInforation搜索的方式获取,其原理是通过搜索0x7a00大小标志位clfs的pool,类似包括pipeAttribute的内核地址也是通过该方式获取。
6, 后再次创建10个log file,这里称之为spray clfs[i] 并修改其日志文件中的数据
Spray clfs[i]生成之后,在这个位置并没有调用AddLogContainer
7, 使用匿名管道对内核进行内存布局。
首先trigger clfs 对应的内核base block内核地址+0x30的位置被循环赋值到一个数组中,然后两次调用函数fun_pipeSpray,对应的参数分别为0x5000及0x4000。
pipeSpray为一个pipe的spray,其根据参数传入的数量生成指定数量对数的pipe(read/write),第一次pipeSpray调用传入0x5000,因此生成了0x5000对pipe(read/write),这里统一将这0x5000对pipe称之为pipeA,第二次的0x4000对称之为pipeB。
遍历0x5000对pipeA,并调用其writepipe写入包含trigger clfs base block + 0x30的数组
遍历结束,从pipeA(0x2000偏移),第174对pipe开始释放,一共释放0x667对pipe对。
释放结束后,紧接着通过前面的spray[i] clfs循环调用CreateLogFiles,用CreateLogFiles调用中某一处内存对象占据前面pipA中释放的pipe对。
CreateLogFiles循环占位结束后,遍历0x4000对pipB,并调用其writepipe写入前面数组。
8, 为 LOG:C:\Users\Public\MyLog%d%08d 添加容器,触发漏洞篡改 LOG:C:\Users\Public\MyLog_%08d 日志的 rgContainers[0]。
9, 对 0x5000000 进行内存布局。
10,1 替换token
对clfs对象trigger clfs,调用CreateLogFile,通过NtFsControlFile读取system process的token,执行了内存0x50000000中的内容,完成了对PipeAttribute内核对象的修改,从而使得NtFsControlFile能实现任意地址读取。
之后重复调用CreateLogFile触发漏洞,完成进程token的替换。
10,2
此外样本中同样也支持修改priviousMod,实现任意地址读写来提权的方式。
在 CClfsBaseFilePersisted::CheckSecureAccess 中使用了 fake pContainer(0x5000000),并最终调用 RtlClearBit 将当前线程的 PreviousMode 置 0。
将当前线程的 PreviousMode 置 0 后便可使用 NtWriteVirtualMemory 进行内核地址的任意读写。
这部分有点混乱
我这里用的https://github.com/fortra/CVE-2023-28252
的exp调试的,该exp对比样本有小改动,(建议调样本。。)
为 LOG:C:\Users\Public\MyLog%d%08d 添加容器,触发漏洞篡改 LOG:C:\Users\Public\MyLog_%08d 日志的 rgContainers[0]。
为 LOG:C:\Users\Public\MyLog%d%08d 添加容器的过程中,由于精心设计了控制块的数据所以出现了以下调用链。
关于如何精心设计控制块的数据可以看论坛里的另一篇帖子
https://bbs.kanxue.com/thread-278241.htm#msg_header_h2_3
trigger clfs中构造的0x68处的0x369对应了record offset array[12]
之后代码中通过trigger clfs + 0x30按公式(poi(poi(trigger clfs + 0x30) + 0x369)++)进行运算,导致triger clfs base block原本偏移0x398处的0x1470被修改为0x1570。并最终在triger clfs调用AddLogContainer时,通过0x1570寻址到错误的container poiner,直接执行到攻击者布局的恶意内存0x5000000中。
在CLFS!ClfsEarlierLsn下断看看
bu CLFS!ClfsEarlierLsn
bu CLFS!CClfsBaseFilePersisted::CheckSecureAccess+0x121
bu CLFS!CClfsBaseFilePersisted::CheckSecureAccess+0x13b
bu CLFS!CClfsBaseFilePersisted::CheckSecureAccess+0x16b
Exp中调用AddLogContainer,对应内核中的函数为CLFS!CClfsLogFcbPhysical::AllocContainer,该函数的this指针指向对象CClfsLogFcbPhysical
CClfsLogFcbPhysical对象0x2b0的位置指向CClfsBaseFilePersisted对象,该对象0x30的位置保存一个指针,该指针指向一段0x90大小的heap内存,这里称之为clfsheap,clfsheap 0x30保存指向base block的指针。
这里分别对trigger clfs base block这两个偏移下读写断点 398下写断点 058下读断点
正常情况下
[CTF入门培训]顶尖高校博士及硕士团队亲授《30小时教你玩转CTF》,视频+靶场+题目!助力进入CTF世界
最后于 2023-11-6 15:36
被kanxue编辑
,原因: