P
Pete Dashwood
I have a passing acquaintance with C++ but am far from expert. I collected
various bits of code and modified them as below.
The trouble is, I don't know enough about the C++ environment (directives
etc. - it took me 2 days to figure out that I needed to export the Method I
want to invoke, and to find the directive for it. I have configured
VS2008 (VC++) to use the entrypoint name ("runTests()")
The code below compiles clean with 3 warnings (which I don't totally
understand) and it executes fine on both real and virtual platforms. The
only problem is that it ALWAYS returns zero It SHOULD return 1 if it is
running on a VM. It is built as a normal .DLL (Not COM).
The "test8()" Method calls somethng called "InVirtualBox" which was supposed
to return a bool. It just wouldn't compile with a type of bool so I changed
it to int. This indicates I am missing some fundamental stuff here and I'd
really appreciate if someone with an experienced C++ eye could just have a
look and confirm that the code should run or not. I have no idea how to
debug this and I need to call it from C#. (I do this via DllImport and it
seems to work fine. (I put it in a try/catch block and it gives no
exceptions))
Here's the code:
#include <windows.h>
#include <excpt.h>
#include <stdio.h>
#include <Tlhelp32.h>
#define DEBUG 0
#define EndUserModeAddress (*(UINT_PTR*)0x7FFE02B4)
typedef LONG (NTAPI *NTSETLDTENTRIES)(DWORD, DWORD, DWORD, DWORD, DWORD,
DWORD);
// global int will be 1 if we are running on VM, 0 if we are not...
int result = 0;
int
InVirtualBox (void)
{
HANDLE handle = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS,0);
PROCESSENTRY32 procinfo = { sizeof(PROCESSENTRY32) };
while(Process32Next(handle, &procinfo))
{
if(!strcmp(procinfo.szExeFile, "VBoxService.exe"))
{
CloseHandle(handle);
return 1;
}
}
CloseHandle(handle);
return 0;
}
unsigned long
get_idt_base (void)
{
unsigned char idtr[6];
unsigned long idt = 0;
_asm sidt idtr
idt = *((unsigned long *)&idtr[2]);
return (idt);
}
unsigned long
get_ldtr_base (void)
{
unsigned char ldtr[5] = "\xef\xbe\xad\xde";
unsigned long ldt = 0;
_asm sldt ldtr
ldt = *((unsigned long *)&ldtr[0]);
return (ldt);
}
unsigned long
get_gdt_base (void)
{
unsigned char gdtr[6];
unsigned long gdt = 0;
_asm sgdt gdtr
gdt = *((unsigned long *)&gdtr[2]);
return (gdt);
}
int
test1 (void)
{
unsigned int idt_base = 0;
idt_base = get_idt_base ();
//printf ("[+] Test 1: IDT\n");
//printf ("IDT base: 0x%x\n", idt_base);
if ((idt_base >> 24) == 0xff) {
//printf ("Result : VMware detected\n\n");
return 1;
}
/*
else {
printf ("Result : Native OS\n\n");
return;
}
*/
return 0;
}
int
test2 (void)
{
unsigned int ldt_base = 0;
ldt_base = get_ldtr_base ();
//printf ("\n[+] Test 2: LDT\n");
//printf ("LDT base: 0x%x\n", ldt_base);
if (ldt_base == 0xdead0000) {
//printf ("Result : Native OS\n\n");
return 0;
}
else {
//printf ("Result : VMware detected\n\n");
//result = 1;
return 1;
}
}
int
test3 (void)
{
unsigned int gdt_base = 0;
gdt_base = get_gdt_base ();
//printf ("\n[+] Test 3: GDT\n");
//printf ("GDT base: 0x%x\n", gdt_base);
if ((gdt_base >> 24) == 0xff) {
//printf ("Result : VMware detected\n\n");
//result = 1;
return 1;
}
/*
else {
printf ("Result : Native OS\n\n");
return;
}
*/
return 0;
}
// Alfredo Andrs Omella's (S21sec) STR technique
int
test4 (void)
{
unsigned char mem[4] = {0, 0, 0, 0};
__asm str mem;
//printf ("\n[+] Test 4: STR\n");
//printf ("STR base: 0x%02x%02x%02x%02x\n", mem[0], mem[1], mem[2], mem[3]);
if ((mem[0] == 0x00) && (mem[1] == 0x40))
//printf ("Result : VMware detected\n\n");
return 1;
//else
//printf ("Result : Native OS\n\n");
return 0;
}
int
test5 (void)
{
unsigned int a, b;
__try {
__asm {
// save register values on the stack
push eax
push ebx
push ecx
push edx
// perform fingerprint
mov eax, 'VMXh' // VMware magic value (0x564D5868)
mov ecx, 0Ah // special version cmd (0x0a)
mov dx, 'VX' // special VMware I/O port (0x5658)
in eax, dx // special I/O cmd
mov a, ebx // data
mov b, ecx // data (eax gets also modified but will not be evaluated)
// restore register values from the stack
pop edx
pop ecx
pop ebx
pop eax
}
} __except (EXCEPTION_EXECUTE_HANDLER) {}
#if DEBUG == 1
printf ("\n [ a=%x ; b=%d ]\n\n", a, b);
#endif
//printf ("\n[+] Test 5: VMware \"get version\" command\n");
if (a == 'VMXh') { // is the value equal to the VMware magic value?
//printf ("Result : VMware detected\nVersion : ");
return 1;
/*
if (b == 1)
printf ("Express\n\n");
else if (b == 2)
printf ("ESX\n\n");
else if (b == 3)
printf ("GSX\n\n");
else if (b == 4)
printf ("Workstation\n\n");
else
printf ("unknown version\n\n");
*/
}
//else
//printf ("Result : Native OS\n\n");
return 0;
}
int
test6 (void)
{
unsigned int a = 0;
__try {
__asm {
// save register values on the stack
push eax
push ebx
push ecx
push edx
// perform fingerprint
mov eax, 'VMXh' // VMware magic value (0x564D5868)
mov ecx, 14h // get memory size command (0x14)
mov dx, 'VX' // special VMware I/O port (0x5658)
in eax, dx // special I/O cmd
mov a, eax // data
// restore register values from the stack
pop edx
pop ecx
pop ebx
pop eax
}
} __except (EXCEPTION_EXECUTE_HANDLER) {}
//printf ("\n[+] Test 6: VMware \"get memory size\" command\n");
if (a > 0)
//printf ("Result : VMware detected\n\n");
return 1;
else
return 0;
//printf ("Result : Native OS\n\n");
}
/*
int
test7_detect (LPEXCEPTION_POINTERS lpep)
{
//printf ("\n[+] Test 7: VMware emulation mode\n");
if ((UINT_PTR)(lpep->ExceptionRecord->ExceptionAddress) >
EndUserModeAddress)
//printf ("Result : VMware detected (emulation mode detected)\n\n");
result = 1;
else
printf ("Result : Native OS or VMware without emulation mode\n"
" (enabled acceleration)\n\n");
return (EXCEPTION_EXECUTE_HANDLER);
}
void __declspec(naked)
test7_switchcs ()
{
__asm {
pop eax
push 0x000F
push eax
retf
}
}
// Derek Soeder's (eEye Digital Security) VMware emulation test
// removed... didn't work
int
test7 (void)
{
NTSETLDTENTRIES ZwSetLdtEntries;
LDT_ENTRY csdesc;
ZwSetLdtEntries = (NTSETLDTENTRIES)GetProcAddress (GetModuleHandle
("ntdll.dll"), "ZwSetLdtEntries");
memset (&csdesc, 0, sizeof (csdesc));
csdesc.LimitLow = (WORD)(EndUserModeAddress >> 12);
csdesc.HighWord.Bytes.Flags1 = 0xFA;
csdesc.HighWord.Bytes.Flags2 = 0xC0 | ((EndUserModeAddress >> 28) & 0x0F);
ZwSetLdtEntries (0x000F, ((DWORD*)&csdesc)[0], ((DWORD*)&csdesc)[1], 0, 0,
0);
__try {
test7_switchcs();
__asm {
or eax, -1
jmp eax
}
}
__except (test7_detect (GetExceptionInformation())) { }
}
*/
/**********************************
** Detect if your application **
** is running in Virtual Box. **
** **
** E0N 2008 **
**********************************/
//#include <windows.h>
//#include <Tlhelp32.h>
int test8 ()
{
if (InVirtualBox() == 1)
{
return 1;
}
return 0;
}
extern __declspec(dllexport) int runTests();
runTests ()
{
/*
The code here has been sourced from various places.Much available code was
rejected
as being too unstable or transient and likely to be overtaken by new VM
releases.
The final tests here were reviewed and amended by Peter E. C. Dashwood, for
PRIMA
Computing, (NZ) Ltd.
The following authors should be acknowledged, and we thank them for making
their code and knowledge
public:
Joanna Rutkovska (the Red Pill 2004)
Tom Liston / Ed Skoudis
Tobias Klein
Alfredo Andres Omella
Derek Soeder (unfortunately, we couldn't get this approach to work
and it is not used here. Neverthless, the code was of
value for educational purposes.)
*/
result = test1 (); //good code
if (result == 1)
return result;
result = test2 (); //good code
if (result == 1)
return result;
result = test3 (); //good code
if (result == 1)
return result;
result = test4 (); //good code
if (result == 1)
return result;
result = test5 (); //good code
if (result == 1)
return result;
result = test6 (); //good code
//test7 (); //bad code don't use (Causes Access Violation)
result = test8 ();
return result;
// result will be zero if the machine is real, 1 if it is virtual, and 2 if
it is impossible to tell.
}
Sorry post has reformatted the code. Any comments or help greatly
appreciated,
Pete.
--
various bits of code and modified them as below.
The trouble is, I don't know enough about the C++ environment (directives
etc. - it took me 2 days to figure out that I needed to export the Method I
want to invoke, and to find the directive for it. I have configured
VS2008 (VC++) to use the entrypoint name ("runTests()")
The code below compiles clean with 3 warnings (which I don't totally
understand) and it executes fine on both real and virtual platforms. The
only problem is that it ALWAYS returns zero It SHOULD return 1 if it is
running on a VM. It is built as a normal .DLL (Not COM).
The "test8()" Method calls somethng called "InVirtualBox" which was supposed
to return a bool. It just wouldn't compile with a type of bool so I changed
it to int. This indicates I am missing some fundamental stuff here and I'd
really appreciate if someone with an experienced C++ eye could just have a
look and confirm that the code should run or not. I have no idea how to
debug this and I need to call it from C#. (I do this via DllImport and it
seems to work fine. (I put it in a try/catch block and it gives no
exceptions))
Here's the code:
#include <windows.h>
#include <excpt.h>
#include <stdio.h>
#include <Tlhelp32.h>
#define DEBUG 0
#define EndUserModeAddress (*(UINT_PTR*)0x7FFE02B4)
typedef LONG (NTAPI *NTSETLDTENTRIES)(DWORD, DWORD, DWORD, DWORD, DWORD,
DWORD);
// global int will be 1 if we are running on VM, 0 if we are not...
int result = 0;
int
InVirtualBox (void)
{
HANDLE handle = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS,0);
PROCESSENTRY32 procinfo = { sizeof(PROCESSENTRY32) };
while(Process32Next(handle, &procinfo))
{
if(!strcmp(procinfo.szExeFile, "VBoxService.exe"))
{
CloseHandle(handle);
return 1;
}
}
CloseHandle(handle);
return 0;
}
unsigned long
get_idt_base (void)
{
unsigned char idtr[6];
unsigned long idt = 0;
_asm sidt idtr
idt = *((unsigned long *)&idtr[2]);
return (idt);
}
unsigned long
get_ldtr_base (void)
{
unsigned char ldtr[5] = "\xef\xbe\xad\xde";
unsigned long ldt = 0;
_asm sldt ldtr
ldt = *((unsigned long *)&ldtr[0]);
return (ldt);
}
unsigned long
get_gdt_base (void)
{
unsigned char gdtr[6];
unsigned long gdt = 0;
_asm sgdt gdtr
gdt = *((unsigned long *)&gdtr[2]);
return (gdt);
}
int
test1 (void)
{
unsigned int idt_base = 0;
idt_base = get_idt_base ();
//printf ("[+] Test 1: IDT\n");
//printf ("IDT base: 0x%x\n", idt_base);
if ((idt_base >> 24) == 0xff) {
//printf ("Result : VMware detected\n\n");
return 1;
}
/*
else {
printf ("Result : Native OS\n\n");
return;
}
*/
return 0;
}
int
test2 (void)
{
unsigned int ldt_base = 0;
ldt_base = get_ldtr_base ();
//printf ("\n[+] Test 2: LDT\n");
//printf ("LDT base: 0x%x\n", ldt_base);
if (ldt_base == 0xdead0000) {
//printf ("Result : Native OS\n\n");
return 0;
}
else {
//printf ("Result : VMware detected\n\n");
//result = 1;
return 1;
}
}
int
test3 (void)
{
unsigned int gdt_base = 0;
gdt_base = get_gdt_base ();
//printf ("\n[+] Test 3: GDT\n");
//printf ("GDT base: 0x%x\n", gdt_base);
if ((gdt_base >> 24) == 0xff) {
//printf ("Result : VMware detected\n\n");
//result = 1;
return 1;
}
/*
else {
printf ("Result : Native OS\n\n");
return;
}
*/
return 0;
}
// Alfredo Andrs Omella's (S21sec) STR technique
int
test4 (void)
{
unsigned char mem[4] = {0, 0, 0, 0};
__asm str mem;
//printf ("\n[+] Test 4: STR\n");
//printf ("STR base: 0x%02x%02x%02x%02x\n", mem[0], mem[1], mem[2], mem[3]);
if ((mem[0] == 0x00) && (mem[1] == 0x40))
//printf ("Result : VMware detected\n\n");
return 1;
//else
//printf ("Result : Native OS\n\n");
return 0;
}
int
test5 (void)
{
unsigned int a, b;
__try {
__asm {
// save register values on the stack
push eax
push ebx
push ecx
push edx
// perform fingerprint
mov eax, 'VMXh' // VMware magic value (0x564D5868)
mov ecx, 0Ah // special version cmd (0x0a)
mov dx, 'VX' // special VMware I/O port (0x5658)
in eax, dx // special I/O cmd
mov a, ebx // data
mov b, ecx // data (eax gets also modified but will not be evaluated)
// restore register values from the stack
pop edx
pop ecx
pop ebx
pop eax
}
} __except (EXCEPTION_EXECUTE_HANDLER) {}
#if DEBUG == 1
printf ("\n [ a=%x ; b=%d ]\n\n", a, b);
#endif
//printf ("\n[+] Test 5: VMware \"get version\" command\n");
if (a == 'VMXh') { // is the value equal to the VMware magic value?
//printf ("Result : VMware detected\nVersion : ");
return 1;
/*
if (b == 1)
printf ("Express\n\n");
else if (b == 2)
printf ("ESX\n\n");
else if (b == 3)
printf ("GSX\n\n");
else if (b == 4)
printf ("Workstation\n\n");
else
printf ("unknown version\n\n");
*/
}
//else
//printf ("Result : Native OS\n\n");
return 0;
}
int
test6 (void)
{
unsigned int a = 0;
__try {
__asm {
// save register values on the stack
push eax
push ebx
push ecx
push edx
// perform fingerprint
mov eax, 'VMXh' // VMware magic value (0x564D5868)
mov ecx, 14h // get memory size command (0x14)
mov dx, 'VX' // special VMware I/O port (0x5658)
in eax, dx // special I/O cmd
mov a, eax // data
// restore register values from the stack
pop edx
pop ecx
pop ebx
pop eax
}
} __except (EXCEPTION_EXECUTE_HANDLER) {}
//printf ("\n[+] Test 6: VMware \"get memory size\" command\n");
if (a > 0)
//printf ("Result : VMware detected\n\n");
return 1;
else
return 0;
//printf ("Result : Native OS\n\n");
}
/*
int
test7_detect (LPEXCEPTION_POINTERS lpep)
{
//printf ("\n[+] Test 7: VMware emulation mode\n");
if ((UINT_PTR)(lpep->ExceptionRecord->ExceptionAddress) >
EndUserModeAddress)
//printf ("Result : VMware detected (emulation mode detected)\n\n");
result = 1;
else
printf ("Result : Native OS or VMware without emulation mode\n"
" (enabled acceleration)\n\n");
return (EXCEPTION_EXECUTE_HANDLER);
}
void __declspec(naked)
test7_switchcs ()
{
__asm {
pop eax
push 0x000F
push eax
retf
}
}
// Derek Soeder's (eEye Digital Security) VMware emulation test
// removed... didn't work
int
test7 (void)
{
NTSETLDTENTRIES ZwSetLdtEntries;
LDT_ENTRY csdesc;
ZwSetLdtEntries = (NTSETLDTENTRIES)GetProcAddress (GetModuleHandle
("ntdll.dll"), "ZwSetLdtEntries");
memset (&csdesc, 0, sizeof (csdesc));
csdesc.LimitLow = (WORD)(EndUserModeAddress >> 12);
csdesc.HighWord.Bytes.Flags1 = 0xFA;
csdesc.HighWord.Bytes.Flags2 = 0xC0 | ((EndUserModeAddress >> 28) & 0x0F);
ZwSetLdtEntries (0x000F, ((DWORD*)&csdesc)[0], ((DWORD*)&csdesc)[1], 0, 0,
0);
__try {
test7_switchcs();
__asm {
or eax, -1
jmp eax
}
}
__except (test7_detect (GetExceptionInformation())) { }
}
*/
/**********************************
** Detect if your application **
** is running in Virtual Box. **
** **
** E0N 2008 **
**********************************/
//#include <windows.h>
//#include <Tlhelp32.h>
int test8 ()
{
if (InVirtualBox() == 1)
{
return 1;
}
return 0;
}
extern __declspec(dllexport) int runTests();
runTests ()
{
/*
The code here has been sourced from various places.Much available code was
rejected
as being too unstable or transient and likely to be overtaken by new VM
releases.
The final tests here were reviewed and amended by Peter E. C. Dashwood, for
PRIMA
Computing, (NZ) Ltd.
The following authors should be acknowledged, and we thank them for making
their code and knowledge
public:
Joanna Rutkovska (the Red Pill 2004)
Tom Liston / Ed Skoudis
Tobias Klein
Alfredo Andres Omella
Derek Soeder (unfortunately, we couldn't get this approach to work
and it is not used here. Neverthless, the code was of
value for educational purposes.)
*/
result = test1 (); //good code
if (result == 1)
return result;
result = test2 (); //good code
if (result == 1)
return result;
result = test3 (); //good code
if (result == 1)
return result;
result = test4 (); //good code
if (result == 1)
return result;
result = test5 (); //good code
if (result == 1)
return result;
result = test6 (); //good code
//test7 (); //bad code don't use (Causes Access Violation)
result = test8 ();
return result;
// result will be zero if the machine is real, 1 if it is virtual, and 2 if
it is impossible to tell.
}
Sorry post has reformatted the code. Any comments or help greatly
appreciated,
Pete.
--