CVE-2021-26900 Win32k漏洞的提权

  • CVE-2021-26900 Win32k漏洞的提权已关闭评论
  • 14 views
  • A+

译文声明

本文来自https://www.zerodayinitiative.com/blog/2021/5/3/cve-2021-26900-privilege-escalation-via-a-use-after-free-vulnerability-in-win32k。

前言

2021年3月,Microsoft发布了一个补丁用于修正Windows内核中的一个漏洞,该bug可能允许攻击者提升权限执行代码。该漏洞由THEORI的安全研究员JeongOh Kyea(@kkokkokye)向ZDI报告。他提供了write-up和POC详细介绍了ZDI-21-331/CVE-2021-26900以及它如何绕过2020年7月的CVE-2020-1381修复程序。

DirectComposition

DirectComposition组件从Windows8开始引入,它有效地支持图像转换和动画等图形效果,@360Vulcan在CanSecWest 2017-Win32k Dark Composition上给出了一个关于发现DirectComposition漏洞的报告。

DirectComposition可以通过用NtDComposition开头的win32k系统调用来访问,Windows10 RS1之前,调用者对每个操作进行单独的系统调用,比如创建或释放资源,在Windows 10 RS1之后,这些被合并到一个系统调用NtDCompositionProcessChannelBatchBuffer中,它以批处理方式处理几个命令,@360Vulcan在CanSecWest

2017上展示了通过fuzz这个函数来发现漏洞,从那时起许多与DirectComposition相关的漏洞被发现,包括Pwn2Own漏洞CVE-2020-1382。

有三个必要的系统调用触发任何DirectComposition漏洞:

NtDCompositionCreateChannel
NtDCompositionProcessChannelBatchBuffer

NtDCompositionCommitChannel。

要创建DirectComposition对象,调用者需要先使用NtDCompositionCreateChannel系统调用创建一个通道。

// Create Channel
HANDLE hChannel;
PVOID pMappedAddress = NULL; SIZE_T SectionSize = 0x4000;
DWORD dwArg1, dwArg2;
NtDCompositionCreateChannel(&hChannel, &SectionSize, &pMappedAddress); // Data is Transferred through pMappedAddress

创建通道后可以使用NtDCompositionProcessChannelBatchBuffer系统调用发送几个命令,每个命令都有它自己不同大小的格式。

enum DCOMPOSITION_COMMAND_ID
{
ProcessCommandBufferIterator,
CreateResource,
OpenSharedResource,
ReleaseResource,
GetAnimationTime,
CapturePointer,
OpenSharedResourceHandle,
SetResourceCallbackId,
SetResourceIntegerProperty,
SetResourceFloatProperty,
SetResourceHandleProperty,
SetResourceHandleArrayProperty,
SetResourceBufferProperty,
SetResourceReferenceProperty,
SetResourceReferenceArrayProperty,
SetResourceAnimationProperty,
SetResourceDeletedNotificationTag,
AddVisualChild,
RedirectMouseToHwnd,
SetVisualInputSink,
RemoveVisualChild
};

映射的节地址pMappedAddress用于存储一批命令,pMappedAddress存储几个命令之后,调用者可以调用NtDCompositionProcessChannelBatchBuffer来处理这些命令。

要触发这个漏洞需要使用3个命令:CreateResource、SetResourceBufferProperty和ReleaseResource。

首先,CreateResource用于创建特定类型的对象,CreateResource命令的大小为16字节,格式如下:根据Windows版本不同,资源类型可能有所不同,您可以通过分析win32kbase!DirectComposition::CApplicationChannel::CreateResource函数来获得资源类型编号

Table-1.png

// Create Resource
*(DWORD*)(pMappedAddress) = CreateResource;
*(HANDLE*)(pMappedAddress + 4) = 1; // Resource ID (a unique number)// For example, on Windows 20H2, 19042.804:
// 0x58 == CInteractionTrackerMarshaler
// 0x59 == CInteractionTrackerBindingManagerMarshaler
*(DWORD*)(pMappedAddress + 8) = 0x59; // Resource Type
*(DWORD*)(pMappedAddress + 12) = FALSE;ntStatus = NtDCompositionProcessChannelBatchBuffer(hChannel, 16, &dwArg1, &dwArg2);

