Skip to content
KitploitKITPLOIT
工具博客
提交
工具博客
提交

黑客、渗透测试和网络安全工具,武装您的安全武器库!

Kitploit 是一个黑客、网络安全和渗透测试工具的目录。发现最新的项目更新,查找漏洞、分析系统、自动化测试并加强你的安全。

··订阅源·联系·隐私·© 2026 Kitploit

工具目录

分类

查看所有分类
Loading categories
CallbackHell — 针对 CVE-2021-40449 的漏洞利用程序 - Win32k 权限提升漏洞 (LPE) | Kitploit
工具/GitHubGitHub/ly4k/callbackhell
权限提升漏洞分析漏洞利用Shellcode后渗透利用Payload 开发二进制利用
GitHubly4k/callbackhell

CallbackHell

针对 CVE-2021-40449 的漏洞利用程序 - Win32k 权限提升漏洞 (LPE)

查看仓库
4819524年前Kitploit 审核通过

最受欢迎

查看全部 →

发现我们社区最常用的工具。

探索所有工具

浏览我们的工具集合

查看所有工具 →
分享

CallbackHell

针对 CVE-2021-40449(Win32k - LPE)的漏洞利用代码

  • CallbackHell
    • 描述
    • 技术分析
    • PoC
    • 参考资料

描述

CVE-2021-40449 是 Win32k 中的一个释放后使用(use-after-free)漏洞,可导致本地权限提升。

该漏洞由 卡巴斯基 在野外攻击中发现。

该已发现的漏洞利用代码支持以下 Windows 产品:

  • Microsoft Windows Vista
  • Microsoft Windows 7
  • Microsoft Windows 8
  • Microsoft Windows 8.1
  • Microsoft Windows Server 2008
  • Microsoft Windows Server 2008 R2
  • Microsoft Windows Server 2012
  • Microsoft Windows Server 2012 R2
  • Microsoft Windows 10 (build 14393)
  • Microsoft Windows Server 2016 (build 14393)
  • Microsoft Windows 10 (build 17763)
  • Microsoft Windows Server 2019 (build 17763)

不过,该漏洞利用代码目前仅在以下版本上测试过:

  • Microsoft Windows 10 (build 14393)
  • Microsoft Windows 10 (build 17763)

技术分析

强烈建议你在继续之前先阅读卡巴斯基的技术分析。

正如卡巴斯基技术分析文章中所提到的,漏洞存在于 GreResetDCInternal 中。如果攻击者挂钩了用户模式回调 DrvEnablePDEV(该回调在 hdcOpenDCW 期间被调用),则可以通过调用 ResetDC 来销毁原始设备上下文;当用户模式回调返回时,会在内核中造成释放后使用。

以下伪代码部分源自泄露的 Windows XP 源代码,并通过逆向工程 Win32kfull.sys 中(补丁发布前的)最新版 GreResetDCInternal 得出。不相关的部分已用 [...] 删除。请留意 VULN: 注释。

root@kitploit:~
BOOL GreResetDCInternal(
    HDC hdc,
    DEVMODEW *pdmw,
    BOOL *pbBanding,
    DRIVER_INFO_2W *pDriverInfo2,
    PVOID ppUMdhpdev)
{
    // [...]
    HDC hdcNew;

    {
        // Create DCOBJ from HDC
        DCOBJ dco(hdc);

        if (!dco.bValid())
        {
            SAVE_ERROR_CODE(ERROR_INVALID_HANDLE);
        }
        else
        {
            // Create DEVOBJ from `dco`
            PDEVOBJ po(dco.hdev());

            // [...]

            // Create the new DC
            // VULN: Can result in a usermode callback that destroys old DC, which
            // invalidates `dco` and `po`
            hdcNew = hdcOpenDCW(L"",
                                pdmw,
                                DCTYPE_DIRECT,
                                po.hSpooler,
                                prton,
                                pDriverInfo2,
                                ppUMdhpdev);

            if (hdcNew)
            {
                po->hSpooler = NULL;

                DCOBJ dcoNew(hdcNew);

                if (!dcoNew.bValid())
                {
                    SAVE_ERROR_CODE(ERROR_INVALID_HANDLE);
                }
                else
                {
                    // Transfer any remote fonts

                    dcoNew->pPFFList = dco->pPFFList;
                    dco->pPFFList = NULL;

                    // Transfer any color transform

                    dcoNew->pCXFList = dco->pCXFList;
                    dco->pCXFList = NULL;

                    PDEVOBJ poNew((HDEV)dcoNew.pdc->ppdev());

                    // Let the driver know
                    // VULN: Method is taken from old (possibly destroyed) `po`
                    PFN_DrvResetPDEV rfn = po->ppfn[INDEX_DrvResetPDEV];

                    if (rfn != NULL)
                    {
                        (*rfn)(po->dhpdev, poNew->dhpdev);
                    }

                    // [...]
                }
            }
        }
    }

    // Destroy old DC
    // [...]
}

