修复WindowsTerminal拖拽:DataExchangeHost vs Win32k UIPI

大类
逆向
Windows
技术标签
逆向-Windows
原理研究-Windows
优先级
Low
开始日期
Mar 13, 2023
状态
Maintaining
Public
Public
最后更新
Mar 13, 2023

TL;DR

安装说明见repo readme

现象:

  • WindowsTerminal内部tab能拖拽
  • WindowsTerminal不能从外面拖拽进文件
  • 新记事本能从外面拖拽

实验

  • 环境:
    • WinDBG挂kd
    • Windows 11
  • 实验方法:
    • fEnforceUIPI初始化逻辑:bp win32kbase!Initialize
    • 修改fEnforceUIPI:eb …
  • 实验1:
    • 启动时下fEnforceUIPI的写断点,始终保证其为false
    • 此时仍然不能从低权限向高权限拖拽
    • 若动态更改fEnforceUIPI为true
      • 管理员cmd可以被拖拽进去
      • 管理员wt仍然不行
  • 实验2:在上述条件下,利用记事本的打开文件引出explorer
    • 两个管理员记事本之间的explorer框可以互相拖
    • 管理员记事本和管理员wt之间的explorer框可以互相拖
    • 管理员wt的explorer框可以拖到管理员记事本编辑框上
    • (需测试:普通用户能否拖到管理员记事本上)
    • 管理员wt仍然无法使用任何方式拖上去(猜测和wt的逻辑写法有关)
  • 初步总结:UIPI只是通过Integrity Level限制,但消息的处理还有一道关卡反而需要UIPI参与才能正常工作

解决

  • 拖拽的时候能看见DataExchangeHost启动,所以实际上大半个流程是走的通的,怀疑是DataExchangeHost在搞鬼
  • x64dbg断点在所有带有Drag关键字的函数上,拖拽的时候除了各种wrapper,唯一触发的成员函数是CDragBroker::GetOleTarget
    • IDA打开一看问题果然出在他身上
    • CDragBroker::GetOleTarget硬编码逻辑,必须IL < 0x3000 (也就是小于High IL)才会放行