Chromium은 Remote rendering을 하게 해주는 OpenGL기반 3D 그래픽 라이브러리 이며, 클라이언트/서버 구조로 되어 있음
HGCM을 이용하면 게스트 머신에서 동작하는 Chromium 클라이언트와 호스트 머신에서 동작하는 Chromium 서버간에 통신을 하게 해준다.
VBoxHGCM 프로토콜은 VBoxGuest.sys 드라이버를 통해 수행됨.
VboxHGCM Protocol
1. VBboxGuest.sys 디바이스 드라이버의 제어권 획득(obtain a handle to the VBoxGuest.sys device driver.)
HANDLE hDevice = CreateFile("\\\\.\\VBoxGuest", // 파일 이름
GENERIC_READ|GENERIC_WRITE, // 읽기,쓰기 모드 지정
FILE_SHARE_READ|FILE_SHARE_WRITE, // 파일 공유 속성 지정
NULL, // 보안 속성 지정
OPEN_EXISTING, // 파일이 생성되는 방법 지정
FILE_ATTRIBUTE_NORMAL, // 파일의 특성 정보 설정
NULL); // 기존에 존재하는 파일과 동일한 특성을 가지는 새 파일을 만들 때 사용되는 전달인자
2. DeviceIoControl을 이용하여 VBoxGuest 드라이버에 메세지를 전송(Send a message to the VBoxGuestdriver through DeviceIoControl)
BOOL rc = DeviceIoControl(hDevice, // 장치의 핸들을 통해 작업을 수행
VBOXGUEST_IOCTL_HGCM_CONNECT, // 작동을 위한 제어코드, 이 값을 통해 장치의 종류 및 수행할 특정 작업을 식별
&info, // 작업을 수행하기위해 필요한 데이터를 포함하는 입력 버퍼에 대한 포인터
sizeof(info), // 입력 버퍼의 사이트
&info, // 작업에 의해 반환 되는 데이터를 수신하는 출력 버퍼에 대한 포인터
sizeof(info), // 반환 퍼버의 사이즈
&cbReturned, // 반환 버퍼에 저장된 데이터의 바이트 크기를 받는 변수에 대한 포인터.
NULL);
VBoxGuest 드라이버는 DeviceIoControl 메세지를 VBoxGuestCommonIOCtl()함수를 이용해 컨트롤 함. [src/VBox/Additions/common/VBoxGuest/VBoxGuest.cpp]
4. VBOXGUEST_IOCTL_HGCM_CALL메세지를 보내고, SHCRGL_GUEST_FN_SET_PID 함수를 호출
5. 그 이후 VBOXGUEST_IOCTL_HGCM_CALL 메세지를 보내는데, 호출할 crOpenGL Guest 함수를 지정
VBox는 다음과 같은 서비스를 실행하는데 HGCM을 이용한다.
6. VBOXGUEST_IOCTL_HGCM_DISCONNECT 메세지를 보내고 VBoxGuest.sys 드라이버를 닫는다
Rendering Command
1. Chromium clinet(VM)는 여러 렌더링 command를 보내는데, Command는 opcode와 opcode의 데이터로 구성 2. Chromium 서버(Hypervisor)는 이러한 Opcode + 데이터를 해석하여 결과를 프레임 버퍼에 저장 3. Frame buffer의 내용은 VM안에 있는 client로 재전송
Buffered Mode
SHCRGL_GUEST_FN_WRITE_BUFFER
1. Cromium 클라이언트가 호출 메시지를 보낼 때까지 해제되지 않은 버퍼를 할당하는데 이때SHCRGL_GUEST_FN_WRITE_READ_BUFFERED 함수 사용
2. 이를 통해 호스트 시스템에서 실행되는 HyperVisor 프로세스의 주소 공간에 임의 크기, 임의 버퍼 수를 임의로 할당(할당 취소)할 수 있음. -> Heap Spray
crUnpack 함수
Chromium 클라이언트가 보낸 CR_MESSAGE_OPCODES를 통해 opcode와 data를 다룬다.
이 코드를 위한 함수는 파이썬 스크립트를 통해 생성됨. src/VBox/HostServices/SharedOpenGL/unpacker/unpack.py.
Unpack.py은 APIspec.txt이라는 파일을 파싱함
전체 OpenGL API의 정의를 포함하고 C 코드를 생성하여 해당 OpenGL 함수에 Chromium opcode를 디스패치
void crUnpack( const void *data, const void *opcodes,
unsigned int num_opcodes, SPUDispatchTable *table )
{
[...]
unpack_opcodes = (const unsigned char *)opcodes;
cr_unpackData = (const unsigned char *)data;
for (i = 0 ; i < num_opcodes ; i++)
{
/*crDebug("Unpacking opcode \%d", *unpack_opcodes);*/
switch( *unpack_opcodes )
{
case CR_ALPHAFUNC_OPCODE: crUnpackAlphaFunc(); break;
case CR_ARRAYELEMENT_OPCODE: crUnpackArrayElement(); break;
case CR_BEGIN_OPCODE: crUnpackBegin(); break;
[...]
Vbox 1day analysis (1)
요약
VirtualBox 6.0에서 사용하는 3D 가속을 이용한 취약점
Chromium library에 대한 사전 지식 필요
사전 지식
Vbox에서는 Chromium library를 이용하여 3D 가속을 구현
VirtualBox 3D 가속은 Chromium을 기반으로 구현됨
Chromium library
Chromium은 OpenGL의 한 프로젝트 였음.
Chromium은 Remote rendering을 하게 해주는 OpenGL기반 3D 그래픽 라이브러리 이며, 클라이언트/서버 구조로 되어 있음
HGCM을 이용하면 게스트 머신에서 동작하는 Chromium 클라이언트와 호스트 머신에서 동작하는 Chromium 서버간에 통신을 하게 해준다.
VBoxHGCM 프로토콜은 VBoxGuest.sys 드라이버를 통해 수행됨.
VboxHGCM Protocol
1. VBboxGuest.sys 디바이스 드라이버의 제어권 획득(obtain a handle to the VBoxGuest.sys device driver.)
CreateFile 원형
2. DeviceIoControl을 이용하여 VBoxGuest 드라이버에 메세지를 전송(Send a message to the VBoxGuest driver through DeviceIoControl)
VBoxGuest 드라이버는 DeviceIoControl 메세지를 VBoxGuestCommonIOCtl() 함수를 이용해 컨트롤 함.
[src/VBox/Additions/common/VBoxGuest/VBoxGuest.cpp]
서비스 연결
Chromium Protocol
crOpenGL guest function
VBoxSharedCrOpenGL 서비스에 HGCM Call 메세지를 보냄
HGCM Protocol calling
VBoxGuest.sys 드라이버가 "VBOXGUEST_IOCTL_HGCM_CALL" 메세지를 받으면 다음을 따른다
1. Guest -> Host로 입력 버퍼 복사
2. Host code call
3. Host -> Guest로 결과를 복사하여 되돌려줌
Chromium Protocol 통신 과정(Client)
1. VBoxGuest.sys 드라이버를 연다.
2. VBOXGUEST_IOCTL_HGCM_CONNECT 메세지를 보냄
3. VBOXGUEST_IOCTL_HGCM_CALL 메세지를 보내고, SHCRGL_GUEST_FN_SET_VERSION 함수를 호출
4. VBOXGUEST_IOCTL_HGCM_CALL 메세지를 보내고, SHCRGL_GUEST_FN_SET_PID 함수를 호출
5. 그 이후 VBOXGUEST_IOCTL_HGCM_CALL 메세지를 보내는데, 호출할 crOpenGL Guest 함수를 지정
VBox는 다음과 같은 서비스를 실행하는데 HGCM을 이용한다.
6. VBOXGUEST_IOCTL_HGCM_DISCONNECT 메세지를 보내고 VBoxGuest.sys 드라이버를 닫는다
Rendering Command
1. Chromium clinet(VM)는 여러 렌더링 command를 보내는데, Command는 opcode와 opcode의 데이터로 구성
2. Chromium 서버(Hypervisor)는 이러한 Opcode + 데이터를 해석하여 결과를 프레임 버퍼에 저장
3. Frame buffer의 내용은 VM안에 있는 client로 재전송
Buffered Mode
SHCRGL_GUEST_FN_WRITE_BUFFER
1. Cromium 클라이언트가 호출 메시지를 보낼 때까지 해제되지 않은 버퍼를 할당하는데 이때SHCRGL_GUEST_FN_WRITE_READ_BUFFERED 함수 사용
2. 이를 통해 호스트 시스템에서 실행되는 HyperVisor 프로세스의 주소 공간에 임의 크기, 임의 버퍼 수를 임의로 할당(할당 취소)할 수 있음. -> Heap Spray
crUnpack 함수
Chromium 클라이언트가 보낸 CR_MESSAGE_OPCODES를 통해 opcode와 data를 다룬다.
이 코드를 위한 함수는 파이썬 스크립트를 통해 생성됨.
src/VBox/HostServices/SharedOpenGL/unpacker/unpack.py.
Unpack.py은 APIspec.txt이라는 파일을 파싱함
전체 OpenGL API의 정의를 포함하고 C 코드를 생성하여 해당 OpenGL 함수에 Chromium opcode를 디스패치
참조
https://wogh8732.tistory.com/273#b48e6d54-d721-4fd4-8eca-2c4deb1aebc7
https://cosyp.tistory.com/247
https://labs.f-secure.com/assets/BlogFiles/offensivecon-2019-3d-accelerated-exploitation-jason-matthyser.pdf https://remind-me-later.tistory.com/111
https://public.jhyeon.dev/research/virtualbox
https://www.coresecurity.com/sites/default/files/private-files/publications/2016/05/corelabs-Breaking_Out_of_VirtualBox_through_3D_Acceleration-Francisco_Falcon.pdf