Windows 内核漏洞利用之UAF:CVE-2015-0057
Introduction
这次是内核中一个 uaf 漏洞的学习,刚好看到 wjllz 师傅的在看雪上的 windows 内核系列文章,就也一起分析了 cve-2015-0057 这个洞(膜一发 wjllz 师傅 tql !!!),这篇写的水平肯定也没有 wjllz 师傅的好,也不太会讲故事,权当自己学习过程的记录,希望也能够帮助到你,如有错误多谢指正。
首先这次的漏洞分析也是参考已有的分析资料来学习,已有的资料包括:
漏洞发现者 Udi Yavo of enSilo 的 分析
Ncc group 详细利用分析的 writeup
keenjoy98 老师在 blackhat 上的议题 A New CVE-2015-0057 Exploit Technology
win8.1 x64 下完整利用 [MS15-010 / CVE-2015-0057] EXPLOITATION
刚开始这样做不可避免,全靠自己从分析 patch 到 poc 再到 exploit 的话水平还达不到,不过这是下一阶段的目标,我会努力往这方面靠。说完了让我们开始专注漏洞,主要涉及的知识点有:
用户态回调函数的使用
堆风水
win8.1 堆头修复
win8.1 smep 绕过
提权 shellcode
The bug
漏洞出现在内核的 GUI 组件中,也就是 win32k.sys 模块,之前从来没有了解过 win32k 有关的用户态回调函数的利用,不过这里有篇相关的 paper 可以参考,帮助我们熟悉 win32k.sys。分析资料中直接给出了漏洞所在位置,也可以自己尝试从 patch 分析一波,我尝试对比了一下 patch 版本和原版本的 win32k.sys,有几十处函数有改动,没有任何思路遂放弃。从资料中找到漏洞代码,漏洞位置在 win32k!xxxEnableWndSBArrows,抛去如何定位漏洞的部分(因为不会 🙁 233),让我们直接理解漏洞原理:
Unpatched
以上代码是未经修补的漏洞代码,在适当的情况下 win32k!xxxDrawScrollBar 可以触发一个用户态调用让 tagSBINFO 对象指针即 rbx 被释放掉,而之后以上代码又使用了释放后内存中的值。简单来说就是某种情况下这个函数会触发一个函数回调,而我们可以控制这个函数回调,运行我们指定的代码。
Patched
在 patched 的版本中,使用 tagSBINFO 指针之前设置了一道检查,这样导致用户控制的回调函数在设置检查的情况下无法被执行,用户的影响被消除了。
那么怎么控制这个回调函数?以及我们需要执行什么样的代码?这就需要完全理解了整个函数的作用以及其内部执行逻辑之后才能回答这个问题。这部分在 Ncc group 的 writeup 和 udi 的 blog 中有详细的解释,一起来看一下。
漏洞所在位置是跟窗体滚动条相关的,而每个窗体都设置了水平和垂直的滚动条 – scrollbar,参考 ReactOS 找到结构体定义:
typedef struct tagSBDATA
{
INT posMin;
INT posMax;
INT page;
INT pos;
} SBDATA, *PSBDATA;
typedef struct tagSBINFO
{
INT WSBflags;
SBDATA Horz;
SBDATA Vert;
} SBINFO, *PSBINFO;
每个 SBDATA 结构都定义了相关的 Scrollbar 的属性,WSBflags 按照设置了多少比特位来决定 scrollbar 的状态属性。而漏洞所在的函数 win32k!xxxEnableWndSBArrows 则是通过这些结构体所描述的信息来设置相应的滚动条属性,参考 NtUserEnableScrollBar 函数,它的函数定义如下:
BOOL xxxEnableWndSBArrows(HWND hWnd, UINT wSBflags, UINT wArrows);
hWnd 是窗体句柄,wSBflags 决定 scrollbar 的属性,wArrows 描述滚动条箭头的属性。
函数总体逻辑可以分为三部分,第一部分是分配新的 scrollbar。函数开始时会检查窗体是否包含滚动条信息,如果需要会重新分配一个 scrollbar 结构体。
相关的符号在 win7 版本中有保留,可以用 windbg 查看,从代码层面来看,函数读取 pSBInfo 值,也就是 tagSBINFO 结构,并且判断是否位空指针,如果该值为空而 wArrows 参数不为空,那么就会给窗体分配一个 tagSBINFO 结构,scrollbar 属性相关的 bit 位设置为 0。否则就沿用已有的 tagSBINFO 结构中 scrollbar 属性的信息。
在看这部分逆向代码的时候对寄存器所保存的参数有点疑惑,查了下发现 win 平台下函数调用参数传递和之前接触的 linux 平台略有不同(如果有和我一样的困惑的同学可以查看相关链接)。
第二部分是设置滚动条的状态,相关参数值的类型的定义在 WinUser.h 中查看,以及 msdn 上的文档,wSBflags 参数值类型:
#define SB_HORZ 0 设置禁用水平滚动条
#define SB_VERT 1 设置禁用垂直滚动条
#define SB_CTL 2 表示滚动条是滚动条控件 // 具体什么作用不清楚
#define SB_BOTH 3 设置同时禁用水平和垂直滚动条
参数 wArrows 则设置滚动条的箭头是否可用,被设置位表示不可用:
#define ESB_ENABLE_BOTH 0x0000
#define ESB_DISABLE_BOTH 0x0003
#define ESB_DISABLE_LEFT 0x0001
#define ESB_DISABLE_RIGHT 0x0002
#define ESB_DISABLE_UP 0x0001
Introduction
这次是内核中一个 uaf 漏洞的学习,刚好看到 wjllz 师傅的在看雪上的 windows 内核系列文章,就也一起分析了 cve-2015-0057 这个洞(膜一发 wjllz 师傅 tql !!!),这篇写的水平肯定也没有 wjllz 师傅的好,也不太会讲故事,权当自己学习过程的记录,希望也能够帮助到你,如有错误多谢指正。
首先这次的漏洞分析也是参考已有的分析资料来学习,已有的资料包括:
漏洞发现者 Udi Yavo of enSilo 的 分析
Ncc group 详细利用分析的 writeup
keenjoy98 老师在 blackhat 上的议题 A New CVE-2015-0057 Exploit Technology
win8.1 x64 下完整利用 [MS15-010 / CVE-2015-0057] EXPLOITATION
刚开始这样做不可避免,全靠自己从分析 patch 到 poc 再到 exploit 的话水平还达不到,不过这是下一阶段的目标,我会努力往这方面靠。说完了让我们开始专注漏洞,主要涉及的知识点有:
用户态回调函数的使用
堆风水
win8.1 堆头修复
win8.1 smep 绕过
提权 shellcode
The bug
漏洞出现在内核的 GUI 组件中,也就是 win32k.sys 模块,之前从来没有了解过 win32k 有关的用户态回调函数的利用,不过这里有篇相关的 paper 可以参考,帮助我们熟悉 win32k.sys。分析资料中直接给出了漏洞所在位置,也可以自己尝试从 patch 分析一波,我尝试对比了一下 patch 版本和原版本的 win32k.sys,有几十处函数有改动,没有任何思路遂放弃。从资料中找到漏洞代码,漏洞位置在 win32k!xxxEnableWndSBArrows,抛去如何定位漏洞的部分(因为不会 🙁 233),让我们直接理解漏洞原理: 无奈人生安全网
Unpatched
以上代码是未经修补的漏洞代码,在适当的情况下 win32k!xxxDrawScrollBar 可以触发一个用户态调用让 tagSBINFO 对象指针即 rbx 被释放掉,而之后以上代码又使用了释放后内存中的值。简单来说就是某种情况下这个函数会触发一个函数回调,而我们可以控制这个函数回调,运行我们指定的代码。
Patched
在 patched 的版本中,使用 tagSBINFO 指针之前设置了一道检查,这样导致用户控制的回调函数在设置检查的情况下无法被执行,用户的影响被消除了。
那么怎么控制这个回调函数?以及我们需要执行什么样的代码?这就需要完全理解了整个函数的作用以及其内部执行逻辑之后才能回答这个问题。这部分在 Ncc group 的 writeup 和 udi 的 blog 中有详细的解释,一起来看一下。
漏洞所在位置是跟窗体滚动条相关的,而每个窗体都设置了水平和垂直的滚动条 – scrollbar,参考 ReactOS 找到结构体定义:
typedef struct tagSBDATA
{
INT posMin;
INT posMax;
INT page;
INT pos;
} SBDATA, *PSBDATA;
typedef struct tagSBINFO
{
INT WSBflags;
SBDATA Horz;
SBDATA Vert;
} SBINFO, *PSBINFO;
每个 SBDATA 结构都定义了相关的 Scrollbar 的属性,WSBflags 按照设置了多少比特位来决定 scrollbar 的状态属性。而漏洞所在的函数 win32k!xxxEnableWndSBArrows 则是通过这些结构体所描述的信息来设置相应的滚动条属性,参考 NtUserEnableScrollBar 函数,它的函数定义如下:
BOOL xxxEnableWndSBArrows(HWND hWnd, UINT wSBflags, UINT wArrows);
hWnd 是窗体句柄,wSBflags 决定 scrollbar 的属性,wArrows 描述滚动条箭头的属性。
函数总体逻辑可以分为三部分,第一部分是分配新的 scrollbar。函数开始时会检查窗体是否包含滚动条信息,如果需要会重新分配一个 scrollbar 结构体。
相关的符号在 win7 版本中有保留,可以用 windbg 查看,从代码层面来看,函数读取 pSBInfo 值,也就是 tagSBINFO 结构,并且判断是否位空指针,如果该值为空而 wArrows 参数不为空,那么就会给窗体分配一个 tagSBINFO 结构,scrollbar 属性相关的 bit 位设置为 0。否则就沿用已有的 tagSBINFO 结构中 scrollbar 属性的信息。
在看这部分逆向代码的时候对寄存器所保存的参数有点疑惑,查了下发现 win 平台下函数调用参数传递和之前接触的 linux 平台略有不同(如果有和我一样的困惑的同学可以查看相关链接)。
第二部分是设置滚动条的状态,相关参数值的类型的定义在 WinUser.h 中查看,以及 msdn 上的文档,wSBflags 参数值类型:
#define SB_HORZ 0 设置禁用水平滚动条
#define SB_VERT 1 设置禁用垂直滚动条
#define SB_CTL 2 表示滚动条是滚动条控件 // 具体什么作用不清楚
#define SB_BOTH 3 设置同时禁用水平和垂直滚动条 copyright 无奈人生
参数 wArrows 则设置滚动条的箭头是否可用,被设置位表示不可用:
#define ESB_ENABLE_BOTH 0x0000
#define ESB_DISABLE_BOTH 0x0003
#define ESB_DISABLE_LEFT 0x0001
#define ESB_DISABLE_RIGHT 0x0002
#define ESB_DISABLE_UP 0x0001
内容来自无奈安全网
[1] [2] [3] [4] [5] [6] [7] [8] 下一页
www.wnhack.com