其次SetResourceBufferProperty用于设置目标对象的数据,该命令的大小和格式取决于资源类型。

Table-2.png

*(DWORD*)pMappedAddress = SetResourceBufferProperty;
*(HANDLE*)(pMappedAddress + 4) = 1; // Resource ID
*(DWORD*)(pMappedAddress + 8) = subcmd; // Sub-Command
*(DWORD*)(pMappedAddress + 12) = datasize; // Datasize
CopyMemory(pMappedAddress + 16, data, datasize); // Data

// Total size of command == 16 + datasize
ntStatus = NtDCompositionProcessChannelBatchBuffer(hChannel, 16 + datasize, &dwArg1, &dwArg2);

最后使用ReleaseResource释放资源,ReleaseResource命令的大小为8字节,格式如下。

Table-3.png

*(DWORD*)(pMappedAddress) = ReleaseResource;
*(HANDLE*)(pMappedAddress + 4) = 1; // Resource ID
ntStatus = NtDCompositionProcessChannelBatchBuffer(hChannel, 8, &dwArg1, &dwArg2);

NtDCompositionCommitChannel系统调用将这些命令序列化后,通过本地过程调用(LPC)协议发送到桌面窗口管理器(dwm.exe),从内核接收到命令后,桌面窗口管理器(dwm.exe)将这些命令呈现到屏幕上。

漏洞

CVE-2021-26900漏洞与CInteractionTrackerBindingManagerMarshaler和CInteractionTrackerMarshaler有关。此漏洞与CVE-2020-1381非常相似,所以讨论CVE-2021-26900之前先解释CVE-2020-1381。

CVE-2020-1381

CVE-2020-1381/ZDI-20-872于2020年7月修补,此漏洞发生在DirectComposition::
CInteractionTrackerBindingManagerMarshaler::SetBufferProperty函数中,该函数是CInteractionTrackerBindingManagerMarshaler对象的SetResourceBufferProperty命令的处理程序。

NTSTATUS DirectComposition::CInteractionTrackerBindingManagerMarshaler::SetBufferProperty(DirectComposition::CInteractionTrackerBindingManagerMarshaler *binding, DirectComposition::CApplicationChannel *resinfo, unsigned int subcmd, void* databuffer, size_t datasize, bool *out)
{
if( subcmd || datasize != 12 )
return STATUS_INVALID_PARAMETER;resource1_id = *(DWORD*)(databuffer)
resource2_id = *(DWORD*)(databuffer+4)
new_entry_id = *(DWORD*)(databuffer+8)// [1]. Get Proper Resource
if ( resource1_id && resource1_id < resinfo->resourceid_max )
tracker1 = *( (resource1_id - 1) * resinfo->entry_size + resinfo->resource_list );
else
tracker1 = NULL;if ( resource2_id && resource2_id < resinfo->resourceid_max )
tracker2 = *( (resource2_id - 1) * resinfo->entry_size + resinfo->resource_list );
else
tracker2 = NULL;// [2]. Check Resource type == CInteractionTrackerMarshaler
if ( tracker1 && tracker2 && tracker1->IsOfType(0x58) && tracker2->IsOfType(0x58) )
{
/*Find tracker pair in tracker list
1-1 If it exists, update entry_id
1-2 If it does not exist, add a new entry
*/
}
/* ... */}

CInteractionTrackerBindingManagerMarshaler对象接收12个字节作为SetResourceBufferProperty命令的数据,数据由三个DWORD组成:resource1_id,resource2_id和new_entry_id。

该函数先从用户([1])指定的resource1_id和resource2_id中检索资源。 然后检查每个资源的类型是否为0x58,这是CInteractionTrackerMarshaler([2])的资源类型。

