Results 1 to 14 of 14

Thread: VMware ring3 detection (RF handling)

  1. #1

    VMware ring3 detection (RF handling)

    Hello,

    Here is one trick to detect vmware discovered by accidance

    I was writing one unpacker, and for me RF was must have to make my unpacker simpler. Unpacker worked great on live system, and then I tried it in vmware, and I got many breaks at same part of the code which should be continued with RF.

    RF from intel manual volume 3, chapter 18:

    Code:
    Because the debug exception for an instruction breakpoint is generated before the
    instruction is executed, if the instruction breakpoint is not removed by the exception
    handler; the processor will detect the instruction breakpoint again when the instruction
    is restarted and generate another debug exception. To prevent looping on an
    instruction breakpoint, the Intel 64 and IA-32 architectures provide the RF flag
    (resume flag) in the EFLAGS register (see Section 2.3, “System Flags and Fields in
    the EFLAGS Register,” in the Intel® 64 and IA-32 Architectures Software Developer’s
    Manual, Volume 3A). When the RF flag is set, the processor ignores instruction
    breakpoints.
    Basically waht debugger would do with break point is:
    - breakpoint reached -> clear breakpoint
    - single step that instruction
    - set breakpoint after singlestep
    - continue execution
    - too much not needed work...

    For DebugRegister breaks on execution, you can simplfy this by setting RF in Eflags, and you don't have to remove your breakpoint on execution.

    So here is how to detect VMWare presence using debug registers due to wrong RF handling:

    Code allocates memory and stores there 0xC3, after that program generates exception to set debug registers. In exception handler code checks if exception occured 1st time (1st debug break) and sets RF (eg. continue execution), after that if exception occurs 2nd time, means that RF wasn't handled and that we have vmware (didn't try with other virtual machines).

    main.c
    Code:
    #include        "defs.h"
    
    PVOID   buffer;
    DWORD   dwExceptionCount;
    
    ULONG   filter(PEXCEPTION_INFO pei){
            PCONTEXT pctx;
            
            pctx = pei->pContext;
            if (dwExceptionCount == 0){
                    dwExceptionCount++;
                    pctx->Dr7 = BPM_LOCAL_EXACT | BPM0_LOCAL_ENABLED;
                    pctx->Dr0 = (DWORD)buffer;
                    pctx->Eip += 2;
                    NtContinue(pctx, FALSE);
            }else if (dwExceptionCount == 1){
                    dwExceptionCount++;
                    pctx->EFlags |= 0x10000;
                    NtContinue(pctx, FALSE);
            }else if (dwExceptionCount == 2){
                    printf("[X] vmware detected\n");
                    ExitProcess(0);
            }
            
            return EXCEPTION_EXECUTE_HANDLER;        
    }
    
    void __declspec(naked) hook_filter(void){
            __asm push      esp
            __asm call      filter
    }
    
    int __cdecl wmain(int argc, wchar_t **argv){
            VOID    (*func)();
            DWORD   dwOldProt;
            PUCHAR  kiuser;
            printf("[*] ring3 VMWARE detection - (c) 2009 deroko of ARTeam\n");
            kiuser = (PUCHAR)GetProcAddress(GetModuleHandle(L"ntdll.dll"), "KiUserExceptionDispatcher");
            
            VirtualProtect(kiuser, 7, PAGE_EXECUTE_READWRITE, &dwOldProt);
            kiuser[0] = 0x68;
            *(DWORD *)&kiuser[1] = (DWORD)hook_filter;
            kiuser[5] = 0xc3;
                        
            buffer = func = VirtualAlloc(0, 0x1000, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
            *(DWORD *)func = 0xC3909090;
            
            __asm xor eax, eax
            __asm mov eax, [eax]
            func();
            
            printf("[*] vmware not detected\n");
            ExitProcess(0);
    }
    defs.h
    Code:
     
    #include        <windows.h>
    #include        <stdio.h>
    
    // Dr6
    #define BPM0_DETECTED                    0x00000001
    #define BPM1_DETECTED                    0x00000002
    #define BPM2_DETECTED                    0x00000004
    #define BPM3_DETECTED                    0x00000008
    
    // Dr7
    #define BPM0_LOCAL_ENABLED               0x00000001
    #define BPM0_W                           0x00010000
    #define BPM0_RW                          0x00030000
    
    #define BPM1_LOCAL_ENABLED               0x00000004
    #define BPM1_W                           0x00100000
    #define BPM1_RW                          0x00300000
    
    #define BPM2_LOCAL_ENABLED               0x00000010
    #define BPM2_W                           0x01000000
    #define BPM2_RW                          0x03000000
    
    #define BPM3_LOCAL_ENABLED               0x00000040
    #define BPM3_W                           0x10000000
    #define BPM3_RW                          0x30000000
    
    #define BPM_LOCAL_EXACT                  0x00000100
    
    typedef LONG NTSTATUS;
    
    NTSTATUS
    NTAPI
    NtContinue(__in PCONTEXT ctx, BOOL Alertalbe);
    
    typedef struct{
    	PULONG ExceptionCodeAddress;
    	PCONTEXT   pContext;
    	ULONG  ExceptionCode;
    	ULONG  ExceptionFlags;
    	PULONG ExceptionRecord;
    	ULONG  ExceptionAddress;
    	ULONG  NumberOfParameters;
    	ULONG  ExceptionInformation[EXCEPTION_MAXIMUM_PARAMETERS];
    }EXCEPTION_INFO, *PEXCEPTION_INFO;
    output of the program running in vmware:
    Code:
    [*] ring3 VMWARE detection - (c) 2009 deroko of ARTeam
    [X] vmware detected
    output of the program running on live system:

    Code:
    [*] ring3 VMWARE detection - (c) 2009 deroko of ARTeam
    [*] vmware not detected
    Hope you find it usefull

  2. #2
    Registered User
    Join Date
    Jan 2008
    Posts
    163
    Blog Entries
    19
    Nice trick deroko, doesn't work on Virtual Box though (tested with XP 32bit and Win7 64bit). I think it's a VMWare only behavior.

  3. #3
    Administrator dELTA's Avatar
    Join Date
    Oct 2000
    Location
    Ring -1
    Posts
    4,205
    Blog Entries
    5
    Thanks for the info deroko, as always.
    "Give a man a quote from the FAQ, and he'll ignore it. Print the FAQ, shove it up his ass, kick him in the balls, DDoS his ass and kick/ban him, and the point usually gets through eventually."

  4. #4
    There is also one more trick to detect vmware in ring0 as from what I know vmware executes ring3 on live cpu. Just execute 66 BSWAP reg32 in ring0 in vmware which is undefined instruction (eg. undefined according to intel manual) and lower part of the register will be swaped, but on live cpu low part of register is always zeroed (tested it on intel and amd cpu). I found this when was writing disassembly engine to support all instructions from intel manual

  5. #5
    Musician member evaluator's Avatar
    Join Date
    Sep 2001
    Posts
    1,479
    Blog Entries
    1
    >>if exception occured 1st time (1st debug break) and sets RF

    Is not RF already in c.EFLAGS ?

  6. #6
    Sorry I ment 1st debug exception when dwExceptionCounte == 1 as 1st exception is to get access to drX (pf with xor eax,eax/mov eax,[eax]). my bad

  7. #7
    Musician member evaluator's Avatar
    Join Date
    Sep 2001
    Posts
    1,479
    Blog Entries
    1
    no, i mean, when DR-exception happens, CPU sets RF and it should be also in CTX.EFLAGs (check it),
    so you not need set it again.

  8. #8
    Registered User
    Join Date
    Nov 2003
    Location
    .hr
    Posts
    40
    Hi,

    What was your guest OS, i know win9x is obsolete, but 9x and NT systems handle RF differently.

  9. #9
    @evaluator: no, RF is not set by default. There are some conditions when it's set but debug exception on execution is not setting this flag.

    @drizz: it's winxp as guest, and winxp/vista as host. It doesn't really matter, as it seems to be vmware virtualization problem. VMWare version is 6.5.1

  10. #10
    hartt
    Guest
    In my computer, the program running on live system (win xp pro sp3)

    [*] ring3 VMWARE detection - (c) 2009 deroko of ARTeam
    [X] vmware detected
    The trick is not working :/
    I promise that I have read the FAQ and tried to use the Search to answer my question.

  11. #11
    then there is something fishy with your cpu, as this behavior is defined in ia32 manuals.

  12. #12
    hartt
    Guest
    It's strange.. My cpu is "Intel Core 2 Duo T7600".
    Your system is 32 or 64 bits ?
    Last edited by hartt; January 31st, 2010 at 10:32.
    I promise that I have read the FAQ and tried to use the Search to answer my question.

  13. #13
    it's 32bit... tested on t7200 and t9550. Do you have by any chance, anything, any hook driver which might block NtContinue? As vmware detected occurs only, and only when RF is not handled by your CPU, which is (and should be) handled by real cpu but not in vmware.

  14. #14
    hartt
    Guest
    I have no hooks in ntdll.dll and SSDT with NtContinue.

    I compiled your code in assembly.. RF flag is not handled by my real cpu because i have a loop
    Source + binary in attachment.

    Code:
    BreakpointBugCheck proc
    
    	push _seh_handler
    	push fs:[0]
    	mov fs:[0], esp                       ; Install Exception Handler
    
    	xor eax, eax                          ; Exception Div by 0 for install BPH
    	div eax
    
    _junk_code:
    	nop
    
    _bph:
    	nop
    
    _func_ret:
    	pop fs:[0]                            ; Delete Exception Handler
    	add esp, 4
    
    	mov eax, 1
    	retn                                  ; Function Return
    
     _seh_handler:
     	mov ecx, [esp+04h]                    ; ecx = EXCEPTION RECORD
    	mov ebx, [ecx]                        ; ebx = EXCEPTION CODE
    
    	cmp ebx, 0C0000094h                   ; Exception Code Div by 0
    	je  _div_exception
    
    	cmp ebx, 80000004h                    ; Exception Code BreakpointH
    	je _bph_exception
    
     _div_exception:
     	mov ecx, [esp+0Ch]                    ; ecx = CONTEXT RECORD
    	mov dword ptr [ecx+4h], _bph          ; Dr0 register
    	mov dword ptr [ecx+18h], 101h         ; Dr7 register
    	mov dword ptr [ecx+0B8h], _junk_code  ; Eip register
    	xor eax, eax
    	retn                                  ; Exception Handler Return
    
    _bph_exception:
    	mov ecx, [esp+0Ch]                    ; ecx = CONTEXT RECORD
    	or dword ptr [ecx+0C0h], 10000h       ; EFlags register (change RFFlag)
    	xor eax, eax
    	retn                                  ; Exception Handler Return
    
    BreakpointBugCheck endp
    Attached Files Attached Files
    I promise that I have read the FAQ and tried to use the Search to answer my question.

Similar Threads

  1. VMware CloudBurst - VMware Guest to Host Escape Exploit
    By Piotr Bania Chronicles in forum Blogs Forum
    Replies: 0
    Last Post: September 16th, 2009, 19:18
  2. Replies: 0
    Last Post: January 12th, 2008, 00:08
  3. NTDLL patch to disallow DR0-DR7 writes from ring3
    By 0xebfe in forum OllyDbg Support Forums
    Replies: 6
    Last Post: September 9th, 2005, 17:34
  4. how can i obtain a ring3 thread context in ring0
    By _d_ in forum Advanced Reversing and Programming
    Replies: 11
    Last Post: June 10th, 2005, 13:49
  5. XP using not only ring0/ring3?
    By omega_red in forum Advanced Reversing and Programming
    Replies: 2
    Last Post: January 30th, 2005, 05:07

Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •