handling exceptions at the OS level - Detecting VMWare

Started by MikeT, December 13, 2009, 10:20:14 PM

Previous topic - Next topic

MikeT

In converting some code like this:

http://www.delphi3000.com/articles/article%5F4135.asp?SK=
or this
http://www.codeproject.com/KB/system/VmDetect.aspx
or this
http://www.powerbasic.com/support/pbforums/showthread.php?t=24024

I do not understand much about how to handle exceptions at the OS level
This is the best article I've found so far:
http://www.jorgon.freeserve.co.uk/Except/Except.htm

and MSDN documents the OS functions here:
http://msdn.microsoft.com/en-us/library/aa363082(VS.85).aspx

The powerbasic code for example, works on Win XP an server 2003, but not on Server 2008 or win7, so first I need to understand more about how to implement a bullet proof exception handler. What is a good approaoh in the context of the VMware detection?

ecube

everything you're ask has been posted on this forum before, just search, the session handlin stuff probably be under SEH

MikeT

Im sorry I am not sure what topics I should be looking for. I did a thorough search of this forum, but I am not clear what I am looking for.
under the search term you suggested SEH I found nothing with the SMF serarch engine, and three with google that seemed to b unrelated
http://www.masm32.com/board/index.php?PHPSESSID=c80cbbbf6e6cf2b30889977a426f07f9&action=printpage;topic=10925.0
http://www.masm32.com/board/index.php?PHPSESSID=63414a5b6ee6899dbcb9080c0ec4bcf3&action=printpage;topic=12183.0
http://www.masm32.com/board/index.php?PHPSESSID=c675bbbd7468cdc0c9aef478bf63fd63&action=printpage;topic=10848.0

I'm not trying to be lazy, i'm just not sure what I'm looking for. If you could give me just a little more to work with?

japheth

Quote from: MikeT on December 21, 2009, 01:47:07 AM
Im sorry I am not sure what topics I should be looking for. I did a thorough search of this forum, but I am not clear what I am looking for.

I'm also not quite sure if it is possible to detect VMware from a ring-3 Win32 application. But if it is possible, then the following code "should" work:


;--- detecting VMware

.386
.MODEL FLAT, stdcall
option casemap:none

GetStdHandle proto stdcall :DWORD
WriteConsoleA proto stdcall :DWORD, :DWORD, :DWORD, :DWORD, :DWORD
ExitProcess proto stdcall :DWORD
wvsprintfA proto stdcall :ptr, :ptr, :ptr

STD_OUTPUT_HANDLE equ -11

CONTEXT struct
dd ? ;context flags
dd 6 dup (?) ;DRx regs
db 112 dup (?) ;FP status
dd 4 dup (?) ;segment regs
rEdi dd ?
rEsi dd ?
rEbx dd ?
rEdx dd ?
rEcx dd ?
rEax dd ?
rEbp dd ?
rEip dd ?
SegCs dd ?
EFlags dd ?
rEsp dd ?
SegSs dd ?
CONTEXT ends

CStr macro text:VARARG
local x
.const
x db text,0
.code
exitm <offset x>
endm

.code

printf proc c uses ebx pszFormat:ptr byte, args:VARARG

local dwWritten:dword
local szText[256]:byte

invoke GetStdHandle, STD_OUTPUT_HANDLE
mov ebx, eax
invoke wvsprintfA, addr szText, pszFormat, addr args
lea ecx, dwWritten
invoke WriteConsoleA, ebx, addr szText, eax, ecx, 0
ret
align 4

printf endp

VMware proc

assume fs:nothing

xor edx,edx
push offset myexc
push fs:[edx]
mov fs:[edx],esp

mov eax, 564D5868h ;magic number (="VMXh")
mov cx, 000ah ;command number (000A=get VMware version)
xor ebx,ebx ;command specific parameter
mov dx, 5658h ;VMware IO port (="VX")
in eax,dx ;"returns" version number in EAX
donebrp:
cmp ebx, 564D5868h ;and magic number in EBX (="VMXh")
setz al
movzx eax,al
pop fs:[0]
add esp,4
ret
myexc:
mov eax, [esp+12] ;get context
mov [eax].CONTEXT.rEip, offset donebrp
xor eax, eax ;== _XCPT_CONTINUE_EXECUTION
retn
align 4
VMware endp

start:
invoke VMware
invoke printf, CStr("VMware()=%u",10), eax
invoke ExitProcess, 0

END start

ecube

It's possible to detect vmware in ring3, here's simple code to do it, along with easy SEH macro's, the title of the thread ironically is SEH

http://www.masm32.com/board/index.php?topic=11065.msg81886#msg81886

hutch--

Cube,

Thats not bad looking SEH code, have you bothered to give it a hammering to see what it does and what it will handle ?
Download site for MASM32      New MASM Forum
https://masm32.com          https://masm32.com/board/index.php

MichaelW

#6
Here is another simple and very limited set of macros that I think will work for this, along with a test app.

;==============================================================================

LPEXCEPTION_POINTERS typedef ptr EXCEPTION_POINTERS