然后将CInteractionTrackerMarshaler资源对添加到CInteractionTrackerBindingManagerMarshaler对象的跟踪器列表中,如名称所示,这两种对象类型CInteractionTrackerMarshaler和CInteractionTrackerBindingManagerMarshaler相互关联,CInteractionTrackerBindingManagerMarshaler对象保留了CInteractionTrackerMarshaler对象对的列表,并且每个CInteractionTrackerMarshaler对象都有一个指向CInteractionTrackerBindingManagerMarshaler对象的指针。

首次调用DirectComposition::CInteractionTrackerBindingManagerMarshaler::SetBufferProperty函数时,因为列表为空,所以跟踪器对被添加到列表中。

// Size == 32 bytes
struct TrackerEntry
{
CInteractionTrackerMarshaler* Tracker1;
CInteractionTrackerMarshaler* Tracker2;
DWORD entry_id;
DWORD flag1;
BYTE flag2;
};NTSTATUS DirectComposition::CInteractionTrackerBindingManagerMarshaler::SetBufferProperty(DirectComposition::CInteractionTrackerBindingManagerMarshaler *binding, DirectComposition::CApplicationChannel resinfo, unsigned int subcmd, void databuffer, size_t datasize, bool *out)
{
// ....
// 1-2. Add New Entry
if ( new_entry_id )
{
// [3]. Append Pair Data to list
result = DirectComposition::CDCompDynamicArrayBase::Grow(binding->tracker_list, 1, 'siCD');
if ( result < 0 )
return result;entry_size = binding->tracker_list.entrysize; // 0x20 by default
offset = entry_size * (binding->tracker_list.numofentry - 1);
dest = binding->tracker_list.ptr + offset;// struct TrackerEntry* TrackerPairEntry;
TrackerPairEntry->Tracker1 = tracker1;
TrackerPairEntry->Tracker2 = tracker2;
TrackerPairEntry->entry_id = new_entry_id;
TrackerPairEntry->flag1 = 0;
TrackerPairEntry->flag2 = 1;memmove(dest, TrackerPairEntry, entry_size);// [4]. Set reference from CInteractionTrackerMarshaler to CInteractionTrackerBindingManagerMarshaler
if ( !tracker1->binding_obj )
DirectComposition::CInteractionTrackerMarshaler::SetBindingManagerMarshaler(tracker1, resinfo, binding);
if ( !tracker2->binding_obj )
DirectComposition::CInteractionTrackerMarshaler::SetBindingManagerMarshaler(tracker2, resinfo, binding);}
// ...
}tracker_list大小增加1将新条目添加到跟踪器列表中,然后写入新的跟踪器对数据([3]),之后它使用DirectComposition::CInteractionTrackerMarshaler::SetBindingManagerMarshaler函数设置每个CInteractionTrackerMarshaler对象到cinteractiontrackbindingmanagermarshaler([4])对象的引用,如下所示。void DirectComposition::CInteractionTrackerMarshaler::SetBindingManagerMarshaler(DirectComposition::CInteractionTrackerMarshaler* tracker, DirectComposition::CApplicationChannel *resinfo, DirectComposition::CInteractionTrackerBindingManagerMarshaler *binding_obj)
{
old_binding_obj = tracker->binding_obj;
if ( old_binding_obj != binding_obj )
{
if ( binding_obj )
binding_obj->refcnt++;
DirectComposition::CApplicationChannel::ReleaseResource(_resource_list, old_binding_obj);
tracker->binding_obj = binding_obj;
}
}

DirectComposition::CInteractionTrackerMarshaler::SetBindingManagerMarshaler函数将tracker->
binding_obj更新为一个新的CInteractionTrackerBindingManagerMarshaler对象,将CInteractionTrackerMarshaler对象对附加到tracker_list之后,CInteractionTrackerMarshaler对象和CInteractionTrackerBindingManagerMarshaler对象之间的关系如下:

Chart1.jpg

