Check if windows host is a VM.
Cross-compiled with mingw 4.2.1 and 4.4.5, tested under XP 32 bits and '7' 64 bits VBox VMs only
کد:
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <ctype.h>
#include <windows.h>
#include <tlhelp32.h>
/* maximun length of registry subkeys.
* MAX_CHAR/5 is set as the maximun length of processes names. */
#define MAX_CHAR 100
typedef char * string;
/* removes the first character of given string.
* example: Str="blah"; _StrLower(Str); <- Str is now "lah".
*/
void _substr(string Str){
size_t i;
for(i=0; Str[i]; i++)
Str[i] = Str[i+1];
Str[i] = '\0';
}
/* converts the string to lower case.
* example: Str="bLAH"; _StrLower(Str); <- Str is now "blah".
*/
void _StrLower(string Str){
size_t i;
for (i = 0; (Str[i] = (char)tolower(Str[i])) != '\0'; i++)
;
}
/* checks if the given process is running.
* case of 'proc' doesn't matter
* example: chk_process("ExPLoReR.eXE") returns TRUE if explorer.exe is running.
* taken from:
* http://stackoverflow.com/questions/8...-its-name-in-c
*/
bool chk_process(string proc){
PROCESSENTRY32 entry;
entry.dwFlags = sizeof(PROCESSENTRY32);
unsigned short len = strlen(proc);
HANDLE snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, NULL);
char exe_name[MAX_CHAR] = "";
_StrLower(proc);
if(Process32First(snapshot, &entry))
while(Process32Next(snapshot, &entry)){
strcpy(exe_name, entry.szExeFile);
exe_name[MAX_CHAR-1] = '\0';
_StrLower(exe_name);
if(!strncmp(proc, exe_name, len))
return TRUE;
}
CloseHandle(snapshot);
return FALSE;
}
/* check if the given subkey exists.
* key = name of subkey in HKEY_LOCAL_MACHINE in which to find subkeys
* vals = array of strings with which to compare the subkeys
* size = number of strings in 'vals'
* example: query_subkey("HARDWARE\\ACPI\\DSDT", { "VBOX__" }, 1) returns true if there exist the
* subkey "VBOX__" under "HKEY_LOCAL_MACHINE\HARDWARE\ACPI\DSDT"
* case for strings in 'vals' matter, other don't.
*/
bool query_subkey(string key, char vals[][MAX_CHAR], unsigned short size){
char subkey_name[256];
unsigned long subkey_name_len, retcode, i, j;
HKEY hkey;
if (RegOpenKeyExA(HKEY_LOCAL_MACHINE, key, NULL, KEY_ENUMERATE_SUB_KEYS, &hkey) == ERROR_SUCCESS)
for(i = 0; 1; i++){
subkey_name_len = 255;
retcode = RegEnumKeyExA(hkey, i, subkey_name, &subkey_name_len, NULL, NULL, NULL, NULL);
subkey_name[255] = '\0';
if(retcode == ERROR_SUCCESS)
for(j = 0; j < size; j++){
if(vals[j] && !strcmp(vals[j], subkey_name)){
RegCloseKey(hkey);
return TRUE;
}
}
else if(retcode == ERROR_NO_MORE_ITEMS){
RegCloseKey(hkey);
return FALSE;
}
}
RegCloseKey(hkey);
return FALSE;
}
/* check if a string 'Str' is contained in registry value 'val', under the subkey 'key' in HKEY_LOCAL_MACHINE
* key = represents the subkey in HKEY_LOCAL_MACHINE
* val = name of the value in the subkey. if it doesn't exists, return FALSE
* Str = string with which to compare the data in the value val
* only for REG_SZ value types.
* example:
* query_val_data("HARDWARE\\DESCRIPTION\\System", "Identifier", "VBOX") will return TRUE if "vbox" is contained
* contained in the registry value "Identifier" under "HKEY_LOCAL_MACHINE\HARDWARE\DESCRIPTION\System".
* case of registry value 'val' matter, other don't.
*/
bool query_val_data(string key, string val, string Str){
HKEY hkey;
DWORD size = 500, keytype = REG_SZ, i=0;
unsigned char data_name[size];
char data[size];
if(RegOpenKeyExA(HKEY_LOCAL_MACHINE, TEXT(key), 0, KEY_QUERY_VALUE, &hkey) == ERROR_SUCCESS){
LONG retcode = RegQueryValueExA(hkey, TEXT(val), 0, &keytype, (unsigned char*)data_name, &size);
if(retcode == ERROR_SUCCESS){
RegCloseKey(hkey);
strcpy(data, (char *)data_name);
_StrLower(Str); _StrLower(data);
size = strlen(Str);
i = strlen(data);
while(i >= size){
if(!strncmp(Str, data, size))
return TRUE;
else{
_substr(data);
i--;
}
}
}
if(retcode == ERROR_FILE_NOT_FOUND)
return FALSE;
}
return FALSE;
}
/* This functions are "translation" of the script "checkvm.rb" ( scripts/meterpreter/checkvm.rb )
* from metasploit.
* https://www.metasploit.com/redmine/p...ter/checkvm.rb
* I just copied the registry keys, values and data, and the process names for checking VM.
* You can add your own VM programs to the list (QEMU, Parallels, Bochs, ...).
*/
/* check if host is a Hyper-V VM*/
bool hypervchk(void){
unsigned short i;
char key[][MAX_CHAR] = {
"SOFTWARE\\Microsoft",
"SYSTEM\\ControlSet001\\Services"
};
char vals[][4][MAX_CHAR] = {
{ "Hyper-V", "VirtualMachine" , "", "" },
{ "vmicheartbeat", "vmicvss", "vmicshutdown", "vmicexchange" }
};
for(i=0; i < 2; i++)
if(query_subkey(key[i], vals[i], 4))
return TRUE;
return FALSE;
}
/* check if host is a VMWare VM*/
bool vmwarechk(void){
char vmwareprocs[][MAX_CHAR/5] = { "vmwareuser.exe", "vmwaretray.exe" };
unsigned short i;
for(i=0; i<2; i++)
if(chk_process(vmwareprocs[i]))
return TRUE;
char key[][MAX_CHAR] = {
"SYSTEM\\ControlSet001\\Services",
"HARDWARE\\DEVICEMAP\\Scsi\\Scsi Port 0\\Scsi Bus 0\\Target Id 0\\Logical Unit Id 0"
};
char vals[][MAX_CHAR] = { "vmdebug", "vmmouse", "VMTools", "VMMEMCTL" };
if(query_subkey(key[0], vals, 4))
return TRUE;
char str[] = "vmware", val[] = "Identifier";
if(query_val_data(key[1], val, str))
return TRUE;
return FALSE;
}
/* check if host is a Virtual PC VM*/
bool checkvrtlpc(void){
char vpcprocs[][MAX_CHAR/5] = { "vmusrvc.exe", "vmsrvc.exe" };
unsigned short i;
for(i=0; i<2; i++)
if(chk_process(vpcprocs[i]))
return TRUE;
char key[] = "SYSTEM\\ControlSet001\\Services";
char vals[][MAX_CHAR] = { "vpcbus", "vpc-s3", "vpcuhub", "msvmmouf" };
if(query_subkey(key, vals, 4))
return TRUE;
return FALSE;
}
/* check if host is a VirtualBox VM*/
bool vboxchk(void){
char vboxprocs[][MAX_CHAR/5] = { "vboxservice.exe", "vboxtray.exe" };
unsigned short i, j;
char key[][MAX_CHAR] = {
"HARDWARE\\ACPI\\DSDT",
"HARDWARE\\ACPI\\FADT",
"HARDWARE\\ACPI\\RSDT",
"SYSTEM\\ControlSet001\\Services",
"HARDWARE\\DEVICEMAP\\Scsi\\Scsi Port 0\\Scsi Bus 0\\Target Id 0\\Logical Unit Id 0",
"HARDWARE\\DESCRIPTION\\System"
};
char vals[][4][MAX_CHAR] = {
{ "VBOX__" , "", "", "" },
{ "VBoxMouse", "VBoxGuest", "VBoxService", "VBoxSF" }
};
char val[][MAX_CHAR] = {
"Identifier",
"SystemBiosVersion"
};
char str[] = "VBOX";
for(i=0; i < 3; i++){
if(query_subkey(key[i], vals[0], 4))
return TRUE;
}
if(query_subkey(key[i++], vals[1], 4))
return TRUE;
for(j=0; j < 2; j++)
if(query_val_data(key[i+j], val[j], str))
return TRUE;
for(i=0; i<2; i++)
if(chk_process(vboxprocs[i]))
return TRUE;
return FALSE;
}
/* check if host is a Xen VM*/
bool xenchk(void){
unsigned short i;
char xenprocs[] = "xenservice.exe";
if(chk_process(xenprocs))
return TRUE;
char key[][MAX_CHAR] = {
"HARDWARE\\ACPI\\DSDT",
"HARDWARE\\ACPI\\FADT",
"HARDWARE\\ACPI\\RSDT",
"SYSTEM\\ControlSet001\\Services"
};
char vals[][5][MAX_CHAR] = {
{ "Xen" , "", "", "", "" },
{ "xenevtchn", "xennet", "xennet6", "xensvc", "xenvdb" }
};
for(i=0; i< 3; i++)
if(query_subkey(key[i], vals[0], 4))
return TRUE;
if(query_subkey(key[3], vals[1], 4))
return TRUE;
return FALSE;
}
/* main program, for testing purposes */
int main(void){
if(hypervchk() || xenchk() || checkvrtlpc() || vmwarechk() || vboxchk())
MessageBoxA(NULL, "Virtual Machine", "Title", MB_OK);
else MessageBoxA(NULL, "No Virtual Machine", "Title", MB_OK);
return 0;
کد:
#include < windows.h >
#include < tlhelp32.h >
typedef int (__cdecl *pPrintf)( const char *, ... );
pPrintf _printf;
char *servicelist[] =
{
// hyperv
"vmicheartbeat",
"vmicvss",
"vmicshutdown",
"vmicexchange",
// vmware
"vmdebug",
"vmmouse",
"VMTools",
"VMMEMCTL",
// virtual pc
"vpcbus",
"vpc-s3",
"vpcuhub",
"msvmmouf",
// virtualbox
"VBoxMouse",
"VBoxGuest",
"VBoxService",
"VBoxSF",
// xen vm
"xenevtchn",
"xennet",
"xennet6",
"xensvc",
"xenvdb",
NULL
};
// msdn code is best code
#define MAX_KEY_LENGTH 255
BOOL KnownServiceExists( void )
{
HKEY hKey;
TCHAR achKey[MAX_KEY_LENGTH];
DWORD i, retCode, cbName, cSubKeys = 0;
FILETIME ftLastWriteTime;
int n;
if ( RegOpenKeyEx(HKEY_LOCAL_MACHINE, "SYSTEM\\ControlSet001\\Services", 0, KEY_READ, &hKey) == ERROR_SUCCESS )
{
retCode = RegQueryInfoKey( hKey, 0, 0, 0, &cSubKeys, 0, 0, 0, 0, 0, 0, &ftLastWriteTime );
if ( cSubKeys )
{
// _printf( "\n[*] number of services: %d\n", cSubKeys );
for ( i = 0; i < cSubKeys; i++ )
{
cbName = MAX_KEY_LENGTH;
retCode = RegEnumKeyEx(hKey, i, achKey, &cbName, 0, 0, 0, &ftLastWriteTime );
if ( retCode == ERROR_SUCCESS )
{
// _printf( "(%d) %s\n", i + 1, achKey );
for ( n = 0; servicelist[n]; n++ )
{
if ( !lstrcmpi(servicelist[n], achKey) )
{
RegCloseKey( hKey );
return 1;
}
}
}
}
}
}
RegCloseKey( hKey );
return 0;
}
// doesn't work on vista 64bit if compiled as 32bit (even running as admin with SE_DEBUG...)
// works on win7x64 though
BOOL KnownProcRunning( void )
{
PROCESSENTRY32 entry;
HANDLE snapshot;
entry.dwFlags = sizeof( PROCESSENTRY32 );
snapshot = CreateToolhelp32Snapshot( TH32CS_SNAPPROCESS, 0 );
if ( Process32First(snapshot, &entry) )
{
while ( Process32Next(snapshot, &entry) )
{
_printf( "[*] (pid:%d) %s\n", entry.th32ProcessID, entry.szExeFile );
// oh well
}
}
CloseHandle( snapshot );
return 0;
}
int mainCRTStartup( void )
{
HMODULE msvcrt;
msvcrt = LoadLibrary( "msvcrt.dll" );
_printf = (pPrintf)GetProcAddress( msvcrt, "printf" );
if ( !_printf ) ExitProcess( 1 );
if ( KnownServiceExists() == 1 )
_printf( "[!] virtual machine detected...\n" );
else
_printf( "[?] no virtual machine detected...\n" );
// KnownProcRunning();
ExitProcess( 0 );
}