欢迎来到 无奈人生 安全网 聚焦网络安全前沿资讯,精华内容,交流技术心得!

CVE-2017-0038:GDI32越界读漏洞从分析到Exploit

来源: 作者: 时间:2019-02-24 19:29 点击: 我要投稿
广告位API接口通信错误,查看德得广告获取帮助

在这篇文章中,我将首先对CVE-2017-0038这个GDI32.dll的Out-of-bound Read漏洞进行分析;随后,我将首先将分享用JS编写一个浏览器可用的Exploit,随后我将和大家一起来看一下这么做的一个限制(为什么无法用浏览器进行Info leak),也是在0patch文章中提到的0xFF3333FF到底是怎么回事;然后,我将和大家分享用C语言完成Exploit,一起来看看真正泄露的内存内容;最后我将把JS和C的Exploit放在github上和大家分享。
调试环境是:

Windows 10 x86_64 build 10240

IE 11

GDI32.dll Version 10.0.10240.16384

请大家多多交流,感谢阅读!
CVE-2017-0038 PoC与漏洞分析
如我在第一章分享的测试环境的图片,同样在0patch的文章中也能看到,在浏览器每次加载poc.emf的时候,都会产生不同的图片,这张图片只有左下角的一个小红点是固定不变的,其实除了左下角四个字节,其他的内容都是泄露的内存,这点在后面的分析中我们可以获得。
那么现在我们需要解决的一个问题就是如何加载这个图片,这样我们需要用JS的画布功能来完成对PoC的构造,并且成功加载PoC.emf。
首先,我们定义一个canvas画布,之后通过js的getElementById来获得画布对象,之后我们通过Image()函数来初始化image对象,加载poc.emf,最后,我们通过drawImage来读取poc.emf,将poc.emf打印在画布上。drawImage后两个参数是image在canvas画布上的坐标,这里我们设置为0,0。