因为它们相互引用,所以释放对象时必须清除这些引用,让我们看看CInteractionTrackerMarshaler对象被释放的情况。要释放与CInteractionTrackerMarshaler对象相关的资源,需要调用DirectComposition::CInteractionTrackerMarshaler::ReleaseAllReferences函数。

void DirectComposition::CInteractionTrackerMarshaler::ReleaseAllReferences(DirectComposition::CInteractionTrackerMarshaler *tracker, DirectComposition::CApplicationChannel *resinfo)
{
/* Omitted */
// ...
binding = tracker->binding_obj;
if( binding )
{
DirectComposition::CInteractionTrackerBindingManagerMarshaler::RemoveTrackerBindings(binding, tracker->resource_id);
DirectComposition::CApplicationChannel::ReleaseResource(resinfo, binding);
}tracker->binding_obj = NULL;
}void DirectComposition::CInteractionTrackerBindingManagerMarshaler::RemoveTrackerBindings(DirectComposition::CInteractionTrackerBindingManagerMarshaler *binding, int resource_id)
{
for (int i = 0; i < binding->tracker_list.numofentry; i++)
{
entry_size = binding->tracker_list.entrysize; // 0x20 by default
entry_ptr = (struct TrackerEntry *)(binding->tracker_list.ptr + entry_size * i);
entry_tracker1 = entry_ptr->Tracker1;
entry_tracker2 = entry_ptr->Tracker2;
if(entry_tracker1->resource_id == resource_id || entry_tracker2->resource_id == resource_id)
{
// set entry_id to 0
entry_ptr->entry_id = 0;
}
}
// Delete the entry of which entry_id is zero.
DirectComposition::CInteractionTrackerBindingManagerMarshaler::CleanUpListItemsPendingDeletion(binding);
}

如果cinteractiontrackbindingmanagermarshaler对象与cinteractiontrackbindingmanagermarshaler对象绑定,则调用DirectComposition::cinteractiontrackbindingmanagermarshaler::RemoveTrackerBindings来删除相应的跟踪条目。

在DirectComposition::cinteractiontrackbindingmanagermarshaler::RemoveTrackerBindings中,如果条目中的两个跟踪器对象中有一个与被删除对象匹配的资源id,则该条目的entry_id被设置为零,最后它调用DirectComposition::cinteractiontrackbindingmanagermarshaler::cleanuplisttitemspendingdeletion来清除那些entry_id等于0的条目。

然而如果一个单独的CInteractionTrackerMarshaler被添加到多个cinteractiontrackbindingmanagermarshaler跟踪列表会因为在添加新条目时没有检查,已经绑定到cinteractiontrackbindingmanagermarshaler对象的cinteractiontrackbindingmanagermarshaler对象可以绑定到第二cinteractiontrackbindingmanagermarshaler对象。

下图显示了这种情况:

Chart2.jpg

这种情况下如果Tracker1被释放,则只删除trackbindingb中的条目,因为Tracker1被绑定到trackbindingb,最后trackbindinga对象的条目具有已释放的对象指针。

Chart3.jpg

这个悬浮对象指针后面会在DirectComposition::cinteractiontrackbindingmanagermarshaler::
emitboundtrackermarshalerupdatecommand函数中被调用解引用,该函数可以通过ntdcompontioncommitchannel系统调用来触发,这个系统调用在批处理命令的序列化期间引用资源。

bool DirectComposition::CInteractionTrackerBindingManagerMarshaler::EmitBoundTrackerMarshalerUpdateCommands(DirectComposition::CInteractionTrackerBindingManagerMarshaler *binding, DirectComposition::CBatch **a2)
{
result = true;
for (int i = 0; i < binding->tracker_list.numofentry; i++)
{
entry_size = binding->tracker_list.entrysize; // 0x20 by default
entry_ptr = (struct TrackerEntry *)(binding->tracker_list.ptr + entry_size * i);
entry_tracker1 = entry_ptr->Tracker1;
entry_tracker2 = entry_ptr->Tracker2;
if( entry_ptr->entry_id )
{
result = entry_tracker1->EmitUpdateCommands(a2) & result;
result = entry_tracker2->EmitUpdateCommands(a2) & result;
}
}
}

