Any Ideas, please?


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 &lt;windows.h&gt;

//#include &lt;Tlhelp32.h&gt;

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.
--
 
Ad

Advertisements

I

Ian Collins

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).

Hang on, it looks like you have something windows specific going on.
You'll have more luck on one of the windows groups.
 
J

Jorgen Grahn

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)

Note: you're not really compiling cleanly if you get warnings which
you don't understand. Warnings usually tell you something is wrong,
even if the program seems to work correctly.

The actual code seems so Windows-specific and contains so much x86
assembly that I couldn't have commented on it even if it was formatted
properly. Sorry.

/Jorgen
 
P

Pete Dashwood

Jorgen said:
Note: you're not really compiling cleanly if you get warnings which
you don't understand. Warnings usually tell you something is wrong,
even if the program seems to work correctly.

Exactly, that's why I asked for help :)
The actual code seems so Windows-specific and contains so much x86
assembly that I couldn't have commented on it even if it was formatted
properly. Sorry.

Never Mind. I do appreciate your time. Thanks.

Pete
 
Ad

Advertisements

P

Pete Dashwood

Ian said:
Hang on, it looks like you have something windows specific going on.
You'll have more luck on one of the windows groups.

Sorry, Ididn't realise that might be a problem.

Thanks for yur response;I'll look for a Windows oriented group.

Pete.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top