Self Destruction To Use After Free In Kernel:CVE-2024-38059分析记录

Self Destruction To Use After Free In Kernel:CVE-2024-38059分析记录

原创 信创实验室 山石网科安全技术研究院 2024-07-10 11:00

漏洞描述

微软七月份补丁日发布了编号为CVE-2024-38059的win32k内核提权漏洞,由山石网科信创安全实验室报告,目前已修复完成,漏洞详细情况详如下:

漏洞名称

Win32k 特权提升漏洞

漏洞公开编号

CVE-2024-38059

漏洞类型

权限提升

公开时间

2024-07-10

漏洞等级

重要

评分

7.8

漏洞所需权限

低权限

漏洞利用难度

PoC状态

未知

EXP状态

未知

漏洞细节

未知

在野利用

未知

微软 DirectComposition 合成器是一个 Windows 组件内核组件,位于win32k驱动程序中,它支持高性能的位
图合成,具有变换、效果和动画功能。应用程序开发人员可以使用 DirectComposition API 创建视觉上引人入胜的用户界面,该界面具有从一个视觉到另一个视觉的丰富流畅的动画过渡。DirectComposition 通过实现高帧速率、使用图形硬件和独立于 UI 线程运行来实现丰富流畅的过渡。DirectComposition 可以接受由不同渲染库绘制的位图内容,包括 Microsoft DirectX 位图和渲染到窗口的位图(HWND 位图)。此外,DirectComposition 支持各种变换,例如 2D 仿射变换和 3D 透视变换,以及剪裁和不透明度等基本效果。

该模块在2019年-2022年期间爆出过大量的漏洞尤其是
 CInteractionTrackerBindingManagerMarshaler

跟踪器对象绑定关联管理器对象中。这个对象在后面更多的漏洞复现报告中会进行详细介绍,敬请关注山石网科安全技术研究院公众号获取更多信息。

漏洞分析

漏洞存在于

DirectComposition::CInteractionTrackerBindingManagerMarshaler::CleanUpListItemsPendingDeletion 
函数中:

void __fastcall DirectComposition::CInteractionTrackerBindingManagerMarshaler::CleanUpListItemsPendingDeletion(__int64 this, struct DirectComposition::CApplicationChannel *a2)
{
  ....

  // 1. 防止重入
  if ( !*(_BYTE *)(this + 65) )
  {
    v4 = *(_QWORD *)(this + 96);
    v5 = 0;
    v6 = 0;
    *(_BYTE *)(this + 65) = 1;
    if ( v4 )
    {
      v7 = 0i64;
      do
      {
        v8 = *(_QWORD *)(this + 72);
        v9 = *(_QWORD *)(this + 104);
        v10 = *(_DWORD *)(v7 * v9 + v8 + 16) == 0;
        v11 = *(_OWORD *)(v7 * v9 + v8);
        *(_OWORD *)v17 = v11;
        if ( v10 )
        {
          v14 = v17[0];
          v10 = (*((_DWORD *)v17[0] + 16))-- == 1;
          if ( v10 )
            DirectComposition::CInteractionTrackerMarshaler::SetBindingManagerMarshaler((__int64)v14, a2, 0i64);
          v15 = v17[1];
          v10 = (*((_DWORD *)v17[1] + 16))-- == 1;
          if ( v10 )
            // 2. CInteractionTrackerBindingManagerMarshaler 对象在调用 SetBindingManagerMarshaler 后可能被销毁
            DirectComposition::CInteractionTrackerMarshaler::SetBindingManagerMarshaler((__int64)v15, a2, 0i64);
          DirectComposition::CApplicationChannel::ReleaseResource((__int64)a2, (__int64)v14);
          DirectComposition::CApplicationChannel::ReleaseResource((__int64)a2, (__int64)v15);
        }
        else
        {
          v12 = *(_OWORD *)(v7 * v9 + v8 + 16);
          v13 = v5 * v9;
          Src[0] = v11;
          Src[1] = v12;
          ++v5;
          memmove((void *)(v8 + v13), Src, v9);
        }

        // 3. 这里产生UAF
        v4 = *(_QWORD *)(this + 96);
        v7 = ++v6;
      }
      while ( v6 < v4 );
    }

    // 4. 这里产生UAF
    DirectComposition::CDCompDynamicArrayBase::Shrink(this + 72, v4 - v5);
    *(_BYTE *)(this + 65) = 0;
  }
}

我们看到,
DirectComposition::CInteractionTrackerBindingManagerMarshaler::CleanUpListItemsPendingDeletion

函数在

CInteractionTrackerBindingManagerMarshaler

对象最终释放时或者在

CInteractionTrackerMarshaler 
对象释放减少引用操作时调用。


CleanUpListItemsPendingDeletion
函数清除绑定在 
CInteractionTrackerMarshaler
对象上的指针和引用时,
在第二次调用
 DirectComposition::CInteractionTrackerMarshaler::SetBindingManagerMarshaler
函数后即可释放。因此,接下来内核的所有操作将使用被释放的指针,因此产生UAF漏洞。

我们看看如何复现该漏洞:

  1. 创建
     hChannel 
    对象并返回句柄和BatchBuffer映射地址

  2. 创建第一个
    CInteractionTrackerMarshaler
    对象,句柄设置为 1

  3. 创建第二个
    CInteractionTrackerMarshaler
    对象,句柄设置为 2

  4. 创建
    CInteractionTrackerBindingManagerMarshaler
    对象,句柄设为 3

  5. 调用
    CInteractionTrackerBindingManagerMarshaler
    对象上的
    SetBufferProperty
    函数,并与两个
    CInteractionTrackerMarshaler
    对象绑定

  6. 退出进程或销毁
    hChannel
    ,蓝屏发生