;-----------------------------------------------------------------
; This macro sets the top-level exception filter for the calling
; process to our try_filter procedure, so when an unhandled
; exception reaches the UnhandledExceptionFilter function, and
; the process is not being debugged, the function will call our
; procedure. The return_address parameter specifies the address
; of a label were execution will continue if an exception occurs.
; Use this macro to begin a guarded section of code.
;-----------------------------------------------------------------

try_begin macro return_address
    push return_address
    pop _exception_return_address_
    invoke SetUnhandledExceptionFilter, try_filter
    mov _previous_exception_filter_, eax
endm

;----------------------------------------------------------------
; This macro sets the top-level exception filter for the calling
; process to what it was before the try_begin macro changed it.
; Use this macro to end a guarded section of code.
;----------------------------------------------------------------

try_end macro
    invoke SetUnhandledExceptionFilter, _previous_exception_filter_
endm

;==============================================================================
    .data
        _exception_return_address_  dd 0
        _previous_exception_filter_ dd 0
        exception_record            EXCEPTION_RECORD <>
    .code
;==============================================================================

;---------------------------------------------------
; This procedure is our top-level exception filter.
;---------------------------------------------------

try_filter proc lpexception_pointers:LPEXCEPTION_POINTERS

    ;--------------------------------------------------------------
    ; Copy the entire EXCEPTION_RECORD structure to global memory.
    ;--------------------------------------------------------------

    mov edx, lpexception_pointers
    mov ecx, [edx].EXCEPTION_POINTERS.pExceptionRecord
    mov edx, offset exception_record
    DISP=0
    repeat (sizeof EXCEPTION_RECORD) / 4
        mov eax, [ecx+DISP]
        mov [edx+DISP], eax
        DISP=DISP+4
    endm

    ;------------------------------------------------------------------
    ; Modify the EIP member of the CONTEXT structure so execution will
    ; continue at the address passed to the try_begin macro, instead
    ; of continuing at the point of the exception (which would cause
    ; the exception to repeat).
    ;------------------------------------------------------------------

    mov edx, lpexception_pointers
    mov eax, [edx].EXCEPTION_POINTERS.ContextRecord
    push _exception_return_address_
    pop [eax].CONTEXT.regEip

    ;------------------------------------------------------------------------
    ; Returning EXCEPTION_CONTINUE_EXECUTION to the UnhandledExceptionFilter
    ; function will cause it to return and continue execution from the point
    ; specified in the EIP member of the CONTEXT structure.
    ;------------------------------------------------------------------------

    return EXCEPTION_CONTINUE_EXECUTION

try_filter endp

;==============================================================================


;==============================================================================
    include \masm32\include\masm32rt.inc
    include try.asm
;==============================================================================
    .data
    .code
;==============================================================================

PEXCEPTION_RECORD typedef ptr EXCEPTION_RECORD

EXCEPTION_NONCONTINUABLE_EXCEPTION  equ 0C0000025h
EXCEPTION_STACK_OVERFLOW            equ 0C00000FDh
EXCEPTION_INVALID_DISPOSITION       equ 0C0000026h
EXCEPTION_GUARD_PAGE                equ 080000001h
EXCEPTION_INVALID_HANDLE            equ 0C0000008h

ShowException proc uses ebx per:PEXCEPTION_RECORD
    mov ebx, per
    SWITCH [ebx].EXCEPTION_RECORD.ExceptionCode
        CASE EXCEPTION_ACCESS_VIOLATION
            print "EXCEPTION_ACCESS_VIOLATION"
        CASE EXCEPTION_DATATYPE_MISALIGNMENT
            print "EXCEPTION_DATATYPE_MISALIGNMENT"
        CASE EXCEPTION_BREAKPOINT
            print "EXCEPTION_BREAKPOINT"
        CASE EXCEPTION_SINGLE_STEP
            print "EXCEPTION_SINGLE_STEP"
        CASE EXCEPTION_ARRAY_BOUNDS_EXCEEDED
            print "EXCEPTION_ARRAY_BOUNDS_EXCEEDED"
        CASE EXCEPTION_FLT_DENORMAL_OPERAND
            print "EXCEPTION_FLT_DENORMAL_OPERAND"
        CASE EXCEPTION_FLT_DIVIDE_BY_ZERO
            print "EXCEPTION_FLT_DIVIDE_BY_ZERO"
        CASE EXCEPTION_FLT_INEXACT_RESULT
            print "EXCEPTION_FLT_INEXACT_RESULT"
        CASE EXCEPTION_FLT_INVALID_OPERATION
            print "EXCEPTION_FLT_INVALID_OPERATION"
        CASE EXCEPTION_FLT_OVERFLOW
            print "EXCEPTION_FLT_OVERFLOW"
        CASE EXCEPTION_FLT_STACK_CHECK
            print "EXCEPTION_FLT_STACK_CHECK"
        CASE EXCEPTION_FLT_UNDERFLOW
            print "EXCEPTION_FLT_UNDERFLOW"
        CASE EXCEPTION_INT_DIVIDE_BY_ZERO
            print "EXCEPTION_INT_DIVIDE_BY_ZERO"
        CASE EXCEPTION_INT_OVERFLOW
            print "EXCEPTION_INT_OVERFLOW"
        CASE EXCEPTION_PRIV_INSTRUCTION
            print "EXCEPTION_PRIV_INSTRUCTION"
        CASE EXCEPTION_IN_PAGE_ERROR
            print "EXCEPTION_IN_PAGE_ERROR"
        CASE EXCEPTION_ILLEGAL_INSTRUCTION
            print "EXCEPTION_ILLEGAL_INSTRUCTION"
        CASE EXCEPTION_NONCONTINUABLE_EXCEPTION
            print "EXCEPTION_NONCONTINUABLE_EXCEPTION"
        CASE EXCEPTION_STACK_OVERFLOW
            print "EXCEPTION_STACK_OVERFLOW"
        CASE EXCEPTION_INVALID_DISPOSITION
            print "EXCEPTION_INVALID_DISPOSITION"
        CASE EXCEPTION_GUARD_PAGE
            print "EXCEPTION_GUARD_PAGE"
        CASE EXCEPTION_INVALID_HANDLE
            print "EXCEPTION_INVALID_HANDLE"
        DEFAULT
            print "exception code "
            print hex$([ebx].EXCEPTION_RECORD.ExceptionCode)
    ENDSW
    print " @ "
    print hex$([ebx].EXCEPTION_RECORD.ExceptionAddress),"h",13,10
    ret
