Hypervisor Detection에 대해 알아보자. Microsoft의 Hyper-V나 VMware, VirtualBox와 같은 대형 하이퍼바이저를 잡는 목적이 아니다. 그런 하이퍼바이저들은 합법적일 뿐더러 소개할 방법에 감지되지 않는다.
우리가 잡는 하이퍼바이저는 불순한 의도(게임 핵, 바이러스, 등등..)를 가지는 하이퍼바이저에 대한 감지를 수행하는 것이다.
애초에 HV가 Guest한테 감지되지 않을 목적으로 제작한 것이라 할 수 있는 방법이 거의 없다시피 한다. 전에 소개한 EPT Hooking같은 경우는 잡을 수 있는 방법이 아예 없다. 따라서 우리는 편법으로 잡을 수밖에 없다. 여기선 대표적인 Detection 3개를 소개한다.
rdtsc
명령을 이용해 CPU 사이클을 체크한다. 여기서 특정 Threshold를 초과하면 VM을 사용하는 것으로, 아니면 베어메탈로 판정한다.void performRDTSCTimingCheck(){
unsigned long long int time1, time2, sum = 0;
const unsigned char avg = 100;
for (int i = 0; i < avg; i++){
time1 = __rdtsc();
#ifdef _WIN32
__asm cpuid;
#elif __linux__
__asm__ volatile("CPUID"::: "eax", "ebx", "ecx", "edx", "memory");
#endif
time2 = __rdtsc();
sum += time2 - time1;
}
sum = sum / avg;
printf("Ticks on average: %llu\\n", sum);
if(sum > 500){
puts("Probably a VM");
}else{
puts("Probably Bare-Metal");
}
}
rdtsc
명령어는 VM Exit을 유발하는 명령어이다. 그 말은 즉슨, VM Exit Handler에서 핸들링할 수 있다는 것이다. 따라서 rdtsc
명령어의 반환값을 조작하여APERF
MSR Entry를 통해 CPU 사이클을 측정할 수 있는데 이를 통해 감지하는 방법이다.