完成构造后,我们稍微修改一下poc.emf的文件结构,然后打开IE11浏览器,通过Windbg附加进程,并且在gdi32!MRSETDIBITSTODEVICE::bPlay函数位置下断点,这个过程会在poc.emf映射在画布上时发生,允许js执行之后,Windbg命中函数入口。
0:022> x gdi32!MRSETDIBITSTODEVICE::bPlay
00007ff8`2a378730 GDI32!MRSETDIBITSTODEVICE::bPlay =
0:022> bp gdi32!MRSETDIBITSTODEVICE::bPlay
Breakpoint 0 hit
GDI32!MRSETDIBITSTODEVICE::bPlay:
00007ff8`2a378730 48895c2408      mov     qword ptr [rsp+8],rbx ss:00000034`93cef6f0={GDI32!MRMETAFILE::bPlay (00007ff8`2a320950)}
0:027> kb
RetAddr:ArgstoChild: Call Site
00007ff8`2a2ff592 : 00007ff8`2a320950 00007ff8`2a2f8ed1 00000000`00000008 ffffffff`8f010c40 : GDI32!MRSETDIBITSTODEVICE::bPlay//到达目标断点
00007ff8`2a2ff0a8 : 0000002c`8f00be8c 00000000`00000000 00000000`00000000 00000000`00000000 : GDI32!PlayEnhMetaFileRecord+0xa2
00007ff8`2a327106 : 00000034`92acee00 00007ff8`2a2ff8f3 00000034`90380680 00000034`93cef988 : GDI32!bInternalPlayEMF+0x858
00007ff8`08650a70 : 00007ff8`08061010 00007ff8`08061010 00000034`93cefa10 00000000`000000ff : GDI32!PlayEnhMetaFile+0x26//关键函数调用PlayEnhMetaFile
现在我们开始单步跟踪这个关键函数的执行流程,之后我放出整个函数的伪代码,相应的注释,我已经写在//后面,首先单步执行,会到达一处参数赋值,在64位系统中,参数是靠寄存器传递的。
0:027> p
GDI32!MRSETDIBITSTODEVICE::bPlay+0x1b:
00007ff8`2a37874b 488bd9          mov     rbx,rcx
0:027> r rcx
rcx=0000002c8f00be8c
0:027> dt vaultcli!EMRSETDIBITSTODEVICE 0000002c8f00be8c
   +0x000 emr              : tagEMR
   +0x008 rclBounds        : _RECTL
   +0x018 xDest            : 0n0
   +0x01c yDest            : 0n0
   +0x020 xSrc             : 0n0
   +0x024 ySrc             : 0n0
   +0x028 cxSrc            : 0n1
   +0x02c cySrc            : 0n1
   +0x030 offBmiSrc        : 0x4c
   +0x034 cbBmiSrc         : 0x28
   +0x038 offBitsSrc       : 0x74
   +0x03c cbBitsSrc        : 4
   +0x040 iUsageSrc        : 0
   +0x044 iStartScan       : 0
   +0x048 cScans           : 0x10
这里rcx传递的指针是MRSETDIBITSTODEVICE::bplay的第一个参数,这个参数是一个非常非常非常重要的结构体EMRSETDIBITSTODEVICE,正是对这个结构体中几个成员变量的控制没有进行严格的判断,从而导致了越界读漏洞的发生。
首先我们来看一下EMF文件格式。

[1] [2] [3] [4] [5] [6] [7]  下一页

在这篇文章中,我将首先对CVE-2017-0038这个GDI32.dll的Out-of-bound Read漏洞进行分析;随后,我将首先将分享用JS编写一个浏览器可用的Exploit,随后我将和大家一起来看一下这么做的一个限制(为什么无法用浏览器进行Info leak),也是在0patch文章中提到的0xFF3333FF到底是怎么回事;然后,我将和大家分享用C语言完成Exploit,一起来看看真正泄露的内存内容;最后我将把JS和C的Exploit放在github上和大家分享。
调试环境是:

Windows 10 x86_64 build 10240

IE 11

GDI32.dll Version 10.0.10240.16384

请大家多多交流,感谢阅读!
CVE-2017-0038 PoC与漏洞分析
如我在第一章分享的测试环境的图片,同样在0patch的文章中也能看到,在浏览器每次加载poc.emf的时候,都会产生不同的图片,这张图片只有左下角的一个小红点是固定不变的,其实除了左下角四个字节,其他的内容都是泄露的内存,这点在后面的分析中我们可以获得。

www.wnhack.com

那么现在我们需要解决的一个问题就是如何加载这个图片,这样我们需要用JS的画布功能来完成对PoC的构造,并且成功加载PoC.emf。
首先,我们定义一个canvas画布,之后通过js的getElementById来获得画布对象,之后我们通过Image()函数来初始化image对象,加载poc.emf,最后,我们通过drawImage来读取poc.emf,将poc.emf打印在画布上。drawImage后两个参数是image在canvas画布上的坐标,这里我们设置为0,0。

完成构造后,我们稍微修改一下poc.emf的文件结构,然后打开IE11浏览器,通过Windbg附加进程,并且在gdi32!MRSETDIBITSTODEVICE::bPlay函数位置下断点,这个过程会在poc.emf映射在画布上时发生,允许js执行之后,Windbg命中函数入口。
0:022> x gdi32!MRSETDIBITSTODEVICE::bPlay
00007ff8`2a378730 GDI32!MRSETDIBITSTODEVICE::bPlay =
0:022> bp gdi32!MRSETDIBITSTODEVICE::bPlay
Breakpoint 0 hit
GDI32!MRSETDIBITSTODEVICE::bPlay:
00007ff8`2a378730 48895c2408      mov     qword ptr [rsp+8],rbx ss:00000034`93cef6f0={GDI32!MRMETAFILE::bPlay (00007ff8`2a320950)}

本文来自无奈人生安全网


0:027> kb
RetAddr:ArgstoChild: Call Site
00007ff8`2a2ff592 : 00007ff8`2a320950 00007ff8`2a2f8ed1 00000000`00000008 ffffffff`8f010c40 : GDI32!MRSETDIBITSTODEVICE::bPlay//到达目标断点
00007ff8`2a2ff0a8 : 0000002c`8f00be8c 00000000`00000000 00000000`00000000 00000000`00000000 : GDI32!PlayEnhMetaFileRecord+0xa2
00007ff8`2a327106 : 00000034`92acee00 00007ff8`2a2ff8f3 00000034`90380680 00000034`93cef988 : GDI32!bInternalPlayEMF+0x858
00007ff8`08650a70 : 00007ff8`08061010 00007ff8`08061010 00000034`93cefa10 00000000`000000ff : GDI32!PlayEnhMetaFile+0x26//关键函数调用PlayEnhMetaFile
现在我们开始单步跟踪这个关键函数的执行流程,之后我放出整个函数的伪代码,相应的注释,我已经写在//后面,首先单步执行,会到达一处参数赋值,在64位系统中,参数是靠寄存器传递的。
0:027> p
GDI32!MRSETDIBITSTODEVICE::bPlay+0x1b:
00007ff8`2a37874b 488bd9          mov     rbx,rcx
0:027> r rcx
rcx=0000002c8f00be8c
0:027> dt vaultcli!EMRSETDIBITSTODEVICE 0000002c8f00be8c

本文来自无奈人生安全网


   +0x000 emr              : tagEMR
   +0x008 rclBounds        : _RECTL
   +0x018 xDest            : 0n0
   +0x01c yDest            : 0n0
   +0x020 xSrc             : 0n0
   +0x024 ySrc             : 0n0
   +0x028 cxSrc            : 0n1
   +0x02c cySrc            : 0n1
   +0x030 offBmiSrc        : 0x4c
   +0x034 cbBmiSrc         : 0x28
   +0x038 offBitsSrc       : 0x74

内容来自无奈安全网


   +0x03c cbBitsSrc        : 4
   +0x040 iUsageSrc        : 0
   +0x044 iStartScan       : 0
   +0x048 cScans           : 0x10
这里rcx传递的指针是MRSETDIBITSTODEVICE::bplay的第一个参数,这个参数是一个非常非常非常重要的结构体EMRSETDIBITSTODEVICE,正是对这个结构体中几个成员变量的控制没有进行严格的判断,从而导致了越界读漏洞的发生。
首先我们来看一下EMF文件格式。
www.wnhack.com

[1] [2] [3] [4] [5] [6] [7]  下一页

无奈人生安全网

。 (责任编辑:admin)
【声明】:无奈人生安全网(http://www.wnhack.com)登载此文出于传递更多信息之目的,并不代表本站赞同其观点和对其真实性负责,仅适于网络安全技术爱好者学习研究使用,学习中请遵循国家相关法律法规。如有问题请联系我们,联系邮箱472701013@qq.com,我们会在最短的时间内进行处理。