Professional Documents
Culture Documents
Corelabs-Breaking Out of VirtualBox Through 3D Acceleration-Francisco Falcon
Corelabs-Breaking Out of VirtualBox Through 3D Acceleration-Francisco Falcon
REcon 2014
PA G E
About me
• From Argentina.
PA G E 2
Agenda
PA G E 3
Agenda
PA G E 4
Motivations and related work
PA G E 5
Motivations
http://mista.nu/blog/2011/07/19/oracle-virtualbox-integer-
overflow-vulnerabilities/
PA G E 6
Related work
PA G E 7
An overview of VirtualBox
PA G E 8
An overview of VirtualBox
PA G E 9
An overview of VirtualBox
PA G E 1 0
VirtualBox Guest Additions
PA G E 1 1
VirtualBox Guest Additions
PA G E 1 2
They warned you!
https://www.virtualbox.org/manual/ch04.html#guestadd-3d:
PA G E 1 3
The Chromium library
PA G E 1 4
Chromium
• Client/server architecture.
PA G E 1 6
PA G E 1 7
Speaking the VBoxHGCM protocol
PA G E 1 8
Speaking the VBoxHGCM protocol
• No privileges needed for this at all; even guest users can open
the device!
PA G E 1 9
Speaking the VBoxHGCM protocol
BOOL rc = DeviceIoControl(hDevice,
VBOXGUEST_IOCTL_HGCM_CONNECT,
&info,
sizeof(info),
&info,
sizeof(info),
&cbReturned,
NULL);
PA G E 2 0
IoControl codes
PA G E 2 1
Connecting to the service
VBoxGuestHGCMConnectInfo info;
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);
PA G E 2 2
Speaking the Chromium protocol
PA G E 2 3
crOpenGL guest functions
• include/VBox/HostServices/VBoxCrOpenGLSvc.h has
definitions for Input Buffer types, available Chromium guest
functions and parameters count:
PA G E 2 4
Sending an HGCM Call message to the “VBoxSharedCrOpenGL”
service:
CRVBOXHGCMSETPID parms;
memset(&parms, 0, sizeof(parms));
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();
BOOL rc = DeviceIoControl(hDevice,
VBOXGUEST_IOCTL_HGCM_CALL, &parms,
sizeof(parms), &parms, sizeof(parms),
&cbReturned, NULL);
PA G E 2 5
HGCM_CALL handling
PA G E 2 7
Starting a Chromium communication
Final steps:
• Send a VBOXGUEST_IOCTL_HGCM_DISCONNECT message.
PA G E 2 8
Chromium Rendering Commands
PA G E 2 9
Rendering commands
PA G E 3 0
CRMessageOpcodes struct
PA G E 3 1
Rendering commands
SHCRGL_GUEST_FN_WRITE_BUFFER:
PA G E 3 5
The Vulnerabilities
PA G E 3 6
CVE-2014-0981, CVE-2014-0982
void
crNetDefaultRecv( CRConnection *conn, CRMessage *msg,
unsigned int len ){
[...]
switch (pRealMsg->header.type) {
[...]
case CR_MESSAGE_WRITEBACK:
crNetRecvWriteback( &(pRealMsg->writeback) );
return;
case CR_MESSAGE_READBACK:
crNetRecvReadback( &(pRealMsg->readback), len );
return;
[...]
PA G E 3 7
Network pointers
PA G E 3 8
PA G E 3 9
Vulnerability Nº 1: CVE-2014-0981
PA G E 4 0
CVE-2014-0981
static void
crNetRecvReadback( CRMessageReadback *rb, unsigned int
len )
{
int payload_len = len - sizeof( *rb );
int *writeback;
void *dest_ptr;
crMemcpy( &writeback, &(rb->writeback_ptr), sizeof(
writeback ) );
crMemcpy( &dest_ptr, &(rb->readback_ptr), sizeof(
dest_ptr ) );
(*writeback)--;
crMemcpy( dest_ptr, ((char *)rb) + sizeof(*rb),
payload_len );
}
PA G E 4 1
CVE-2014-0981
PA G E 4 2
Vulnerability Nº 2: CVE-2014-0982
PA G E 4 3
CVE-2014-0982
static void
crNetRecvWriteback( CRMessageWriteback *wb )
{
int *writeback;
crMemcpy( &writeback, &(wb->writeback_ptr), sizeof(
writeback ) );
(*writeback)--;
}
PA G E 4 4
CVE-2014-0982
PA G E 4 5
Vulnerability Nº 3: CVE-2014-0983
PA G E 4 6
CVE-2014-0983
switch( *unpack_opcodes ) {
[...]
case CR_VERTEXATTRIB4NUBARB_OPCODE:
crUnpackVertexAttrib4NubARB(); break;
[...]
PA G E 4 7
CVE-2014-0983
void SERVER_DISPATCH_APIENTRY
crServerDispatchVertexAttrib4NubARB( GLuint index, GLubyte x,
GLubyte y, GLubyte z, GLubyte w )
{
cr_server.head_spu->dispatch_table.VertexAttrib4NubARB( index,
x, y, z, w );
cr_server.current.c.vertexAttrib.ub4[index] = cr_unpackData;
}
PA G E 4 9
CVE-2014-0983
• CVE-2014-0983: VirtualBox
crServerDispatchVertexAttrib4NubARB Memory Corruption
Vulnerability
PA G E 5 0
CVE-2014-0983
PA G E 5 1
The Fixes
PA G E 5 2
The fixes
#ifdef IN_GUEST
case CR_MESSAGE_WRITEBACK:
crNetRecvWriteback( &(pRealMsg->writeback) );
[...]
case CR_MESSAGE_READBACK:
crNetRecvReadback( &(pRealMsg->readback), len );
#endif
PA G E 5 3
The fixes
PA G E 5 4
Exploitation
PA G E 5 5
Exploitation
PA G E 5 6
Exploitation
void SERVER_DISPATCH_APIENTRY
crServerDispatchVertexAttrib4NubARB( GLuint index, GLubyte x,
GLubyte y, GLubyte z, GLubyte w )
{
cr_server.head_spu->dispatch_table.VertexAttrib4NubARB( index,
x, y, z, w );
cr_server.current.c.vertexAttrib.ub4[index] = cr_unpackData;
}
PA G E 5 9
Exploitation
PA G E 6 0
Exploitation
PA G E 6 1
Need to bypass ASLR?
PA G E 6 2
Exploitation
PA G E 6 3
Can’t rely on non-ASLR modules
PA G E 6 4
Exploitation with full ASLR bypass
PA G E 6 5
“Infoleaks are made,
not found”
- Halvar Flake -
PA G E 6 6
Exploitation with full ASLR bypass
typedef struct {
[...]
int numClients;
CRClient *clients[CR_MAX_CLIENTS];
[...]
} CRServer;
PA G E 6 7
Exploitation with full ASLR bypass
PA G E 6 8
Exploitation with full ASLR bypass
struct CRConnection {
[...]
uint8_t *pHostBuffer;
uint32_t cbHostBuffer;
[...]
};
PA G E 6 9
Exploitation with full ASLR bypass
PA G E 7 0
PA G E 7 1
PA G E 7 2
PA G E 7 3
Exploitation with full ASLR bypass
PA G E 7 4
Exploitation with full ASLR bypass
PA G E 7 5
Exploitation with full ASLR bypass
PA G E 7 6
PA G E 7 7
Exploitation with full ASLR bypass
PA G E 7 8
Infoleak
*pcbBuffer = pClient->conn->cbHostBuffer;
if (*pcbBuffer) {
CRASSERT(pClient->conn->pHostBuffer);
crMemcpy(pBuffer, pClient->conn->pHostBuffer, *pcbBuffer);
pClient->conn->cbHostBuffer = 0;
}
PA G E 7 9
Infoleak
PA G E 8 0
Leaking what?
PA G E 8 1
Leaking what?
void SERVER_DISPATCH_APIENTRY
crServerDispatchBarrierExecCR(GLuint name ){
[...]
barrier =
(CRServerBarrier*)crHashtableSearch(cr_server.barriers, name);
[...]
barrier->waiting[barrier->num_waiting++] = cr_server.run_queue;
[...]
}
PA G E 8 2
Leaking what?
• Since we fully control the value of the barrier pointer, this line
means that we can also fully control the address where
cr_server.run_queue will be stored by crafting a fake
CRServerBarrier at a known address:
barrier->waiting[barrier->num_waiting++] = cr_server.run_queue;
PA G E 8 3
PA G E 8 4
PA G E 8 5
PA G E 8 6
Bye bye ASLR!
PA G E 8 7
Live Demo!
PA G E 8 8
Future Work and Conclusions
PA G E 8 9
Future Work
PA G E 9 0
Conclusions
PA G E 9 1
Contact info
@fdfalcon
ffalcon@coresecurity.com
PA G E 9 2
Questions?
PA G E 9 3
Thank you!
PA G E 9 4