Page 1 of 1

Detecting emulator presence...

Posted: Thu Apr 05, 2007 11:17 am
by inflater
Hi guys,
how can I please detect in my kernel, if it's running inside Bochs/QEMU or MS Virtual PC 2007? Is it able in real mode through assembler? If yes, can you post me the code? (ASM would be better, but C is good too.)

Thank you.
inflater

Posted: Thu Apr 05, 2007 11:24 am
by ~
Maybe testing for all incorrect behavior under the emulator, but you would need to find such code that works correctly in Bochs but fails in real hardware. It's a shame that it's appreciated until one figures out it could be used to detect Bochs, and generally gets dropped. Also, such bogus execution gets fixed because anyway it's needed and wouldn't be fun to keep up to date with the new and the outdated bugs.

You will also need a way of recovering from exceptions and misbehavior that could result.

That's the only way I get to think, because anyway emulators are intended to be undetectable for software, so they look exactly as true hardware. Being otherwise would trash the emulation.

Posted: Thu Apr 05, 2007 12:59 pm
by Dex
Here some code hackers use for that job.

Code: Select all

#include <stdio.h> 
inline int idtCheck () 
{ 
unsigned char m[6]; 
__asm sidt m; 
printf("IDTR: %2.2x %2.2x %2.2x %2.2x %2.2x %2.2x\n", m[0], m[1], 
m[2], m[3], m[4], m[5]); 
return (m[5]>0xd0) ? 1 : 0; 
} 
int gdtCheck() 
{ 
unsigned char m[6]; 
__asm sgdt m; 
printf("GDTR: %2.2x %2.2x %2.2x %2.2x %2.2x %2.2x\n", m[0], m[1], 
m[2], m[3], m[4], m[5]); 
return (m[5]>0xd0) ? 1 : 0; 
} 
int ldtCheck() 
{ 
unsigned char m[6]; 
__asm sldt m; 
printf("LDTR: %2.2x %2.2x %2.2x %2.2x %2.2x %2.2x\n", m[0], m[1], 
m[2], m[3], m[4], m[5]); 
return (m[0] != 0x00 && m[1] != 0x00) ? 1 : 0; 
} 
int main(int argc, char * argv[]) 
{ 
idtCheck(); 
gdtCheck(); 
if (ldtCheck()) 
printf("Virtual Machine detected.\n"); 
else 
printf("Native machine detected.\n"); 
return 0; 
}

Posted: Thu Apr 05, 2007 1:03 pm
by ehird
Do all assembler folks not indent?

Posted: Thu Apr 05, 2007 1:08 pm
by ~
I do indent, and the rest of the projects are as well, but maybe less. And of course do more than indenting... what's the point?

By the way, interesting code, and interesting to see what's going on there; but anyway looks like a very simple (and fully reliable?) way of detecting for emulator or true hardware...

Posted: Thu Apr 05, 2007 1:11 pm
by bubach
no, why would you think that? some even do in assembly, for loops and stuff.

Posted: Thu Apr 05, 2007 2:13 pm
by Brynet-Inc
I'm not sure for what emulator the code Dex posted is for.. but It fails in QEMU.

Code: Select all

IDTR: ff 07 60 b2 55 d0
GDTR: ff ff 00 50 37 d3
LDTR: 18 00 00 50 37 d3
Native machine detected.