ShowException endp

;==============================================================================

IsVMwarePresent proc
    try_begin x
    mov eax, 564D5868h
    xor ebx, ebx
    mov ecx, 0000000Ah
    mov edx, 00005658h
    in  eax, dx
    cmp ebx, 564D5868h
    jne x
    try_end
    mov eax, 1
    ret
  x:
    invoke ShowException, addr exception_record
    try_end
    xor eax, eax
    ret
IsVMwarePresent endp

;==============================================================================
start:
;==============================================================================

    try_begin x1
    mov ecx, 1
    xor edx, edx
  try1:
    div ecx
    print "no exception",13,10
    jmp @f
  x1:
    invoke ShowException, addr exception_record
    print hex$(try1),"h",13,10
  @@:
    try_end

    try_begin x2
    xor ecx, ecx
    xor edx, edx
  try2:
    div ecx
    print "no exception",13,10
    jmp @f
  x2:
    invoke ShowException, addr exception_record
    print hex$(try2),"h",13,10
  @@:
    try_end

    try_begin x3
    xor eax, eax
  try3:
    mov eax, [eax]
    print "no exception",13,10
    jmp @f
  x3:
    invoke ShowException, addr exception_record
    print hex$(try3),"h",13,10
  @@:
    try_end

    try_begin x4
  try4:
    dd 0ffffffffh
    print "no exception",13,10
    jmp @f
  x4:
    invoke ShowException, addr exception_record
    print hex$(try4),"h",13,10
  @@:
    try_end

    try_begin x5
  try5:
    int 3
    print "no exception",13,10
    jmp @f
  x5:
    invoke ShowException, addr exception_record
    print hex$(try5),"h",13,10
  @@:
    try_end

    try_begin x6
  try6:
    invoke RaiseException, 1234h, 0, 0, 0
    print "no exception",13,10,13,10
    jmp @f
  x6:
    invoke ShowException, addr exception_record
    print hex$(try6),"h",13,10,13,10
  @@:
    try_end

    invoke IsVMwarePresent
    print str$(eax),13,10,13,10

    inkey "Press any key to exit..."
    exit

;==============================================================================
end start


no exception
EXCEPTION_INT_DIVIDE_BY_ZERO @ 004013B5h
004013B5h
EXCEPTION_ACCESS_VIOLATION @ 00401421h
00401421h
EXCEPTION_ILLEGAL_INSTRUCTION @ 0040148Bh
0040148Bh
EXCEPTION_BREAKPOINT @ 004014F7h
004014F7h
exception code 00001234 @ 7C59BCB1h
00401560h

EXCEPTION_PRIV_INSTRUCTION @ 004012F4h
0
eschew obfuscation

ecube

Quote from: hutch-- on December 21, 2009, 11:44:22 PM
Cube,

Thats not bad looking SEH code, have you bothered to give it a hammering to see what it does and what it will handle ?

I haven't used it extensively but as BlackVortex mentioned is doesn't change any registers, and the times I have used it i've had no problems.

dedndave

maybe what Hutch meant was - has it been tested on a variety of OS's
i can only test it on XP
Mike was looking for something that will work on all windows OS's
the one he has doesn't work under server 2008 or win7

ecube

ill test on win7 real quick

update, tested both simotaniously, seems to work fine

update 2, works on windows xp pro x64 too

update 3, works on windows vista home


MikeT

>the title of the thread ironically is SEH
Urgh... now I feel like an idiot. You are right. I was looking within the body of the search results which returned a lot of cloSEHandle etc.
Thank you for your patience. That says a lot. Thank you for that code. I am going to study it.

hutch--

Michael,

Thanks for the example, I just copied and built it and it works perfectly.
Download site for MASM32      New MASM Forum
https://masm32.com          https://masm32.com/board/index.php