Due to some comments on my previous post (http://www.openrce.org/blog/view/1025/Old_new_Virtual_Machine_detection_method.) , I decided to write a simple tool and do some more research - just to check the exceptions generated by more (different) VMs on different platforms and processors (IA-32 / x64).
There are some new interesting facts, hehe ;>

Firstly, I launched the test program under Windows XP and Vista on a 64bit processor and the log looked like this:

14 bytes long: no exception
15 bytes - 0xc0000005 Exception
16 bytes - 0xc0000005 Exception
17 bytes - 0xc0000005 Exception
18 bytes - 0xc0000005 Exception
19 bytes - 0xc0000005 Exception
20 bytes - 0xc0000005 Exception
21 bytes - 0xc0000005 Exception
22 bytes - 0xc0000005 Exception
23 bytes - 0xc0000005 Exception


There's no Illegal Instruction exception generated anymore on x64 (tested on instructions up to 100 bytes long), huh.
The processors that the tests were made on are:

AuthenticAMD athlon x2 6000+ and Intel(R) Core(TM)2 Quad CPU Q6600 @ 2.40GHz

Next then, I ran PrefTest (the tool name itself) on two Virtual Machines, using the same computers as before, and the results were different ;p

15 bytes - 0xc0000005 Exception
16 bytes - 0xc0000005 Exception
17 bytes - 0xc0000005 Exception
18 bytes - 0xc0000005 Exception
19 bytes - 0xc0000005 Exception
20 bytes - 0xc0000005 Exception
21 bytes - 0xc000001d Exception
22 bytes - 0xc000001d Exception
and so on...


Seems that these tested VMs change the exception value to stay undetected instead of just letting the real processor generate one.
To be precise, the log which part is shown above, was generated by PrefTest running on VMWare Workstation 6.0.2 build 59824 and VirtualBox 1.5.2.

The conclusion is that VMs modify the exceptions' types by hand (I think they do, but it's worth confirming), which is not a very good idea as they are still not the same ;>
The real processor's architecture should be taken into account to avoid such differences

Special thanks to GynvaelColdwind and omeg for helping me with this little research ;-)

And the PrefTest tool source code (isn't really pretty, but what is important, it works):

Code:
.586
.model flat, stdcall
assume fs:flat
option casemap:none

include \masm32\include\windows.inc
include \masm32\include\kernel32.inc
include \masm32\include\user32.inc
include \masm32\include\gdi32.inc
include \masm32\include\msvcrt.inc
includelib \masm32\lib\kernel32.lib
includelib \masm32\lib\user32.lib
includelib \masm32\lib\gdi32.lib
includelib \masm32\lib\msvcrt.lib


.data
OldAttr dd 0
TempVal dd 0
format1 db '%d bytes long: no exception',0ah,0
format2 db '%d bytes - 0x%.8x Exception',0ah,0

Eip     dd 0
Pointer dd 0

.code
start:

  call @F
@@:
  pop eax ; EAX <--- EIP

_test:
  jmp _protect
  db 100 dup (90h)
  jmp _return

_protect:
  inc eax
  inc eax
  inc eax

  ; Eip     - Esi
  ; Pointer - Edi
  mov esi, eax
  mov edi, eax
  mov [Eip], esi
  mov [Pointer], edi

  invoke VirtualProtect, esi,100,PAGE_EXECUTE_READWRITE,offset OldAttr

_loop:

  mov byte ptr [edi],    03eh
  mov byte ptr [edi+1],  0c6h
  mov byte ptr [edi+2],  05
  mov dword ptr [edi+3], offset TempVal
  mov byte ptr [edi+7],  0

  inc edi
  inc dword ptr [Pointer]
  jmp _thread

_start:
  ; SEH
  push offset _handler
  push dword ptr fs:[0]
  mov dword ptr fs:[0], esp
  
  jmp [Eip]

_thread:
  invoke CreateThread, NULL, 0, offset _start, 0, 0, 0
  invoke WaitForSingleObject, eax, INFINITE
  jmp _loop

_return:
  mov esi, [Eip]
  mov edi, [Pointer] 

  mov eax, edi
  sub eax, esi
  add eax, 6

  invoke _imp__printf, offset format1, eax
  invoke ExitThread, 0

_handler:
  mov esi, [Eip]
  mov edi, [Pointer] 

  mov eax, edi
  sub eax, esi
  cmp eax, 90
  jge _end
  add eax, 6

  mov edx, [esp+4]
  mov edx, [edx]
  invoke _imp__printf, offset format2, eax, edx

  invoke ExitThread, 0

_end:
  invoke ExitProcess, 0
    
end start
https://www.openrce.org/blog/view/1029/Virtual_Machine_detection_method_cd.