Posted: Thu Apr 05, 2007 2:34 pm
by Dex
Virtual PC if I remember and i am sure it does not work under linux :( .
So it upto code here, to try it and mod it.

Posted: Thu Apr 05, 2007 2:49 pm
by bubach
Maybe this helps?
Smiddy @ BOS forums wrote:Hi,

I'm sharing code, enjoy!

Code: Select all

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; VM - Detects if we're in a virtual mcahine like Virtual PC, VMWare, or 
;;      Bochs. If there are others, this is where they shall reside for
;;      detecting them.
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

BochsDetectedMessage    db 'Bochs detected',13,10,0
BochsNotDetectedMessage db 'Bochs not detected',13,10,0
BochsOn                 dd 0

DetectBochs:

    mov dx,0E9h
    in al,dx
    
    cmp al,0E9h
    je .InBochs
    mov eax,0
    mov esi,BochsNotDetectedMessage
    jmp .Done
    
.InBochs:

    mov eax,1
    mov esi,BochsDetectedMessage
    
.Done:

    mov [BochsOn],eax
    call PrintString
    
    ret



    ret


align 4
VPCDetectedMessage      db  'Virtual PC Detected',13,10,0
VPCNotDetectedMessage   db  'Virtual PC Not Detected',13,10,0
align 4
VPCOn       dd 0

DetectVPC:

    push ebx
    
    cli                                     ; Turn off interrupts
    mov esi,VPCInvalidOpcodeException       ; Store new Invalid Opcode Exception
    mov eax,6                               ; Invalid Opcode is 6
    call AddExceptionToIDT                  ; Call routine to replace it
    sti                                     ; Turn on interrupts
    
    mov ebx,0                               ; This will stay 0 if VPC running
    mov eax,1                               ; VPC function number
    
.CallVPC:
    
    db 0Fh,3Fh,07h,0Bh                      ; Call VPC
    
    test ebx,ebx
    jz .InVPC
    mov eax,0
    mov esi,VPCNotDetectedMessage
    jmp .Done
    
.InVPC:

    mov eax,1
    mov esi,VPCDetectedMessage
    
.Done:

    mov [VPCOn],eax
    call PrintString
    
    cli
    mov esi,UnhandledINT                    ; Restore original unhandled interrupt
    mov eax,6                               ; Invalid Opcode is 6
    call AddExceptionToIDT
    sti
    
    pop ebx
    
    ret

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; VPCInvalidOpcodeException - replaced invalid opcode exception handler with
;;                             this one to go past the VPC call in the above
;;                             procedure.
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

VPCInvalidOpcodeException:

    mov ebx,-1                              ; Not running VPC
    add DWORD [esp],4                       ; Fix the EIP in stack to skip past call VPC
    
    iret

;---------------------------------
; We need this because ATA
; Identify command is NOT working
; under vmware ;) surprise!
;---------------------------------
align 4
VMWareDetectedMessage       db  'VM Ware Detected',13,10,0
VMWareNotDetectedMessage    db  'VM Ware Not Detected',13,10,0

ALIGN 4
VMWareOn                    dd  0           ; Default = 0 = OFF, 1 = ON

DetectVMWare:
    
    mov eax,564D5868h                       ; 'VMXh'
    mov ebx,12345h                          ; This can be any number, but not 'VMXh'
    mov ecx,00Ah                            ; Get VMWare version
    mov edx,'VX'                            ; Port number
    IN  eax,dx                              ; Read port 5658h
    cmp ebx,564D5868h                       ; Is this from the EAX?
    je .InVMWare                            ; Yes, goto flag it
    mov eax,0
    mov esi,VMWareNotDetectedMessage
    jmp .Done
    
.InVMWare:

    mov eax,1
    mov esi,VMWareDetectedMessage
    
.Done:

    mov [VMWareOn],eax
    call PrintString
    
    ret
I hope you all can use it...
It's also at: http://bos.asmhackers.net/forum/viewtopic.php?id=59

Posted: Thu Apr 05, 2007 6:40 pm
by mystran
Can anybody detect emulators with code running in userspace? :)

Posted: Fri Apr 06, 2007 3:01 am
by Combuster
I can sense an emulator when bochs is emulating an amd64 or anything before the pentium:

It works by checking what flags are touched by an DIV instruction. Bochs and Pentium processors preserve all flags, other processors set the flags in specific ways.

Actually, this method can even tell you the brand of your chip when it doesnt support cpuid, and for that reason it was originally used to detect cyricies. (My kernel uses it for exactly that reason)

However, this will obviously not detect a virtual machine.

Posted: Fri Apr 06, 2007 3:21 am
by inflater
Thanks for your responses and hints! :)

inflater

Posted: Sun Apr 08, 2007 8:35 am
by Daedalus
One other thing to try is looking at the hardware.

For example, most hardware in VMWare has the name "VMWare" tacked onto it - CDROMS, Hard disks, display adaptors, etc.

I'm not sure if Bochs does though ...