• CVE-2015-0057 POC构造 & 利用分析(2015.7)


    CVE-2015-0057 POC构造 & 利用分析

    主要内容:

    构造POC

    利用思路

    0x00 初探

    从这篇文章可以获知:

    1.问题出在 win32k!xxxEnableWndSBArrows 函数,其在触发 user-mode callback 后,执行完相应操作后从用户层返回到内核层,对接下来操作的对象未能验证其是否已经释放(更改),而继续对其进行操作,导致UAF。触发user-mode callback的调用流程为:

    2.所涉及的敏感对象为 tagSBINFO,可以通过CreateWindows("SCROLLBAR"...)来创建。

    3.关键利用代码也位于 win32k!xxxEnableWndSBArrows 函数内,位于第一次调用 xxxDrawScrollBar 函数后。

    所以要构造POC,思路就很明确了:

    win32k!xxxEnableWndSBArrows 函数执行到关键代码之前,找到一条能够触发 user-mode callback 的调用路径,hook 掉对应的应用层函数,在其中 destroy tagSBINFO 对象。

    Aaron Adams给出了触发上面 user-mode callback 流程的部分代码,为其添加一个最基本的窗口,然后在WM_CREATE消息中创建scrollbarShow scrollbar Enable scrollbar,将其编译成程序。

    0x01 跟踪

    对该程序的执行过程跟踪,查看其是否按照预期的 user-mode callback 流程执行。发现在其 xxxGetColorObjects 函数中,流程走向了另一条流程 --> 调用 xxxGetControlBrush 函数。相关代码段:

    经查阅ReactOS,得知tagWnd.fnid=0x29A 含义:

    此时的 tagWnd 就是我们所创建的 SCROLLBAR 的,而SCROLLBARfnid的值一直都为0x29A

    所以此时有两个选择:

    1.想办法更改 fnid 的值

    2.寻找另一条触发user-mode callback的路径

    我选择了2:寻找 xxxGetControlBrush 函数内触发user-mode callback的调用路径。

    关于怎么判断 user-mode callback 是否可以触发,内核小王子Tajei Mandt很早就纰漏了相关知识:

    任何的user-mode callback流程最终内核到用户层的入口点都会是 nt!KeUserModeCallback

    函数名带有"xxx""zzz"前缀的一般都可以触发。

    。。。

    有趣的是,在寻找的过程中,结合动态调试发现 xxxGetControlBrush 又去调用 xxxDefWindowProc 函数了。那么是否可以回到上面的user-mode callback继续执行,但是在对 xxxLoadUserApiHook 函数跟踪之后,发现其并不能调用 xxxLoadHmodIndex

    同样的,两个选择,仍然选择2:放弃这条路径,返回到 xxxDefWindowProc 函数中寻找另一条路径。

    xxxDefWindowProc 调用 xxxLoadUserApiHook 附近有这样一段代码:

    虽然call ds:rva gapfnScSendMessage[r11+r10*8]看起来是动态确定,但在测试过程中,在xxxEnableWndSBArrows的调用流程中,其都是调用的 SfnDWORD 函数。

    这就是寻找的user-mode callback的调用流程了。

    0x02 确定

    目前确定的 user-mode callback 流程内核部分:

    NtUserEnableScrollBar--> xxxEnableScrollBar--> xxxEnableWndSBArrows--> xxxDrawScrollBar(第一次) -->xxxDrawSB2 -->xxxGetColorObjects -->xxxGetControlBrush -->xxxGetControlColor -->xxxDefWindowProc -->SfnDWORD(call ds:rva gapfnScSendMessage[r11+r10*8])--> KeUserModeCallback

    关于该流程对应的用户层函数,这个对应关系可以通过使用 Windbg 查看 peb.KernelCallbackTable 来确定:

    也可以直接利用IDA查看:

    Index为调用KeUserModeCallback 最后一个push的值:

    所以 win32k!SfnDWORD 对应的用户层函数为 user32!fnDWORD

    到此,整个user-mode callback流程便清晰了。

    0x03 行动

    接下来需要利用这次user-mode callbackhook 掉其流程中用户层函数 user32!fnDWORD,然后在 MyfnDWORD destroy scrollbar

    由于user32!fnDWORD调用频繁,所以要进行区分,为了把干扰和不确定因素降低,在 WM_CREATE消息中,hook user32!fnDWORD 便立即调用 EnableScrollBar

    测试过程中,在目标 user-mode callback 流程触发的 user32!fnDWORD 调用之前,没有一次 user32!fnDWORD 的调用,所以第一次的 MyfnDWORD 调用就是目标流程所触发的,此时 destroy scrollbar 就好了。

    0x04 效果

    调用 win32k!xxxDrawScrollBar 函数之前:

    之后:

    可以看到其已经从tagWnd中移除了。

    0x05 利用分析

    流程:

    [1] 创建大量的 tagPROPLIST 对象,为下一步挖坑做前提条件。

    [2] 释放掉一些 tagPROPLIST 对象,为 tagSBINFO 对象准备一些坑

    [3] CreateWindow(SCROLLBAR....)创建 tagSBINFO 对象,入坑

    [4] xxxEnableWndSBArrows 触发 user-mode callback 机制,在流程中用户层函数 USER32!_fnDWORD 中释放掉SCROLLBAR,再利用 user32!NtUserSetProp 来让 tagPROPLIST 占据刚释放掉的 SCROLLBAR 对象内存空间.

    [5]user-mode callback 流程返回到内核,来到关键代码段,利用其增加 tagPROPLIST.cEntries 大小。此时利用 SetProp() 可以获得对 tagPROPLIST 相邻内存进行越界写的能力。

    [6]利用这个越界写的能力,对事先布置在tagPROPLIST对象相邻 tagWnd.strName 进行操作,利用tagWnd.strName相关的函数 InternalGetWindowText() NtUserDefSetText() 可以分别获得任意地址读和任意地址写的能力。

    [7] Write-What-Where 完成,将 HalDispatchTable+4 修改为 shellcode 地址。到此剩下的工作和其他内核漏洞利用一样了。

    by:会飞的猫
    转载请注明:http://www.cnblogs.com/flycat-2016

  • 相关阅读:
    启xin宝app的token算法破解——frida篇(四)
    启xin宝app的token算法破解——token分析篇(三)
    启xin宝app的token算法破解——逆向篇(二)
    启xin宝app的token算法破解——抓包分析篇(一)
    关于企查查app sign研究
    企查查app (二)
    企查查app (完结)
    企查查app 初步探索
    天眼查sign 算法破解
    企查查app新增企业数据抓取
  • 原文地址:https://www.cnblogs.com/flycat-2016/p/5452963.html
Copyright © 2020-2023  润新知