“cerber”敲诈者对CVE-2016-7255漏洞利用分析

时间:2017-03-27 12:44 来源:武松娱乐整理 字体:[ ] 评论:
 0x1 前言 “cerber”敲诈者对CVE-2016-7255漏洞利用分析。360互联网安全中心近日捕获到一款“ceber”敲诈者木马变种,该变种与其他“ceber”敲诈者木马变种在代码执行流程上并没有太大区别。唯一值得注意的是,该木马利用CVE-2016-7255权限提升漏洞对自身进行提权。本文将分析该敲诈者对CVE-2016-7255权限提升漏洞的利用过程。 0x2 漏洞细节 出问题的代码位于win32k!xxxNextWindow中,由于缺少必要的检查直接将tagWND+0xC0成员偏移0x28对应地址中的值与4进行或操作,而tagWND+0xC0又是可控的,从而导致了任意地址写。存在漏洞的代码如下所示。 \ 图1 存在漏洞的代码 图中v12表示的就是tagWND结构体,该结构体如下所示(省略掉部分)。 \ 图2 tagWND结构体 从上图可以看出,tagWND+0xC0对应的是spmenu成员,如果存在用户态函数可以对该成员进行赋值,即可触发任意地址写。对于32位系统而言,可以直接调用SetWindowLong函数,SetWindowLong函数会调用内核态函数NtUserSetWindowLong完成此功能;对于64位系统而言,不存在可以利用的用户态函数,但是可以使用syscall的方式调用内核态函数NtUserSetWindowLong或函数NtUserSetWindowLongPtr来完成这项工作。(以下介绍的是NtUserSetWindowLong函数,NtUserSetWindowLongPtr函数执行流程相同)。 NtUserSetWindowLong函数只是一层外壳,它会将参数传递给xxxSetWindowLong并调用它,该函数如下所示。 \ 图3 xxxSetWindowLong函数 在该函数中会对传入的nIndex进行判断,并根据nIndex的值执行对应的操作。对于nIndex的值为-16,-20,-12,-21的情况,会调用xxxSetWindowData函数进行处理。如下所示。 \ 图4 调用xxxSetWindowData函数进行处理 该函数接收xxxSetWindowLong的参数,当nIndex参数为-12(GWL_ID),且所操作窗口的style为WS_CHILD或WS_CHILDWINDOW(0x40000000)时,会将所操作窗口tagWND结构体的spmenu成员的值设为dwNewLong。如下图所示。 \ 图5 触发漏洞的位置 由于dwNewLong是调用NtUserSetWindowLong函数时传递的参数,用户态进程可以利用syscall随意控制它。而win32k!xxxNextWindow函数会对spmenu+0x28的成员与4进行或操作,因此触发了任意地址写。 0x3 漏洞利用分析 从漏洞细节中可以看出,用户态进程拥有对tagWND结构体的spmenu成员的修改权,该成员是个tagMENU结构体,结构体定义如下所示。 \ 图6 tagMENU结构体 不难看出,xxxNextWindow函数修改的值就是spmenu的fFlags成员(偏移0x28),由于对该成员进行与0x4的或操作,因此该漏洞只能修改1bit大小的区域。 只能修改1bit表面上看起来貌似没有多大价值,不过该木马变种并非只把目光集中在这1bit上,而是转移到了tagWND结构体的cbWNDExtra成员,该成员表示的是窗口附加数据的大小。如果能够通过修改窗口附加数据的大小来覆盖关键地址,之后再利用其他方式写入数据,就可达到完美利用。 那么要完成对cbWNDExtra成员的写操作,就必须获取cbWNDExtra成员的地址或者是cbWNDExtra成员相对于某个已知地址的偏移。除外还必须获取附加数据的地址或者是相对于某个已知地址的偏移,以便之后进行计算与写入。对于获取cbWNDExtra成员的地址,该木马创建了两个窗口“ExtraWnd1”和“ExtraWND2”,而这两个窗口的不同之处在于其窗口类的cbWndExtra成员,该成员正好对应tagWND的 cbWNDExtra成员。程序将两个窗口类的cbWndExtra成员分别赋值为0x118和0x130,如下图所示。 \ 图7 创建两个窗口 创建窗口之后就是获取cbWNDExtra成员在tagWND结构体中的偏移,使用的是HMValidateHandle函数。该函数并未在用户态中导出,不过有个用户态函数IsMenu调用了它。木马通过判断IsMenu中相关字节码的位置获取HMValidateHandle的地址。 \ 图8 利用字节码定位函数 HMValidateHandle函数会泄露tagWND结构体的内容,因此木马很容易就能定位cbWNDExtra成员在tagWND结构体中的偏移。为了保险起见,木马判断两个窗口tagWND结构体的cbWNDExtra成员的偏移,当两个cbWNDExtra为注册窗口类时设置的值(0x118和0x130)且偏移相同时才说明该偏移有效。 \ 图9 确定cbWndExtra成员的偏移 在获取cbWNDExtra成员的偏移之后,该获取附加数据的偏移了。附加数据在内核态中是紧跟在tagWND结构体之后的,而SetWindowLong函数可以向窗口写入附加数据,nIndex表示的是写入的初始偏移。该木马调用SetWindowLong函数向附加数据区域的开头写入0x31323334,之后再次调用HMValidateHandle函数并通过比较偏移的内容是否为0x31323334来确定附加数据的偏移。 \ 图10 确定附加数据的偏移 确定关键的两处偏移之后,就该进行漏洞的触发了。由于触发漏洞的窗口必须设置为WS_CHILD或WS_CHILDWINDOW(0x40000000)类型。因此此处调用SetWindowLong函数设置窗口的style。 \ 图11 设置窗口style 然后就是对tagWND结构体的spmenu成员赋值,此时调用的是以GWL_ID做为nIndex参数的NtUserSetWindowLong函数(或NtUserSetWindowLongPtr函数)。该木马会首先确定程序所处的系统环境,如果是32位系统则直接调用SetWindowLong函数完成工作;如果是64位系统,则在用户态中使用syscall并赋予特殊的ID调用NtUserSetWindowLongPtr函数。32位系统环境下和64位系统环境下调用方式如图所示。 图12 32位系统下通过调用SetWindowLong函数调用NtUserSetWindowLong \ 图13 64位系统使用syscall方式调用NtUserSetWindowLongPtr函数
顶一下(0) 踩一下(0)
Top_arrow
武松娱乐注册