上面的函数显示tracker_list中的对象调用Emitupdatecommand方法,被释放的对象在进程中被引用,产生了一个UAF漏洞。

CVE-2021-26900

CVE-2021-26900/ZDI-21-331可以绕过CVE-2020-1381补丁重新触发上述漏洞,CVE-2020-1381的补丁如下:

NTSTATUS DirectComposition::CInteractionTrackerBindingManagerMarshaler::SetBufferProperty(DirectComposition::CInteractionTrackerBindingManagerMarshaler *binding, DirectComposition::CApplicationChannel *resinfo, unsigned int subcmd, void* databuffer, size_t datasize, bool *out)
{
// ...
// 1-2. Add New Entry
if ( new_entry_id )
{
if ( !tracker1->binding_obj || tracker1->binding_obj == binding ) { // [*] Check tracker1->binding_obj
if ( !tracker2->binding_obj || tracker2->binding_obj == binding ) { // [*] Check tracker2->binding_obj
/* Add Tracker Pair routine */
result = DirectComposition::CDCompDynamicArrayBase::Grow(binding->tracker_list, 1, 'siCD');
// ...
// Omitted
}
}
}
// ...
}

添加标有[*]的代码部分用来检查CInteractionTrackerMarshaler对象的binding_obj,它检查CInteractionTrackerMarshaler是否已经绑定到另一个cinteractiontrackbindingmanagermarshaler。

然而这个补丁可以通过更新跟踪器条目绕过,让我们看看更新跟踪器条目的代码:

NTSTATUS DirectComposition::CInteractionTrackerBindingManagerMarshaler::SetBufferProperty(DirectComposition::CInteractionTrackerBindingManagerMarshaler *binding, DirectComposition::CApplicationChannel resinfo, unsigned int subcmd, void databuffer, size_t datasize, bool *out)
{
// ...
// 1. Find tracker pair in tracker list
for (int i = 0; i < binding->tracker_list.numofentry; i++)
{
entry_size = binding->tracker_list.entrysize; // 0x20 by default
entry_ptr = (struct TrackerEntry *)(binding->tracker_list.ptr + entry_size * i);
entry_tracker1 = entry_ptr->Tracker1;
entry_tracker2 = entry_ptr->Tracker2;tracker1_id = tracker1->resource_id;
tracker2_id = tracker2->resource_id;if ( (entry_tracker1->resource_id == tracker1_id && entry_tracker2->resource_id == tracker2_id) ||
(entry_tracker1->resource_id == tracker2_id && entry_tracker2->resource_id == tracker1_id) )
{
// 1-1 If it exists, update entry_id
if ( entry_ptr->entry_id == new_entry_id )
return 0;
// [1] Update entry_id
entry_ptr->entry_id = new_entry_id;
entry_ptr->flag2 = 1;if ( !new_entry_id )
{
// [2] if the new_entry_id is zero, remove relationship between CInteractionTrackerMarshaler and
// CInteractionTrackerBindingManagerMarshaler "if NECESSARY"
DirectComposition::CInteractionTrackerBindingManagerMarshaler::RemoveBindingManagerReferenceFromTrackerIfNecessary(binding, resinfo, tracker1_id, tracker2_id);
}
else
{
// Some routine
}
// ...
return 0;
}}
// 1-2. Add New Entry
// ...
}

首先上面的代码尝试找到具有跟踪器pair (tracker1, tracker2)或者(tracker2, tracker1)的条目,如果有条目,则将entry_id更新为new_entry_id([1])。

和该漏洞最重要的相关部分是[2],当new_entry_id为0时cinteractiontrackbindingmanagermarshaler对象将该条目视为不必要的时,为了处理这个条目它调用DirectComposition::