为什么这几个操作后内核会崩溃呢?

我们来跟踪下对象的释放过程:

void __fastcall DirectComposition::CApplicationChannel::ReleaseAllResources(__int64 this, __int64 a2)
{
  // 1. 清空 marshaler 对象句柄表并同时释放对象
  ...

  // 2. 删除第二个 marshaler 对象表并释放对象
  while ( 1 )
  {
    v11 = (__int64)DirectComposition::CLinearObjectTableBase::EnumerateObjects(this + 112, &v21);
    v12 = v11;
    if ( !v11 )
      break;
    DirectComposition::CResourceMarshaler::AddRef(v11);

    // 3. 调用 marshaler对象的 ReleaseAllReferences 函数
    (*(void (__fastcall **)(__int64, __int64))(*(_QWORD *)v12 + 0xC0i64))(v12, this);
    DirectComposition::CApplicationChannel::ReleaseResource(this, v12);
  }
  if ( a2 )
    *(_BYTE *)a2 = *(_DWORD *)(this + 524) != 0;
}

void __fastcall DirectComposition::CInteractionTrackerMarshaler::ReleaseAllReferences(__int64 this, struct DirectComposition::CApplicationChannel *a2)
{
  ...

  // 1. 将 CInteractionTrackerBindingManagerMarshaler 从 CInteractionTrackerMarshaler 对象中移除
  v11 = *(_QWORD *)(this + 448);
  if ( v11 )
  {
    // 2. 最终调用 DirectComposition::CInteractionTrackerBindingManagerMarshaler::CleanUpListItemsPendingDeletion 函数
    DirectComposition::CInteractionTrackerBindingManagerMarshaler::RemoveTrackerBindings(v11, a2, *(_DWORD *)(this + 32));
    DirectComposition::CApplicationChannel::ReleaseResource((__int64)a2, *(_QWORD *)(this + 448));
    *(_QWORD *)(this + 448) = 0i64;
  }
}

我们来追踪这些对象的引用计数:

我们首先创建的是 
CInteractionTrackerMarshaler 
对象,所以 
DirectComposition::CLinearObjectTableBase::EnumerateObjects 
在调用时候首先返回 
CInteractionTrackerMarshaler 
对象的指针,下面是各个对象的引用计数情况:

CInteractionTrackerMarshaler
对象1 引用计数: 1

CInteractionTrackerMarshaler
对象2 引用计数: 1

CInteractionTrackerBindingManagerMarshaler
对象引用计数: 2(2个 
CInteractionTrackerMarshaler 
绑定了它)

  1. DirectComposition::CResourceMarshaler::AddRef

    (+1),在调用
     ReleaseAllReferences 
    函数之前,在
     CInteractionTrackerMarshaler 
    对象 1 上添加新的引用,引用计数表:(2, 1, 2)

2
.

D
irectComposition::CInteractionTrackerBindingManagerMarshaler::CleanUpListItemsPendingDeletion 
函数调用
 DirectComposition::CInteractionTrackerMarshaler::SetBindingManagerMarshaler 
(-1),删除
 CInteractionTrackerBindingManagerMarshaler 
对象上的引用,引用计数表:(2, 1, 1)

3. 
DirectComposition::CInteractionTrackerMarshaler::SetBindingManagerMarshaler 
(-1),再次删除
 CInteractionTrackerBindingManagerMarshaler 
对象上的引用,并销毁它,引用计数表:(2, 1, 0),
CInteractionTrackerBindingManagerMarshaler 
对象被释放

4. 
DirectComposition::CApplicationChannel::ReleaseResource 
两次 (-1, -1),从每个
 CInteractionTrackerMarshaler 
对象中删除一个引用,第二个对象被释放,引用计数表:(1, 0, 0)

  1. 内核继续访问

    CInteractionTrackerBindingManagerMarshaler 
    对象时发生崩溃

个人认为或许应该在调用 
CleanUpListItemsPendingDeletion 
函数之前在 
CInteractionTrackerBindingManagerMarshaler 
对象上添加一个额外的引用计数,并在 
CleanUpListItemsPendingDeletion 
函数完成后调用
 ReleaseResource 
来解决这个问题,感兴趣同学的可以研究下微软的修复方式。

影响版本

Windows 10 Version 21H2 for 32-bit Systems

Windows 10 Version 21H2 for ARM64-based Systems

Windows 10 Version 21H2 for x64-based Systems

Windows 10 Version 22H2 for 32-bit Systems

Windows 10 Version 22H2 for ARM64-based Systems

Windows 10 Version 22H2 for x64-based Systems

Windows 11 version 21H2 for ARM64-based Systems

Windows 11 version 21H2 for x64-based Systems

Windows 11 Version 22H2 for ARM64-based Systems

Windows 11 Version 22H2 for x64-based Systems

Windows 11 Version 23H2 for ARM64-based Systems

Windows 11 Version 23H2 for x64-based Systems

Windows Server 2022

Windows Server 2022 (Server Core installation)

Windows Server 2022, 23H2 Edition (Server Core installation)

安全建议

安装相应的补丁程序,目前,官方已发布修复程序,受影响的用户可以直接升级至安全版本。

下载地址:https://msrc.microsoft.com/update-guide/vulnerability/CVE-2024-38059

参考信息

https://msrc.microsoft.com/update-guide/vulnerability/CVE-2024-
38059

https://learn.microsoft.com/zh-cn/windows/win32/directcomp/basic-concepts