ScoopyNG

From aldeid
Jump to navigation Jump to search

Description

ScoopyNG is a Proof of Concept (PoC) to detect whether it is run inside VMware. According to the author, it is "able to detect VMware even if "anti-detection-mechanisms" are deployed."

Following tests are performed:

Test Description
Test #1 sidt instruction
Test #2 sldt (Red Pill and No Pill) instructions
Test #3 sgdt intruction
Test #4 str intruction
Test #5 Use the backdoor I/O port 0x0a option
Test #6 Use the backdoor I/O port 0x14 options,
Test #7 This check relies on a bug in older VMware versions running in emulation mode.

Installation

Download link: http://www.trapkit.de/research/vmm/scoopyng/ScoopyNG.zip

Example

Below is the output of ScoopyNG run inside 2 different configurations:

Native OS (Windows 8.1 update 1 64 bit) VMware (Windows 7 SP1 64 bit)
C:\>ScoopyNG.exe


####################################################
::       ScoopyNG - The VMware Detection Tool     ::
::              Windows version v1.0              ::

[+] Test 1: IDT
IDT base: 0xf55bc0c0
Result  : Native OS


[+] Test 2: LDT
LDT base: 0xdead0000
Result  : Native OS


[+] Test 3: GDT
GDT base: 0xf55bc040
Result  : Native OS


[+] Test 4: STR
STR base: 0x40000000
Result  : Native OS


[+] Test 5: VMware "get version" command
Result  : Native OS


[+] Test 6: VMware "get memory size" command
Result  : Native OS


[+] Test 7: VMware emulation mode
Result  : Native OS or VMware without emulation mode
          (enabled acceleration)

::                   tk,  2008                    ::
::               [ www.trapkit.de ]               ::
###################################################
C:\>ScoopyNG.exe


####################################################
::       ScoopyNG - The VMware Detection Tool     ::
::              Windows version v1.0              ::

[+] Test 1: IDT
IDT base: 0x40d0080
Result  : Native OS


[+] Test 2: LDT
LDT base: 0xdead0000
Result  : Native OS


[+] Test 3: GDT
GDT base: 0x40d0000
Result  : Native OS


[+] Test 4: STR
STR base: 0x40000000
Result  : Native OS


[+] Test 5: VMware "get version" command
Result  : VMware detected
Version : Workstation


[+] Test 6: VMware "get memory size" command
Result  : VMware detected


[+] Test 7: VMware emulation mode
Result  : Native OS or VMware without emulation mode
          (enabled acceleration)

::                   tk,  2008                    ::
::               [ www.trapkit.de ]               ::
####################################################

Source code

/* ScoopyNG - The VMware detection tool
 * Version v1.0
 *
 * Tobias Klein, 2008
 * www.trapkit.de
 */

#include <windows.h>
#include <excpt.h>
#include <stdio.h>

#define DEBUG	0
#define EndUserModeAddress (*(UINT_PTR*)0x7FFE02B4)

typedef LONG (NTAPI *NTSETLDTENTRIES)(DWORD, DWORD, DWORD, DWORD, DWORD, DWORD);

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);
}

void
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;
	}

	else {
		printf ("Result  : Native OS\n\n");
		return;
	}
}

void
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;
	}

	else {
		printf ("Result  : VMware detected\n\n");
		return;
	}
}

void
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");
		return;
	}

	else {
		printf ("Result  : Native OS\n\n");
		return;
	}
}

// Alfredo Andrés Omella's (S21sec) STR technique
void
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");
	else
		printf ("Result  : Native OS\n\n");
}

void
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 : ");
			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");
}

void
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");
	else 
		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");
		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
void
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())) { }
}

int
main (void)
{	
	printf ("\n\n####################################################\n");
	printf ("::       ScoopyNG - The VMware Detection Tool     ::\n");
	printf ("::              Windows version v1.0              ::\n\n");
	
	test1 ();
	test2 ();
	test3 ();
	test4 ();
	test5 ();
	test6 ();
	test7 ();

	printf ("::                   tk,  2008                    ::\n");
	printf ("::               [ www.trapkit.de ]               ::\n");
	printf ("####################################################\n\n");

	return 0;
}