cinteractiontrackbindingmanagermarshaler::RemoveBindingManagerReferenceFromTrackerIfNecessary函数,但这个函数不会删除这个条目,它只删除绑定。

void DirectComposition::CInteractionTrackerBindingManagerMarshaler::RemoveBindingManagerReferenceFromTrackerIfNecessary(DirectComposition::CInteractionTrackerBindingManagerMarshaler *binding, DirectComposition::CApplicationChannel *resinfo, int resource1_id, int resource2_id)
{if (resource1_id && resource1_id < resinfo->resourceid_max)
tracker1 = *( (resource1_id - 1) * resinfo->entry_size + resinfo->resource_list );
else
tracker1 = NULL;if(resource2_id && resource2_id < resinfo->resourceid_max)
tracker2 = *( (resource2_id - 1) * resinfo->entry_size + resinfo->resource_list );
else
tracker2 = NULL;tracker1_exist = false;
tracker2_exist = false;// Check type of Resources
if ( tracker1 && tracker2 && tracker1->IsOfType(0x58) && tracker2->IsOfType(0x58) )
{
for(int i = 0; i < binding->tracker_list.numofentry; i++)
{
entry_size = binding->tracker_list.entrysize; // 0x20 by default
entry_ptr = (struct TrackerEntry *)(binding->tracker_list.ptr + entry_size * i);
entry_tracker1 = entry_ptr->Tracker1;
entry_tracker2 = entry_ptr->Tracker2;tracker1_id = tracker1->resource_id;
tracker2_id = tracker2->resource_id;// Find the entry
if ( entry_ptr->entry_id ) {
if ( entry_tracker1->resource_id == tracker1_id || entry_tracker2->resource_id == tracker1_id )
tracker1_exist = true;
if ( entry_tracker1->resource_id == tracker2_id || entry_tracker2->resource_id == tracker2_id )
tracker2_exist = true;
}
}
// If there is no other object related with tracker1 or tracker2
// Remove the binding.
if ( !tracker1_exist )
DirectComposition::CInteractionTrackerMarshaler::SetBindingManagerMarshaler(tracker1, resinfo, 0);
if ( !tracker2_exist )
DirectComposition::CInteractionTrackerMarshaler::SetBindingManagerMarshaler(tracker2, resinfo, 0);}
}

上面的函数寻找资源id为tracker1_id或tracker2_id的条目,如果没有其他资源id为tracker1_id或tracker2_id的条目则这两个对象不用相互引用,所以DirectComposition::CInteractionTrackerMarshaler::SetBindingManagerMarshaler函数被一个NULL绑定对象调用,来删除CInteractionTrackerMarshaler对象的绑定。

然而,即使从CInteractionTrackerMarshaler到cinteractiontrackbindingmanagermarshaler的绑定被删除,但tracker1或tracker2的指针仍然留在跟踪器列表中,用零new_entry_id更新条目后的状态如下所示:

Chart4.jpg

现在CInteractionTrackerMarshaler对象中的binding_obj设为零,这样可以绕过CVE-2020-1381的补丁,如果我们将tracker1绑定到另一个cinteractiontrackbindingmanagermarshaler对象,则状态如下:

Chart5.jpg

