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