• CVE-2021-33739 EOP漏洞分析


    背景

      CVE-2021-33739是一个UAF漏洞,成因是由于在对象CInteractionTrackerBindingManagerMarshaler与对象CInteractionTrackerMarshaler双向绑定的前提下,再对双方绑定进行解绑,CInteractionTrackerMarshaler指向前者的指针虽被清除,但CInteractionTrackerBindingManagerMarshaler中指向CInteractionTrackerMarshaler的指针仍然存在,之后释放CInteractionTrackerMarshaler对象,CInteractionTrackerBindingManagerMarshaler中的指针仍然指向被free的内核地址,从而导致UAF漏洞。

    分析

      首先创建一个CInteractionTrackerBindingManagerMarshaler(id=1)和两个CInteractionTrackerMarshaler对象资源(id=2、3)。创建方式是利用用户态win32u.dll模块的导出函数NtDCompositionProcessChannelBatchBuffer,通过和信道关联的缓冲区pMappedAddress指定创建资源类型(ResourceType)和指令(nCmdCreateResource),在内核中创建指定id的相应资源。信道通过调用函数NtDCompositionCreateChannel创建。

      系统调用NtDCompositionProcessChannelBatchBuffer支持的指令如下,每个指令都有自己不同的缓冲区大小和格式。当前漏洞涉及到了其中的nCmdCreateResource(1)、nCmdReleaseResource(3)、nCmdSetResourceBufferProperty(12)。

      nCmdCreateResource指令对应的缓冲区(pMappedAddress)格式和大小:

      调用后,执行至win32kbase!DirectComposition::CApplicationChannel::CreateResource,再根据isSharedResource参数执行CreateInternalSharedResource或CreateInternalResource,漏洞在CreateInternalResource中。

      win32kbase!DirectComposition::CApplicationChannel::CreateInternalResource根据Resource Type创建不同资源对象。

      对象全部创建成功后,指定处理指令nCmdSetResourceBufferProperty,将两种不同类型指令进行绑定。缓冲区格式如下:

      该指令将执行至CInteractionTrackerBindingManagerMarshaler::SetBufferProperty,该函数位于CInteractionTrackerBindingManagerMarshaler对象偏移0xA8处。

      如果CInteractionTrackerBindingManagerMarshaler没有绑定对象,且nCmdSetResourceBufferProperty指令对应pMappedAddress中由用户指定的EntryID(Data偏移+0x8处)不为0,则将TrackerManager(CInteractionTrackerBindingManagerMarshaler)和两个Tracker(CInteractionTrackerMarshaler)互相绑定。

      由TrackerManager向Tracker的绑定方式是创建一个TrackerEntry结构,指针放在TrackerManager偏移+0x38处。TrackerEntry结构大小为32字节:
    pTracker1(QWORD) | pTracker2(QWORD) | entry_id(QWORD) | 1(QWORD)
      绑定后的TrackerManager:

      而从Tracker向TrackerManager的绑定由SetBindingManagerMarshaler函数实现。该函数先判断Tracker偏移0x190处指针是否指向待绑定的TrackerManager,在确认未绑定的条件下先将TrackerManager偏移0x14处的资源引用值加1,接着在Tracker对象偏移0x190处写入TrackerManager对象指针值,实现绑定。

      指令完成后,再次执行上一步nCmdSetResourceBufferProperty指令操作,不过变动是需要指定EntryID为0(szBuff+0x8)。

      再次执行至SetBufferProperty,此时流程将进入另一分支,因为此时在TrackerManager对象偏移0x50处值由0变成1,应该和TrackerEntry关联。之后又根据用户给的Tracker1和Tracker2二者ID从channel对象关联的pMappedAddress中取出各自对应下标的指针值,和TrackerManager中TrackerEntry绑定的两个Tracker ID进行比较,相同则继续,不同则跳转至绑定分支。

      顺利执行下来,又对用户指定的EntryID判断为0的话,将调用RemoveBindingManagerReferenceFromTrackerIfNecessary,该函数将解除TrackerManager和Tracker的绑定关系。然而漏洞就是出现在此处,因为RemoveBinding...函数只是将Tracker中的TrackerManager指针值置0,而TrackerManager中的TrackerEntry仍然存在。

      之后释放(nCmdReleaseResource)两个Tracker资源,再调用NtDCompositionCommitChannel提交channel数据后将触发BSOD。可以看到,最终是在调用CInteractionTrackerBindingManagerMarshaler::EmitBoundTrackerMarshalerUpdateCommands发生错误。

    利用

    目前公开的POC,是利用构造的Palette对象去占用被释放的两个Tracker的原本空间,之后再借助NtDCompositionCommitChannel触发利用。

      每释放一个Tracker,就紧接着通过大量创建Fake_Palette对象的方式去占用目标空间。为了能准确地实现占用,构造的Fake_Palette对象大小应和原本被释放的Tracker对象大小一致,可以在之前的windbg中使用命令!pool中看到Tracker的size为0x1A0。

      在分析部分,可以知道最终是在CInteractionTrackerBindingManagerMarshaler::EmitBoundTrackerMarshalerUpdateCommands函数除触发的BSOD。
      查看该函数,可以看到会调用 (*pTracker)+0x50 地址处的函数,应该是原本已释放Tracker的虚表函数调用。

      通过构造Palette,可指定函数调用,POC中选用了nt! SeSetAccessStateGenericMapping,可将16字节内容写入可控地址,可用于替换_KTHREAD中的PreviousMode(1:usermode;0:kernelmode),内核中的完整性检查是在previousmode为1前提下,意味着previousmode被覆写为0可进行跟高权限操作。

      查看nt!SeSetAccessStateGenericMapping,其中rdx指向channel缓冲区的偏移0xB8处的16字节。多次调试后发现该位置前8字节为一个不明指针值,后8字节为0值,因此覆写时,向后移动了9字节,以保证0值覆盖previousmode字段。

      POC代码中似乎还尝试修改Token,但是rdx不可控,似乎没起作用。
      另外在EmitBoundTrackerMarshalerUpdateCommands中,需要TrackerEntry的ID不为0方才能调用虚表中的函数。但是解绑Tracker2和Tracker3时,TrackerEntry被重新设置为了0,因此POC除了创建Tracker2和Tracker3,还需要创建第三个Tracker(Tracker4)。在绑定和释放Tracker2和Tracker3且Fake_Palette成功占用二者原来空间后,再绑定Tracker4和TrackerManager,指定TrackerEntry不为0,如POC中的0xffff。

      成功占用后的空间情况,可以看到都是大小为0x1A0的相同连续空间分布。

      PreviousMode覆写前后:

      之后将shellcode注入winlogon.exe,启动system权限的cmd.exe。

    参考

    https://www.anquanke.com/post/id/245427
    https://www.zerodayinitiative.com/blog/2021/5/3/cve-2021-26900-privilege-escalation-via-a-use-after-free-vulnerability-in-win32k
    https://github.com/Lagal1990/CVE-2021-33739-POC/blob/fbbba006a610f4f269c9aefdf060562d86459bf5/CVE-2021-26868 %26 CVE-2021-33739/exp/exp.cpp

  • 相关阅读:
    ios app: 使用企业license设置发布app的过程
    gtest测试代码编写思想
    受尽侮辱的语言
    创业者的思维误区---《精益创业》
    session的取代者:Json Web Tokens----在客户端存储登陆状态
    lineman 的理念与 modern web app
    angularjs框架及其生态环境 --待续
    javascript的崛起及其生态元素
    Cassandra 2.x 提示“错误: 代理抛出异常错误: java.lang.NullPointerException”
    cassandra运行出现了Unable to gossip with any seeds,cqlsh链接不上,提示connection refused处理办法
  • 原文地址:https://www.cnblogs.com/zUotTe0/p/15227947.html
Copyright © 2020-2023  润新知