Flag: Tornado! Hurricane!

Blogs >> j00ru's Blog

Created: Sunday, January 20 2008 11:37.16 CST Modified: Sunday, January 20 2008 12:10.44 CST
Printer Friendly ...
Virtual Machine detection method cd.
Author: j00ru # Views: 7826

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):

.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


Blog Comments
sovietskicpu Posted: Sunday, January 20 2008 14:50.22 CST
Man I think you still don't get the thing out hehe..

"Seems that these tested VMs change the exception value to stay undetected instead of just letting the real processor generate one."

VirtualBox is an open source so why not looking at it first ?

j00ru Posted: Sunday, January 20 2008 15:57.07 CST
sovietskicpu: Yeah you're right, I'm gonna check it ;> just posted some more info from experiments but... I'll try to confirm everything I wrote ;>

GynvaelColdwind Posted: Monday, January 21 2008 01:28.52 CST
@sovietskicpu
Hmm I don't see your point. The exceptions send to the program on both guest and host PC differ, that is a fact. And meanwhile, both the guest and host OS show the same CPU Type.
If the type is the same, but the exceptions differ, this can be used to check if the guest machine is in fact a guest machine.
Which part of this troubles u ?

sovietskicpu Posted: Monday, January 21 2008 04:30.24 CST
GynvaelColdwind,

"Which part of this troubles u ?"

hehe I am not in troubles :p

Looking at this : "Seems that these tested VMs change the exception value to stay undetected instead of just letting the real processor generate one." made me suggest to j00ru to first take a look at VirtualBox sources.

GynvaelColdwind, with all my respect man, you still won't see my point if you think this way.Please go "study" Boch/QEMU/VirtualBox sources code, try to better understand the emulation technologie in depth then we will make a rich and good discussion about VM Detections subtilities.

The difference in the returned exception value is not due to any supervisor intentional modifications but it is due to the ILL handling mechanism of instructions PREFIXES by the disassemblers engines of the tested Virtual Machines.

GynvaelColdwind Posted: Monday, January 21 2008 05:37.58 CST
sovietskicpu,

I'll guess I'll take a look in spare time at the sources (well, I know Bochs source quite well).

Anyway, I see your point, but please note that whatever we call the place that is wrong in the virtual machine, should it be the exception handling mechanism (as j00ru has written in the post), or the disassembler mechanism (as You stated in your post, and I tend to agree with u that it is more likely), it does not change the fact that this works the way it does, and can be used to detect the virtual machine. And just that is my point.

sovietskicpu Posted: Monday, January 21 2008 08:20.49 CST
I absolutly agree with you in that !!

j00ru Posted: Monday, January 21 2008 10:05.40 CST
sovietskicpu: once more to tell, You are right ;>
My purpose was to prove that VMWare/VirtualPC/others can be detected with this method as well as AV emulators (in response to your comment on my previous post) ;>
VMs modifying the exception code was just an assumption, nothing really meaningful ;-) But the fact is that exceptions differ, doesn't matter why, when it comes to detection ;>

sovietskicpu Posted: Monday, January 21 2008 10:45.53 CST
j00ru,

you are right too, I dont deny in anyway your discoveries. I think your code will be soon included in some of the incoming Rootkits/VX and I bet that some guys from the AV scene, snooping around, will begin to add your VM detection algo to their stupid heuristic sensors hehe...

"doesn't matter why, when it comes to detection"

the WHY always really matter when it comes to future detections. You are a reverser, so the WHY is the key of everythings... hehe I was kidding :p

j00ru Posted: Monday, January 21 2008 10:59.10 CST
Hahaha, of course ;)
What I meant was only that even without the knowledge of how something works, it does ;> but WHY is the key of everything indeed ;)

PeterFerrie Posted: Tuesday, January 22 2008 21:44.12 CST
See more examples here:
http://pferrie.tripod.com/papers/attacks.pdf
and
http://pferrie.tripod.com/papers/attacks2.pdf

These are getting old now.  I must finish v3 one day.