然后trackbindinga中的entry_id将其更新为非零值产生与CVE-2020-1381中相同的状态。`

补丁

该补丁应用于win32kbase.sys,修复CVE-2021-26900漏洞方法如下:

```
NTSTATUS DirectComposition::CInteractionTrackerBindingManagerMarshaler::SetBufferProperty(DirectComposition::CInteractionTrackerBindingManagerMarshaler binding, DirectComposition::CApplicationChannel resinfo, unsigned int subcmd, void databuffer, size_t datasize, bool out)
{
...

if( ( entry_tracker1->resource_id == tracker1_id && entry_tracker2->resource_id == tracker2_id ) ||
( entry_tracker1->resource_id == tracker2_id && entry_tracker2->resource_id == tracker1_id ) )
{
// 1-1 If it exists, update entry_id
if ( entry_ptr->entry_id == new_entry_id )
return 0;
// [1]. Update entry_id
entry_ptr->entry_id = new_entry_id;
entry_ptr->flag2 = 1;

  • if ( !new_entry_id ) {
  • DirectComposition::CInteractionTrackerBindingManagerMarshaler::RemoveBindingManagerReferenceFromTrackerIfNecessary(binding, resinfo, tracker1_id, tracker2_id);
  • }
  • else {
  • // Some routine
  • }
    ...
    return 0;
    }
    // 1-2. Add New Entry
    if ( new_entry_id )
    {
    if (!tracker1->binding_obj || tracker1->binding_obj == binding) { // [] Check tracker1->binding_obj
    if (!tracker2->binding_obj || tracker2->binding_obj == binding) { // [
    ] Check tracker2->binding_obj
  • overflow_check = tracker1->listref++ == -1;
  • if ( overflow_check ) {
  • tracker1->listref = -1
  • }
  • else {
  • overflow_check = tracker2->listref++ == -1;
  • if ( overflow_check ) {
  • tracker1->listref--;
  • tracker2->listref--;
  • }
  • else {
    / Tracker Pair Add routine /
    result = DirectComposition::CDCompDynamicArrayBase::Grow(binding->tracker_list, 1, 'siCD');
    ...
    // Omitted
  • }
  • }
    }
    }
    }
    ...
    }
    ```

该补丁适将条目添加到tracker_list中修改entry_id并释放资源的代码。

修改entry_id时虽然entry_id为0,但绑定不会被删除。

然后添加条目时list字段被添加到资源中,当相同的对象被插入到tracker_list中时该字段用于正确地释放对象。

```
void DirectComposition::CInteractionTrackerBindingManagerMarshaler::CleanUpListItemsPendingDeletion(DirectComposition::CInteractionTrackerBindingManagerMarshaler binding, DirectComposition::CApplicationChannel resinfo)
{

live_obj_num = 0;
for (int i = 0; i < binding->tracker_list.numofentry; i++)
{
entry_size = binding->tracker_list.entrysize; // 0x20 by default
entry_ptr = (struct TrackerEntry *)(binding->tracker_list.ptr + entry_size * i);
entry_tracker1 = entry_ptr->Tracker1;
entry_tracker2 = entry_ptr->Tracker2;

  • if ( entry_ptr->entry_id )
  • {
    // Make list compact
    write_ptr = (struct TrackerEntry *)(binding->tracker_list.ptr + entry_size * live_obj_num);
    memmove(write_ptr, entry_ptr, entry_size)
  • }
  • else
  • {
  • // NULL entry_id
  • entry_tracker1->listref--;
  • if (!entry_tracker1->listref) {
  • DirectComposition::CInteractionTrackerMarshaler::SetBindingManagerMarshaler(entry_tracker1, resinfo, 0);
  • }
  • entry_tracker2->listref--;
  • if (!entry_tracker2->listref) {
  • DirectComposition::CInteractionTrackerMarshaler::SetBindingManagerMarshaler(entry_tracker1, resinfo, 0);
  • }
  • }

    }
    DirectComposition::CDCompDynamicArrayBase::Shrink(binding->tracker_list,
    binding->tracker_list.numofentry - live_obj_num);
    }
    ```

最后释放资源时,绑定实际上会在DirectComposition:: cinteractiontrackbindingmanagermarshaler:: cleanuplisttitemspendingdeletion函数中被删除。

这里可以找到演示此漏洞的POC

相关推荐: 沙盒逃逸之seccomp学习

前言 今年的国赛pwn出了2道关于沙盒逃逸的题目,但之前只是了解并没有接触过沙盒逃逸,所以没做,国赛后的几天又去学习了沙盒逃逸,又一次知道了自己多菜。。。写下本篇记录沙盒逃逸的学习,本文仅介绍与pwn有关的沙盒逃逸。 沙盒 介绍 为了保护系统安全,用户层的应用…