www.pudn.com > vmdetect.rar > vmdetect.cpp
// VMDetect // http://www.offensivecomputing.net/ // Written by Danny Quist // Copyright 2006 Offensive Computing #include < windows.h> #include// Generic Checks int ldtCheck(void); int mswCheck(void); // VM Specific Checks int vmwareCheck(void); int vpcCheck(void); enum { NATIV = 0x00, VMEMU = 0x01, VMVMWARE = 0x02, VMVPC = 0x04, VMNOEMU = 0x08 }; int main(int argc, char **argv) { int isvmstat = 0; int vmwareversion = 0; unsigned char rc = 0; if( rc = ldtCheck()) { isvmstat |= VMNOEMU; mswCheck(); } else if ( rc = mswCheck() ) isvmstat |= VMEMU; if ( vmwareversion = vmwareCheck() ) isvmstat |= VMVMWARE; if ( rc = vpcCheck() ) isvmstat |= VMVPC; if (!isvmstat) printf("Native machine detected\n"); else { if (isvmstat & VMVMWARE) printf("VMWare version %d detected\n", vmwareversion); else if (isvmstat & VMVPC) printf("Virtual PC detected\n"); if (isvmstat & VMEMU) printf("Fully emulated virtual machine detected\n"); else if (isvmstat & VMNOEMU) printf("Virtual machine detected without emulation\n"); } return 0; } // Fails when emulation is turned off int ldtCheck() { unsigned char m[2]; __asm sldt m; printf("LDT: %2.2x%2.2x\n", m[0], m[1]); return (m[0] != 0x00 && m[1] != 0x00) ? 1 : 0; } // From http://chitchat.at.infoseek.co.jp/vmware/backdoor.html int vmwareCheck(void) { int rc = 0; __try { __asm { mov eax, 'VMXh' mov ebx, 0; // any value but not the MAGIC VALUE mov ecx, 0xA // get VMWare version mov edx, 'VX' // port number in eax, dx; // read port cmp ebx, 'VMXh' // is it a reply from VMWare? jne notVmware jmp isVmware notVmware: mov rc, 0 jmp done isVmware: mov rc, eax // on return EAX returns the version done: } } __except(EXCEPTION_EXECUTE_HANDLER) { rc = 0; } return rc; } // From Elias Bachaalany's Codeproject.com post: // http://www.codeproject.com/system/VmDetect.asp DWORD __forceinline IsInsideVPC_exceptionFilter(LPEXCEPTION_POINTERS ep) { PCONTEXT ctx = ep->ContextRecord; ctx->Ebx = -1; // Not running VPC ctx->Eip += 4; // skip past the "call VPC" opcodes return EXCEPTION_CONTINUE_EXECUTION; // we can safely resume execution since we skipped faulty instruction } // From Elias Bachaalany's Codeproject.com post: // http://www.codeproject.com/system/VmDetect.asp int vpcCheck(void) { int rc = 0; __try { __asm { mov ebx, 0; // It will stay ZERO if VPC is running mov eax, 1; // VPC function number // call VPC __emit 0Fh; __emit 3Fh; __emit 07h; __emit 0Bh; test ebx, ebx; setz [rc]; } } // The except block shouldn't get triggered if VPC is running!! __except(IsInsideVPC_exceptionFilter(GetExceptionInformation())) { rc = 0; } return rc; } // This only returns a valid check when running inside of vmware, // and the LDT check has failed. // There are those out there that will say "the SMSW only returns two bytes" // and you would be right. If you read the Intel Software developer's manual // it states: // // SMSW r32/m16 // Store machine status word in low-order 16 // bits of r32/m16; high-order 16 bits of r32 // are undefined. // // The key is the undefined high order bits. The key to the detection is seeing what // the Intel processor actually puts in the undefined area. Experimentation // showed that the high order bits were always set to 0x8001. On a fully // emulated VMWare session (acceleration turned off) the value always // reflected the initial value. // // This provides the signature method for identifying a fully emulated VMware // session without having to invoke any of the VMWare specific function calls. int mswCheck(void) { int rc = 0; unsigned int reax = 0; __asm { mov eax, 0xCCCCCCCC; // This is the magic value smsw eax; mov DWORD PTR [reax], eax; } printf("MSW: %2.2x%2.2x%2.2x%2.2x\n", (reax >> 24) & 0xFF, (reax >> 16) & 0xFF, (reax >> 8) & 0xFF, reax & 0xFF); // If the high order bits are still 0xCC, then we are in a VMWare session // with emulation turned off. if ( (( (reax >> 24) & 0xFF ) == 0xcc) && (( (reax >> 16) & 0xFF ) == 0xcc)) rc = 1; else rc = 0; return rc; }