[가상화] LDT(Local Descriptor Table)를 이용한 VMM Detection
System Programming/Virtualization 2011/07/28 22:07안녕하세요, SecuRex0입니다.^^
저번 포스트(여기를 클릭하시면 보실 수 있습니다)에서는 Intel 계열의 단일 코어 CPU에서 SIDT를 이용해 VMM을 감지하는 방법에 대해서 알아보았습니다. 예고했듯이, 이번 포스트는 한차원 더 발전된 방법인 LDT를 이용한 VMM 감지입니다.
NOTE - SIDT를 이용한 VMM 감지가 멀티코어에서는 되지 않는 이유
싱글코어에서는 IDT의 위치가 변경되지 않기 때문에, Memory Relocated된 IDT인지 판별해서 감지를 했었습니다. 하지만 멀티코어에서는 서로 다른 코어에서 프로세스가 동작할 때 IDT가 변화될 수 있습니다. 그래서 멀티코어에서는 감지가 정확하게 되지 않습니다. 그래서 사용하는 방법이 LDT를 이용한 감지입니다. LDT를 이용해 VMM을 감지할 시 멀티코어에서도 원활히 동작합니다.
LDT(Local Descriptor Table)는 특권(privilege)의 변경을 수행할때 사용되는 테이블이며, 특권의 변경이 수행될 시 세그먼테이션을 제공합니다. Base address, access rights, 타입, 길이, 그리고 현재 세그먼트에 대한 사용 정보를 저장합니다. 이것에 대한 접근을 수행하기 위해서는 LDTR(Local Descriptor Table Register)이라는 녀석을 사용하는데요, 이 녀석은 GDT안의 LDT 디스크립터를 가리키는 셀렉터(selector)입니다. LLDT(Load LDT), SLDT(Store LDT) 명령으로 참조하고 설정할수 있습니다.
하지만 LDT는 모든 시스템에서 사용하지 않습니다. 심지어 세계 OS 시장의 대부분을 점유하고 있는 윈도우즈에서도 LDT를 사용하지 않습니다. 가상화 모드에서 동작하는 윈도우즈의 LDT는 반드시 운영 체제 위에서 존재하는 값보다 더 분리된 값(a separate value)으로 존재해야 합니다. 그래서 VM은 각각의 운영체제마다 GDT와 LDT에 대한 구현의 차이를 조금씩 둡니다. 중요한 것은 SIDT, SLDT, SGDT 어셈블리 인스트럭션은 가상화 모드를 유지하기 위해 끊임없이 가상화 되어야 합니다. 그래서 그들은 같은 값을 가질 수 없으며 VM은 그들의 값들에 대한 일련의 카피본을 제공해 줍니다.
나머지 기본적인 원리는 동일합니다. 아래는 소스 코드입니다.
#include <stdio.h>
inline int checkIDT();
int checkGDT();
int checkLDT();
int main(int argc, char **argv)
{
checkIDT();
checkGDT();
if(checkLDT())
printf("Inside VM\n");
else
printf("Inside Native Machine\n");
return 0;
}
inline int checkIDT()
{
unsigned char m[6];
__asm sidt m;
return (m[5] > 0xd0) ? 1 : 0;
}
int checkGDT()
{
unsigned char m[6];
__asm sgdt m;
return (m[5] > 0xd0) ? 1 : 0;
}
int checkLDT()
{
unsigned char m[6];
__asm sldt m;
return (m[0] != 0x00 && m[1] != 0x00) ? 1 : 0;
}
제 컴퓨터에서 실행한 결과입니다..^^
다음 포스트 예고: Anti VMM Detection
'System Programming > Virtualization' 카테고리의 다른 글
| [가상화] LDT(Local Descriptor Table)를 이용한 VMM Detection (10) | 2011/07/28 |
|---|---|
| [가상화] SIDT 계열의 단일 인스트럭션으로 VMM 감지 - Redpill Project (9) | 2011/07/27 |
| [가상화] 가상화의 기본 개념 (8) | 2011/07/15 |