Also some funny behaviours here:
http://www.symantec.com/enterprise/security_response/weblog/2007/01/locked_and_loaded.html
and here:
http://www.symantec.com/enterprise/security_response/weblog/2007/02/x86_fetchdecode_anomalies.html

sovietskicpu Posted: Wednesday, January 23 2008 04:06.32 CST
Heuh ??? Damn it !!! the real Peter Ferrie from SYMANTEC is here !!

"I bet that some guys from the AV scene, snooping around, will begin to add your VM detection algo to their stupid heuristic sensors hehe..." : ==> Has already did its effect very quickly i think hahaha...

attacks.pdf and attacks1.pdf I already know them by heart btw :p

Is there some jobs openings in symantec ???

PeterFerrie Posted: Wednesday, January 23 2008 18:04.57 CST
There are always openings. :-)

Regarding the exception that is generated, it's a Windows bug, not a CPU behaviour.
The 0xc0000005 (int 0d) is the proper one.

sovietskicpu Posted: Wednesday, January 23 2008 18:28.40 CST
heuh ? any explanation of this ?

EliCZ Posted: Thursday, January 24 2008 07:31.32 CST
> See more examples here:
> http://pferrie.tripod.com/papers/attacks.pdf
> and
> http://pferrie.tripod.com/papers/attacks2.pdf

> These are getting old now.  I must finish v3 one day.

Cui bono?

PeterFerrie Posted: Thursday, January 24 2008 10:04.10 CST
sovietskicpu: Windows sees the int 0dh exception and examines the instruction that caused it.  After seeing so many prefixes, it gives up and issues an improper int 06h.  It is similar to the invalid lock: exception when a 0f0h appears inside the instruction, even if it is not a prefix (the link to that is in my earlier comment).

EliCZ: it's for all kinds of people.  Some fix their bugs and improve their anti-detection.  Some people gain new insights into how some VMs work.  Of course, some people might use it for bad purposes, but it has more good uses than bad ones.  It's a sharing of research.  I think that's important.

GynvaelColdwind Posted: Friday, January 25 2008 13:04.10 CST
@PeterFerrie
"It's a sharing of research.  I think that's important."
Yeah, it is, share it, share it ;>
Btw concealing such papers would be security by obscurity anyway...



Add New Comment
Comment:









There are 31,313 total registered users.


Recently Created Topics
[help] Unpacking VMP...
Mar/12
Reverse Engineering ...
Jul/06
hi!
Jul/01
let 'IDAPython' impo...
Sep/24
set 'IDAPython' as t...
Sep/24
GuessType return une...
Sep/20
About retrieving the...
Sep/07
How to find specific...
Aug/15
How to get data depe...
Jul/07
Identify RVA data in...
May/06


Recent Forum Posts
Finding the procedur...
rolEYder
Question about debbu...
rolEYder
Identify RVA data in...
sohlow
let 'IDAPython' impo...
sohlow
How to find specific...
hackgreti
Problem with ollydbg
sh3dow
How can I write olly...
sh3dow
New LoadMAP plugin v...
mefisto...
Intel pin in loaded ...
djnemo
OOP_RE tool available?
Bl4ckm4n


Recent Blog Entries
halsten
Mar/14
Breaking IonCUBE VM

oleavr
Oct/24
Anatomy of a code tracer

hasherezade
Sep/24
IAT Patcher - new tool for ...

oleavr
Aug/27
CryptoShark: code tracer ba...

oleavr
Jun/25
Build a debugger in 5 minutes

More ...


Recent Blog Comments
nieo on:
Mar/22
IAT Patcher - new tool for ...

djnemo on:
Nov/17
Kernel debugger vs user mod...

acel on:
Nov/14
Kernel debugger vs user mod...

pedram on:
Dec/21
frida.github.io: scriptable...

capadleman on:
Jun/19
Using NtCreateThreadEx for ...

More ...


Imagery
SoySauce Blueprint
Jun 6, 2008

[+] expand

View Gallery (11) / Submit