GreAnimatePalette 空指针引用

contents

  • 前言
  • 空指针引用
  • 附件下载
  • 0x00: 前言

    在 Windows Vista 的时候,微软将打印机驱动从内核态移动到了用户态,这样可以解决相当一部分打印机驱动导致的漏洞,因为第三方开发的驱动的安全性有待提高.

    这样做好处的显而易见的,减少了许多第三方开发的打印机驱动的漏洞,但是也带来了弊端,通过Hook图形设备驱动接口 Or 打印机驱动接口,为安全研究员们扩展了一个新的攻击面,这就有些得不偿失了.

    因此本系列文章将从简入深的讲解多个由安全性提高转化成安全性”降低”的多个漏洞,其中包含但不限于(空指针引用,内存越界读写等)

    0x01: 空指针引用

    创建图形驱动程序必须要创建的函数如下



    这些函数是必须要创建的,如果为空,则在内核中创建对象不可能成功.

    通过 CreateDC 指定名称可以创建一个关于打印机设备的上下文环境,我们阅读源码后发现他会回调打印机 DDI 函数中的 DrvEnablePDEV ,并传递了多个重要数据结构,我们可以 Hook DrvEnablePDEV 函数来修改函数执行过后的结果,当其返回内核时,我们即可控制函数的执行流程了.



    不过在早期的 Windows 中,安全性并没有现在这么高,很多安全保护都是不存在的,就比如说空指针引用,我们就可以利用他来达到本地权限提升的目的

    GreAnimatePalette函数分析:

    AnimatePalette 函数置换指定逻辑调色板中的颜色项,在Win32k中该函数调用了实现函数 XEPALOBJ::ulAnimatePalette 来实现功能.

    但是在早期的Windows7中,该函数存在空指针引用漏洞,利用该漏洞我们可以达到本地权限提升的目的.

    我们可以使用用户态包装好的 AnimatePalette 函数来调用到 GreAnimatePalette 函数或者从ShaDownSSDT中搜素编号调用 NtGdiDoPalette 函数都可以执行到 XEPALOBJ::ulAnimatePalette.

    由于该函数是 XEPALOBJ 类中的函数,所以存在一个This指针,通常为ecx,此处也是一样,ecx保存着指向 PALETTE 结构的指针.

    该函数首先判断了传入的iStart是否大于颜色项的总个数,如果大于则结束函数

    接着判断iStart + cEntry 是否大于 cEntries,如果大于则将cEntry设置为cEntries-iStart.

    判断是否为某个DC中的调色板,判断Palette.cRefhpal是否存在,不存在则跳出循环

    判断Palete->GdiInfo.flRaster & RC_PALETTE是否为真,如果为假,则跳出循环

    最后判断 Palete->ptransCurrent 是否存在,如果不存在则跳出循环,存在则初始化两个局部变量,一个指向 Palete->ptransCurrent ,另外一个指向 Palete->ptransCurrent->ajVector[iStart] .

    下面是个循环,大致意思就是从函数的第三个参数 (ppalSrc) 复制内容到 Palette.pFirstColor[iStart] 中,并且判断 Palete->ptransCurrent 是否为真,如果为真则读取 Palete->ptransCurrent->ajVector[iStart] 处的内容当作偏移,来写入到 palSurf.pFirstColor[Palete->ptransCurrent->ajVector[iStart]] 中. (写入内容为*ppalSrc)

    结束循环后,函数会再次判断 Palete->ptransCurrent 是否存在, Palete->GdiInfo.flRaster & RC_PALETTE 是否为真以及判断 Palete->fs& PDEV_DISABLED 是否为假,如果为False,则会从 PEDV->apfn[] 表中寻找需要的函数函数并跳转执行.

    是不是很熟悉 PPFNDRV ,这个上文是不是回调过 DrvEnablePDEV ,这里是要回调 DrvSetPalette 吗?

    理论上来说是的,但是实际上来说,上文保存了一个必须创建图形驱动程序必须要创建的函数表,其中并没有 DrvSetPalette ,因为这个函数是可选的.

    问题来了,如果不存在这个函数,但是函数调用了他,会出现什么问题呢?

    答对了,空指针引用,在老版本 Windows 中并没有对函数指针是否正确进行验证,所以如果函数指针指向0,依然会Call过去,这样就造成了一个空指针引用的漏洞,我们只要在0处申请内存,填充代码,在同一进程上下文中即可触发该引用,让操作系统执行我们的代码.

    附件下载:

    Word:因为你安全了,所以你危险了(空指针引用).doc

    Poc:Null-DDI.zip

    2020/03/22 17:10

    Return HomePage