这是第5篇也是最后一篇,在无特权用户的环境中使Windows操作系统崩溃,这是我所知道的最后一个方法。以下是关于Windows DoS问题的上几篇文章:
今天要解释的错误可以在win32k!NtGdiGetDIBitsInternal
系统调用中找到,这是Windows最近所有版本的图形子系统的一部分,自从Windows的早期(至少Windows NT)开始就已经有了。这个漏洞在微软四月的补丁中进行了修补,它修复了Project Zero报告的内核漏洞(CVE-2017-0058)。当时也向供应商报告了DoS问题,但由于其严重程度不高,因此不符合安全公告的标准。
该漏洞函数的功能是基于设备描述表(Device Context),HBITMAP对象(HBITMAP object),启动扫描线程(starting scan line),扫描线程数(number of scan lines),BITMAPINFO头(BITMAPINFO header )和输出缓冲区(output buffer)来获取位图数据。这是通过以下存在于ReactOS源中的函数声明所示:
此声明显示,建议将最大的cjMaxBits
字节写入到pjBits
的输出存储区。在查看win32k.sys
函数的实际利用后,结论似乎是正确的,我们可以在这里找到以下代码片段:
如上所示,如果cjMaxBits
参数的值为非零,则优先于该GreGetBitmapBitsSize
例程的返回值。这也是有趣的事,在使用ProbeForWrite
调用执行pjBits
指针的初始验证之后,从pjBits
到pjBits
+ cjMaxBits-1
的用户模式存储区跨越被锁定,因此,除了PAGE_READWRITE
访问权限之外,它不能被取消映射或限制。通过这样做,内核确保对该区域的所有后续读/写访问是安全的(即不会触发异常),直到相应的 MmUnsecureVirtualMemory
调用,这反过来允许它跳过在系统调用的整个逻辑上设置非常广泛的try/except
块,或使用临时缓冲区。另一方面,逻辑非常依赖于被锁定在存储器中的特定数量的字节,因此,如果内核稍后尝试取消引用安全用户模式区域外的单个字节,有可能触发未处理的异常和伴随的蓝屏。
系统调用逻辑的核心在于内部的GreGetDIBitsInternal
函数:
这进一步调用GreGetDIBitsInternalWorker
。在该例程中,位图像素实际上复制到用户模式的输出缓冲区。一个特殊的情况是当呼叫者通过pbmi->bmiHeader.biCompression
字段对输出数据进行RLE
压缩时,它可以产生以下对EncodeRLE4
或EncodeRLE8
的额外调用:
这里,第二个参数是指向锁定的用户模式存储器的指针,第五个参数是可以写入的最大字节数。不一致是非常明显的:当NtGdiGetDIBitsInternal
使用cjMaxBits
(如果它不是零)作为最大缓冲区长度时,内部EncodeRLE
函数使用通过输入结构字段传递的另一个值(bmi-> bmiHeader.biSizeImage)。如果前者小于后者,并且所请求数据的大小足够大,则可以在受保护区域之外使得EncodeRLE
访问字节,从而产生所需的未处理的内核异常。值得注意的是,这种情况只能导致本地DoS,因为缓冲区溢出是线性的,并且缓冲区本身被保证位于初始ProbeForWrite
调用的ring-3
存储器中。
功能概念验证码很简单,可以在下面找到。它适用于Windows 7 32位(由于硬编码的系统调用号码),并且期望在test.bmp
文件中输入一个位图。我们使用了100 x 100 x 24bpp
的白色图像进行测试。错误的本质在第42行和第57行中可见 – 只有输出缓冲区的单个字节被保护,但是内核可能会写入多达0x10000000
。
启动程序为我们提供了一个蓝屏(DSoD)形式的预期结果:
完整的崩溃摘要如下:
KERNEL_MODE_EXCEPTION_NOT_HANDLED (8e) This is a very common bugcheck. Usually the exception address pinpoints the driver/function that caused the problem. Always note this address as well as the link date of the driver/image that contains this address. Some common problems are exception code 0x80000003. This means a hard coded breakpoint or assertion was hit, but this system was booted /NODEBUG. This is not supposed to happen as developers should never have hardcoded breakpoints in retail code, but ... If this happens, make sure a debugger gets connected, and the system is booted /DEBUG. This will let us see why this breakpoint is happening. Arguments: Arg1: c0000005, The exception code that was not handled Arg2: 8ef2584c, The address that the exception occurred at Arg3: 949e19a0, Trap Frame Arg4: 00000000 Debugging Details: ------------------ EXCEPTION_CODE: (NTSTATUS) 0xc0000005 - The instruction at 0x%08lx referenced memory at 0x%08lx. The memory could not be %s. FAULTING_IP: win32k!EncodeRLE8+1ac 8ef2584c c60300 mov byte ptr [ebx],0 TRAP_FRAME: 949e19a0 -- (.trap 0xffffffff949e19a0) ErrCode = 00000002 eax=000f1002 ebx=000f1000 ecx=00000004 edx=fb8d4f61 esi=00000064 edi=fb8d4efc eip=8ef2584c esp=949e1a14 ebp=949e1a40 iopl=0 nv up ei ng nz ac pe cy cs=0008 ss=0010 ds=0023 es=0023 fs=0030 gs=0000 efl=00010297 win32k!EncodeRLE8+0x1ac: 8ef2584c c60300 mov byte ptr [ebx],0 ds:0023:000f1000=?? Resetting default scope DEFAULT_BUCKET_ID: WIN7_DRIVER_FAULT BUGCHECK_STR: 0x8E PROCESS_NAME: usermode_oob_w CURRENT_IRQL: 2 ANALYSIS_VERSION: 6.3.9600.17237 (debuggers(dbg).140716-0327) x86fre LAST_CONTROL_TRANSFER: from 816f3dff to 8168f9d8 STACK_TEXT: 949e0f5c 816f3dff 00000003 c890b2ef 00000065 nt!RtlpBreakWithStatusInstruction 949e0fac 816f48fd 00000003 949e13b0 00000000 nt!KiBugCheckDebugBreak+0x1c 949e1370 816f3c9c 0000008e c0000005 8ef2584c nt!KeBugCheck2+0x68b 949e1394 816c92f7 0000008e c0000005 8ef2584c nt!KeBugCheckEx+0x1e 949e1930 81652996 949e194c 00000000 949e19a0 nt!KiDispatchException+0x1ac 949e1998 8165294a 949e1a40 8ef2584c badb0d00 nt!CommonDispatchException+0x4a 949e1a40 8eddaf69 fb8d4f61 ff0f0ffc 00000064 nt!KiExceptionExit+0x192 949e1b04 8edf8c05 00000028 949e1b5c 949e1b74 win32k!GreGetDIBitsInternalWorker+0x73e 949e1b7c 8ede39cc 06010327 0905032f 00000000 win32k!GreGetDIBitsInternal+0x21b 949e1c08 81651db6 06010327 0905032f 00000000 win32k!NtGdiGetDIBitsInternal+0x250 949e1c08 00e45ba6 06010327 0905032f 00000000 nt!KiSystemServicePostCall
谢谢阅读!
*作者:j00ru,MottoIN小编编译发布,