首页
社区
课程
招聘
[原创]CVE-2022-21882提权漏洞学习笔记
发表于: 2022-8-21 17:45 16666

[原创]CVE-2022-21882提权漏洞学习笔记

2022-8-21 17:45
16666

一.前言

1.漏洞描述

该漏洞的成因及利用基本上和CVE-2021-1732一样,可以认为该漏洞是在对CVE-2021-1732漏洞进行补丁之后,绕过该补丁达成漏洞利用。在对CVE-2021-1732补丁后,在xxxCreateWindowEx函数调用过程中,会在调用xxxClientAllocWindowClassExtraBytes申请扩展内存后,会对窗口对象的偏移0x128处的pExtraBytes进行验证,以此来验证是否在执行用户层函数时被修改。然而,该补丁仅针对xxxCreateWindowEx函数,在后面的Windows版本中,出现了新的函数会调用xxxClientAllocWindowClassExtraBytes函数,而这些函数没有对pExtraBytes进行验证,导致可以通过这些新函数来实现对窗口对象偏移0xE8的Flags以及0x128的pExtraBytes进行修改。

2.实验环境

  • 操作系统:Win10 x64 21H2 专业版

  • 编译器:Visual Studio 2017

  • 调试器:IDA Pro, WinDbg

二.漏洞分析

1.CVE-2021-1732补丁分析

在对CVE-2021-1732进行补丁之后,xxxCreateWindowEx函数会在申请扩展内存之后,会调用tagWND::RedirectedFieldpExtraBytes::operator函数来对窗口对象进行验证,如果该函数返回1,则函数接下来就会释放窗口对象,然后直接退出函数,而不执行下面的对pExtraBytes成员的赋值:

__int64 __fastcall xxxCreateWindowEx(int a1, __int64 a2, __int64 a3, __int64 a4, unsigned int a5, unsigned int a6, unsigned int a7, unsigned int a8, unsigned int a9, __int64 a10, __int64 a11, __int64 a12, __int64 a13, unsigned int a14, int a15, int a16, __int64 a17)
{
  cbwndExtra = *(unsigned int *)(*((_QWORD *)tagWND + 5) + 0xC8i64);
  if ( !(_DWORD)cbwndExtra )
    goto LABEL_211;
  pBuffer = xxxClientAllocWindowClassExtraBytes(cbwndExtra);        // 申请扩展内存
  v355 = pBuffer;
  if ( !pBuffer )
  {
    v273 = 2;
    if ( *((_DWORD *)tagWND + 2) != 1 )
      goto LABEL_538;
    goto LABEL_197;
  }
  
  // 对窗口对象进行验证
  if ( (unsigned int)IsWindowBeingDestroyed((__int64)tagWND)
    || (*(_BYTE *)(_HMPheFromObject(v95) + 0x19) & 1) != 0
    || (zero = 0i64, tagWND::RedirectedFieldpExtraBytes::operator!=((__int64)tagWND + 0x140, &zero)) )
  {
    xxxFreeWindow(tagWND);                                              // 释放窗口
    if ( v113 )
      goto LABEL_553;
    goto LABEL_37;                                                      // 退出函数
  }
  
  *(_QWORD *)(tagWNDK + 0x128) = pBuffer;                               // 为pExtraBytes成员赋值
}

xxxCreateWindowEx调用tagWND::RedirectedFieldpExtraBytes::operator验证函数的时候,传入的是tagWND + 0x140和值为0的zero这两个参数,而验证函数代码则如下,所以该函数就是在验证*(*(tagWND + 0x140 - 0x118) + 0x128) = *(*(tagWND + 0x28) + 0x128)是否不等于NULL,就是在验证pExtraBytes是否已经被写入,因为在xxxCreateWindowEx函数会在验证通过之后才为pExtraBytes成员赋值,如果验证时候该值已经不为NULL,就说明在用户层函数被劫持了:

然而,该补丁是打在xxxCreateWindowEx函数中,函数xxxClientAllocWindowClassExtraBytes并没有任何变化,该补丁可以在原来的系统中起到保护作用。可是在之后的系统中,增加了不同的函数可以调用xxxClientAllocWindowClassExtraBytes,其中就包括了xxxSwitchWndProc。因此可以通过该函数来实现对窗口对象的Flags和pExtraBytes成员进行修改,最终达成利用:

2.xxxSwitchWndProc函数分析

在xxxSwitchWndProc函数中,会判断窗口对象是否存在扩展内存,如果存在扩展内存,则会调用xxxClientAllocWindowClassExtraBytes函数来申请内存。随后,函数会重新为pExtraBytes成员进行赋值,并调用xxxClientFreeWindowClassExtraBytes函数将原来pExtraBytes指向的内存释放掉。因此,可以通过xxxSwitchWndProc函数来实现xxxClientAllocWindowClassExtraBytes函数的调用,并通过劫持相应的用户层函数,可以实现对pExtraBytes的修改:

三.漏洞利用

1.xxxSwitchWndProc函数的调用

通过交叉引用可以看到,xxxSwitchWndProc函数由xxxWrapSwitchWndProc函数调用的。

xxxSwitchWndProc函数则由NtUserMessageCall函数开始一步步调用到,该函数的定义如下:

typedef NTSTATUS (__fastcall *lpfnNtUserMessageCall)(HWND hWnd, 
                                                     UINT msg, 
                                                     WPARAM wParam, 
                                                     LPARAM lParam, 
                                                     ULONG_PTR ResultInfo, 
                                                     DWORD dwType, 
                                                     BOOL bAnsi);

[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课

最后于 2022-8-21 17:55 被1900编辑 ,原因:
收藏
免费 4
支持
分享
打赏 + 50.00雪花
打赏次数 1 雪花 + 50.00
 
赞赏  Editor   +50.00 2022/09/27 恭喜您获得“雪花”奖励,安全圈有你而精彩!
最新回复 (0)
游客
登录 | 注册 方可回帖
返回