Vincent Mussot and I implemented new virtualization counter-countermeasures in puppetmaster. This time we can detect and thwart 6 tests out of 7 in ScoopyNG. In addition to the SIDT test, we counter the SLDT, SGDT and STR techniques in a similar way: instrument the binary until one of these instructions is found, intercept the memory address it writes to and patch the return value.
The 2 other tests use the VMware backdoor (the in eax instruction, with a magic value in eax and edx). We thwart it by detecting the backdoor trigger, and changing the magic values (this way an exception is raised, as if there were no backdoor). We then restore the magic values to add a little bit of stealth.
You can compile and run puppetmaster with the latest version (27887) of Pin on Windows and Linux. The makefile for the free version of Visual C++ is given below.
// puppetmaster.cpp // Usage: pin -t <puppetmaster.dll> -- <binary> [arguments]\n // Currently supported anti-virtualisation techniques: SIDT, SLDT, SGDT, STR, VMWare channel // works with pin-2.6-27887-msvc9 #include <string> #include "pin.H" int needRestore = 0; VOID poisonSIDT(ADDRINT memIp) { char *data = (char *)memIp; unsigned int* m = (unsigned int *)(data+2); *m = 0xd00dbeef; // if ((idt_base >> 24) == 0xff) -> vmware detected } void poisonSLDT(ADDRINT memIp) { char *data = (char *)memIp; unsigned int* m = (unsigned int *)(data); *m = 0xdead0000; // if (ldt_base != 0xdead0000) -> vmware detected } void poisonSGDT(ADDRINT memIp) { char *data = (char *)memIp; unsigned int* m = (unsigned int *)(data+2); *m = 0xdeadbabe; // if ((gdt_base >> 24) == 0xff) -> vmware detected } void poisonSTR(ADDRINT memIp) { char *data = (char *)memIp; unsigned int* m = (unsigned int *)(data); *m = 0xbebaadde; // if ((mem[0] == 0x00) && (mem[1] == 0x40)) -> vmware detected } void poisonVMWareChannel() { unsigned int EAX_save; unsigned short int DX_save; __asm { mov EAX_save, eax mov DX_save, dx } if ((EAX_save == 0x564D5868) && (DX_save == 0x5658)){ __asm { mov dx, 0x0004 } needRestore = 1; } else needRestore = 0; } void restoreVMWareChannel() { if (needRestore == 1) { __asm { mov eax, 0x564D5868 mov dx, 0x5658 } needRestore = 0; } } VOID Instruction(INS ins, VOID *v) { string buffer = INS_Disassemble(ins); if (buffer.substr(0,4) == "sidt") INS_InsertCall(ins, IPOINT_AFTER, (AFUNPTR)poisonSIDT, IARG_MEMORYWRITE_EA, IARG_END); else if (buffer.substr(0,4) == "sldt") INS_InsertCall(ins, IPOINT_AFTER, (AFUNPTR)poisonSLDT, IARG_MEMORYWRITE_EA, IARG_END); else if (buffer.substr(0,4) == "sgdt") INS_InsertCall(ins, IPOINT_AFTER, (AFUNPTR)poisonSGDT, IARG_MEMORYWRITE_EA, IARG_END); else if (buffer.substr(0,3) == "str") INS_InsertCall(ins, IPOINT_AFTER, (AFUNPTR)poisonSTR, IARG_MEMORYWRITE_EA, IARG_END); else if (buffer.substr(0,6) == "in eax") { INS_InsertCall(ins, IPOINT_BEFORE, (AFUNPTR)poisonVMWareChannel, IARG_END); INS_InsertCall(ins, IPOINT_AFTER, (AFUNPTR)restoreVMWareChannel, IARG_END); } } int main(int argc, char * argv[]) { PIN_Init(argc, argv); INS_AddInstrumentFunction(Instruction, 0); PIN_StartProgram(); return 0; }
Here is the Nmakefile for the Nmake utility:
# Nmakefile ###################################################################################### # This is the NMAKE file for building and testing PIN toos contained in one of the # subdirectories of the PinTool project or PIN kit. # # For description of targets and options, see Nmakefile in the root directory. ###################################################################################### !if "$(PIN_HOME)"=="" PIN_HOME=.. !endif # Define tools to be buit and tested ###################################################################################### COMMON_TOOLS=puppetmaster.dll # Include building and testing rules from the root Nmakefile. ###################################################################################### INCLUDE_SUB_RULES=1 !INCLUDE $(PIN_HOME)\Nmakefile
Build instructions:
- download and install Pin and Visual C++
- under $PIN_HOME\source\tools, create a puppetmaster directory
- put puppetmaster.cpp and the Nmakefile in that directory
- from that directory, run ..\nmake.bat puppetmaster.dll
Now you can run it and use your newly acquired ninja skills on ScoopyNG:
<pre>C:\pin-2.6-27887-msvc9-ia32_intel64-windows\source\tools\puppetmaster>pin -t obj-ia32\puppetmaster.dll -- ScoopyNG.exe #################################################### :: ScoopyNG - The VMware Detection Tool :: :: Windows version v1.0 :: [+] Test 1: IDT IDT base: 0xd00dbeef Result : Native OS [+] Test 2: LDT LDT base: 0xdead0000 Result : Native OS [+] Test 3: GDT GDT base: 0xdeadbabe Result : Native OS [+] Test 4: STR STR base: 0xdeadbabe Result : Native OS [+] Test 5: VMware "get version" command Result : Native OS [+] Test 6: VMware "get memory size" command Result : Native OS :: tk, 2008 :: :: [ www.trapkit.de ] :: ####################################################
Note: we do not support the last test in ScoopyNG because Pin does not currently support far rets in different code segments. But as far as I can tell the bug that this last test uses has been patched, I was not able to trigger it. It should probably be considered deprecated.