CVE-2019-0808利用里的几处数学问题

CVE-2019-0808是2019年4月google披露的一次使用chrome 0day进行攻击时用于绕过chrome沙箱限制的windows权限提升漏洞,本文并不对具体的漏洞原因及利用技术进行分析,exodusintel的文章中已经分析得很清楚,这里只是对该漏洞中利用的几处数学问题进行一些解释。

该漏洞的原理如下图所示(直接借用360核心安全分析中的图),具体来说即当用户调用对应的NtUserMNDragOver函数时,在内核中将最终调用函数xxxMNDragOver,此时如果检查到对应的MourseMove消息,将导致xxxMNDragOver中的消息处理函数xxxCallHandleMenuMessages进入到xxxMNMouseMove中,xxxMNMouseMove函数中调用函数xxxMNFindWindowFromPoint,在函数xxxMNFindWindowFromPoint会通过函数SendMessage发送WM_MN_FINDMENUWINDOWFROMPOINT消息,此时如果攻击者在user层通过SetWindowsHook的方式劫持的对应的WM_MN_FINDMENUWINDOWFROMPOINT消息,并返回一个空的hmenu,此时该空的hmenu将通过函数xxxMNFindWindowFromPoint返回,并传递给xxxMNMouseMov下的xxxMNUpdateDraggingInfo,xxxMNUpdateDraggingInfo最终在通过MNGetpItem函数返回该空hmenu时将导致崩溃。

其本质上就是函数xxxMNFindWindowFromPoint对用户层返回的数据没有做校验的原因。

 

在利用的hook函数中,当监控到对应的漏洞ox1eb消息时,调用函数SebMenuproc,该函数中实现对于null地址内存的布局。

 

SebMenuproc中我们首先通过wParam获取到至关重要的pPopupMenu,需要+0x10,之后通过这个值配合pramary cbwndextr,计算出0x34中的值并写入,设置0x20处的值为0xffffffff,设置0x4c出的值为((0x100000180 - addressToWriteTo) / 0x6C)。

具体如下图(借用exodusintel的布局图)

 

看到这个地方我们会有两个疑问

  1. ((addressToWrite + 0x6C) - ((pPopupAddressInCalculations * 0x6C) + 0x4))中(addressToWrite + 0x6C)为啥要+0x6c
  2. 420行处(偏移0x4c处)这么设置的原因。

我们首先来看看第二个的问题,实际上在xxxMNUpdateDraggingInfo中执行完第一个MNGetpItem后,要执行到之后xxxMNSetGapState触发函数,中间是有判断要求的。

通过反汇编模式可以看得更清楚,简单来说,第一个MNGetpItem执行完之后,会获取0x4c处的值将其*0x6c,并以此加上0x34处的值,再加上0x28,通过这个值作为指针获取其中的值来进行一系列判断(下图中的ecx),为了保证最终进入到后面的漏洞函数,一个简单的思路就是将这个最终计算的指针指向的值设置为一个巨大的值。

*((null + 0x34) + (null + 0x4c) * 0x6c +0x28)

 

关键的位置如下所示

 

从公式可知,0x34,0x4c都是我们可控的,因此这个指针的值也是我们可控,问题是我们需要将这个指针指向何处,要知道我们能控制的地址实际上只有null附近的地址,因此我们将我们指针的位置控制在0x120到0x180之间,将这里附近的值都设置为f0,从而保证其最终获取的值都为0xf0f0f0f0,为什么不设置为0xffffffff,因为之后还会有一些值的操作,0xffffffff会导致直接上益,从而变成一个很小的值

*((null + 0x34) + (null + 0x4c) * 0x6c +0x28)

之所以用0x100000180,注意这里是9位,这样实际的计算中*((null + 0x34) + (null + 0x4c) * 0x6c +0x28)获取的值将为0x100000180,x86下将直接去掉最高位,最终的值为0x180,从而确保一定获取到0xf0f0f0f0。

第二个疑问,为什么需要+0x6c,这里就是实际漏洞触发有关了,我们最终需要调用红框中的MNGetpItem,通过其返回值来修改最终的cbwndextra,而其参数注意并不是a2,而是a2-1

 

因此我们的计算公式需要在a2的位置-1,从而需要按照第二处的公式计算,

第一

addressToWrite = *(_DWORD *)(v2 + 0x34) + 0x6C * a2(pPopupAddressInCalculations);

addressToWrite-4 = *(_DWORD *)(v2 + 0x34) + 0x6C * a2(pPopupAddressInCalculations);

addressToWrite-4-0x6C * a2(pPopupAddressInCalculations) = *(_DWORD *)(v2 + 0x34)

addressToWrite-(0x6C * a2(pPopupAddressInCalculations) + 4) = *(_DWORD *)(v2 + 0x34)

第二

addressToWrite-(0x6C * a2(pPopupAddressInCalculations-1) + 4) = *(_DWORD *)(v2 + 0x34)

addressToWrite+0x6C -((pPopupAddressInCalculations * 0x6C) + 0x4)) = *(_DWORD *)(v2 + 0x34)

一次实际的调试如下所示

设置好对应的null地址之后,最终如下所示:

 

CVE-2018-0808在利用是还是非常经典的,从一位写转化为全局读写,最终实现代码执行,这里强烈推荐exodusintel的文章,各个利用分析的细节都很清楚,这里只是将我分析中遇到的两个问题进行分享。

参考链接

https://security.googleblog.com/2019/03/disclosing-vulnerabilities-to-protect.html

https://blog.exodusintel.com/2019/05/17/windows-within-windows/

http://blogs.360.cn/post/RootCause_CVE-2019-0808_CH

猜你喜欢

转载自www.cnblogs.com/goabout2/p/11255693.html