从伪代码中可以看出,旧的设备上下文可以在 hdcOpenDCW 调用的用户模式回调中被释放,随后会从旧的设备上下文中获取 DrvResetPDEV 方法,并以 (po->dhpdev, poNew->dhpdev) 作为参数进行调用。

要创建并挂钩设备上下文,可以执行以下操作:

  • 使用 EnumPrinters 查找可用的打印机
  • 使用 OpenPrinter、GetPrinterDriver 和 LoadLibraryExA 将打印机驱动程序加载到内存中
  • 使用 GetProcAddress 和 DrvEnableDriver 获取打印机驱动程序的用户模式回调表
  • 使用 VirtualProtect 取消对打印机驱动程序用户模式回调表的保护
  • 覆盖打印机驱动程序的所需用户模式回调表条目
  • 使用 CreateDC(NULL, printerName, NULL, NULL) 为打印机创建设备上下文

现在,我们便拥有了一个带有已挂钩用户模式回调的打印机设备上下文。

我们只对其中一个挂钩感兴趣,即 DrvEnablePDEV。该挂钩之所以值得关注,体现在两个方面:触发 UAF 以及控制参数,如前所述。要触发 UAF 漏洞,我们需要在挂钩内部调用 ResetDC,这将销毁旧的设备上下文。当我们从挂钩返回时,仍处于第一次 GreResetDCInternal 调用之中;紧接着,它会从已销毁的旧设备上下文中获取 DrvResetPDEV 函数指针,并以 DrvEnablePDEV 返回的两个参数——旧的 DHPDEV 和新的 DHPDEV——调用该函数。

如果你的进程以中等完整性级别运行,借助 EnumDeviceDrivers 和 NtQuerySystemInformation,KASLR 应该不构成问题。

卡巴斯基提到,原始漏洞利用代码使用 GDI 调色板对象和单个内核函数调用来实现任意内存读写。本漏洞利用代码使用一种在大型池上分配 BitMapHeader 的技术以及 RtlSetAllBits,为当前进程令牌启用所有特权。BitMapHeader 将指向当前进程令牌的 _SEP_TOKEN_PRIVILEGES。通过调用 RtlSetAllBits(BitMapHeader),即可通过单个内核函数调用为当前进程令牌启用所有特权。由此,便可滥用这些新特权来获取 SYSTEM 权限。本漏洞利用代码使用 SeDebugPrivilege 将 shellcode 注入 winlogon.exe 进程。

PoC

./poc.png

参考资料

  • https://securelist.com/mysterysnail-attacks-with-windows-zero-day/104509/
  • https://github.com/siberas/CVE-2016-3309_Reloaded/
  • https://www.ired.team/miscellaneous-reversing-forensics/windows-kernel-internals/how-kernel-exploits-abuse-tokens-for-privilege-escalation
  • https://github.com/KaLendsi/CVE-2021-40449-Exploit
  • https://mp.weixin.qq.com/s/AcFS0Yn9SDuYxFnzbBqhkQ
下载工具