Results 1 to 6 of 6

Thread: XGETBV trickies

  1. #1
    Musician member evaluator's Avatar
    Join Date
    Sep 2001
    Posts
    1,489
    Blog Entries
    1

    XGETBV trickies

    Well, started play for some reassembly & meet this XGETBV instruction (AVX related?), which quite puzzled me.
    this instruction is included in CPU detection routines with bunch of CPUIDs. ..and..
    when I ripped these routines, XGETBV does fault in my prog! while not doing in there.. (FFox)
    now I have few assumpts:
    1. instruction activated by specifically compiled mz-pe header?? (tried some flags..) or signed pe-images?
    2. instruction activated by some call to system?
    3. or in registry is granted some keys upon installation? (less likely)

    also, checked inet, where is few info:
    https://www.felixcloutier.com/x86/xgetbv

    here is written about ECX=1. while in FFox ECX=0

    https://software.intel.com/en-us/cpp-compiler-developer-guide-and-reference-xgetbv
    "Currently, only the value '0' is allowed."

    Code:
    Code010001010:
        push ebx
        push edi
        push esi
        pushf
        pop eax
        mov ecx eax
        xor eax 0200000
        push eax
        popf
        pushf
        pop eax
        mov edx 0
        cmp ecx eax | je Code01000102E
        mov edx 01
    Code01000102E:
        test edx edx | je Code0100010F1
        xor eax eax
        cpuid
        test eax eax | je Code0100010F1
        mov esi eax
        xor ecx ecx
        mov eax 01
        cpuid
        mov eax ecx
        shr edx 017
        and al 01
        and dl 01
        mov B$Virtual0100695ED al
        mov eax ecx
        mov B$Virtual0100695EC dl
        shr eax 09
        and al 01
        cmp esi 080000001
        mov B$Virtual0100695EE al
        mov eax 0 | jb Code01000108F
        mov edi ecx
        mov eax 080000001
        xor ecx ecx
        cpuid
        mov eax ecx
        shr al 06
        mov ecx edi
        and al 01
    Code01000108F:
        mov B$Virtual0100695EF al
        mov eax ecx
        mov edx ecx
        shr eax 013
        and edx 01C000000
        and al 01
        mov B$Virtual0100695F0 al
        mov eax ecx
        shr eax 014
        and al 01
        cmp edx 01C000000
        mov B$Virtual0100695F1 al | jne Code01000112D
        mov edi ecx
        xor ecx ecx
        xgetbv
        and eax 06
        xor ebx ebx
        cmp eax 06
        sete B$Virtual0100695F2
        cmp esi 07

  2. #2
    Super Moderator
    Join Date
    Dec 2004
    Posts
    1,511
    Blog Entries
    15
    xgetbv is compiled via the intrinsic _xgetbv defined in immintrin.h
    as far as i know only one register is defined XCR0 == 0

    but this intrinsic also takes 1 as its parameter
    and returns result in EAX:EDX (this can probably be used as an anti debugging feature )
    because the results are different inside and outside of debugger (3 no debugger ,7 with debugger afaik)


    Code:
    :\>f:\git\usr\bin\grep -ir xcr --include=*.h *
    immintrin.h:#define _XCR_XFEATURE_ENABLED_MASK 0
    
    :\>f:\git\usr\bin\grep -n -A 6 -B 6 -ir xcr --include=*.h *
    immintrin.h-1082-
    immintrin.h-1083-/* Start of new intrinsics for Dev10 SP1
    immintrin.h-1084- *
    immintrin.h-1085- * The list of extended control registers.
    immintrin.h-1086- * Currently, the list includes only one register.
    immintrin.h-1087- */
    immintrin.h:1088:#define _XCR_XFEATURE_ENABLED_MASK 0
    immintrin.h-1089-
    immintrin.h-1090-/* Returns the content of the specified extended control register */
    immintrin.h-1091-extern unsigned __int64 __cdecl _xgetbv(unsigned int ext_ctrl_reg);
    immintrin.h-1092-
    immintrin.h-1093-/* Writes the value to the specified extended control register */
    immintrin.h-1094-extern void __cdecl _xsetbv(unsigned int ext_ctrl_reg, unsigned __int64 val);
    you can use windbg in kmode to look at xcr0

    Code:
    0: kd> dx @$curprocess.Threads.First().Registers.Kernel
    @$curprocess.Threads.First().Registers.Kernel                
        cr0              : 0x80050033
        cr2              : 0xffffe70634a784c0
        cr3              : 0x45f81002
        cr4              : 0x170678
        cr8              : 0x0
        gdtr             : 0xfffff802531f0fb0
        gdtl             : 0x57
        idtr             : 0xfffff802531ee000
        idtl             : 0xfff
        tr               : 0x40
        ldtr             : 0x0
        kmxcsr           : 0x1f80
        kdr0             : 0x0
        kdr1             : 0x0
        kdr2             : 0x0
        kdr3             : 0x0
        kdr6             : 0xffff0ff0
        kdr7             : 0x400
        xcr0             : 0x1f   <<<<<<

    nothing special needed like registry or whatever it will compile and run correctly without any cpuid if you have a computer that can use that instruction as below

    Code:
    #include <stdio.h>
    #include <windows.h>
    #include <intrin.h>
    #include <excpt.h>
    	unsigned long long foo = 0;
    int filter(unsigned int code, struct _EXCEPTION_POINTERS *ep)
    {
        if (code == EXCEPTION_ACCESS_VIOLATION)
        {
            printf("Access Violation ");
    		foo = 0;
            return EXCEPTION_EXECUTE_HANDLER;
        }
        else
        {
            puts("didn't catch AV, unexpected.");
            return EXCEPTION_CONTINUE_SEARCH;
        };
    }
    
    void main(void)
    {
    	printf("lets print some xcrs\n");
    
    	for (int i=0;i<0x10;i++){
    		__try {
    		 foo = _xgetbv(i);
    		 printf( "                 %x = %I64X\n" , i,foo);
    		}__except(filter(GetExceptionCode(), GetExceptionInformation()))
    		{
    		printf( "%x = %I64X\n" , i,foo);
    		}
    	}
    }
    will return

    Code:
    :\>sixcr.exe
    lets print some xcrs
                     0 = 1F
                     1 = 3
    Access Violation 2 = 0
    Access Violation 3 = 0
    Access Violation 4 = 0
    Access Violation 5 = 0
    Access Violation 6 = 0
    Access Violation 7 = 0
    Access Violation 8 = 0
    Access Violation 9 = 0
    Access Violation a = 0
    Access Violation b = 0
    Access Violation c = 0
    Access Violation d = 0
    Access Violation e = 0
    Access Violation f = 0

    disassembly of main

    Code:
    0:000> uf .
    sixcr!main:
    00007ff7`45881050 4883ec38        sub     rsp,38h
    00007ff7`45881054 488d0d1dd30400  lea     rcx,[sixcr!__xt_z+0x40 (00007ff7`458ce378)]
    00007ff7`4588105b e8d0000000      call    sixcr!printf (00007ff7`45881130)
    00007ff7`45881060 c744242000000000 mov     dword ptr [rsp+20h],0
    00007ff7`45881068 eb0a            jmp     sixcr!main+0x24 (00007ff7`45881074)  Branch
    
    sixcr!main+0x1a:
    00007ff7`4588106a 8b442420        mov     eax,dword ptr [rsp+20h]
    00007ff7`4588106e ffc0            inc     eax
    00007ff7`45881070 89442420        mov     dword ptr [rsp+20h],eax
    
    sixcr!main+0x24:
    00007ff7`45881074 837c242010      cmp     dword ptr [rsp+20h],10h
    00007ff7`45881079 7d4b            jge     sixcr!main+0x76 (00007ff7`458810c6)  Branch
    
    sixcr!main+0x2b:
    00007ff7`4588107b 8b4c2420        mov     ecx,dword ptr [rsp+20h]
    00007ff7`4588107f 0f01d0          xgetbv
    00007ff7`45881082 48c1e220        shl     rdx,20h
    00007ff7`45881086 480bd0          or      rdx,rax
    00007ff7`45881089 488bc2          mov     rax,rdx
    00007ff7`4588108c 4889053deb0500  mov     qword ptr [sixcr!foo (00007ff7`458dfbd0)],rax
    00007ff7`45881093 4c8b0536eb0500  mov     r8,qword ptr [sixcr!foo (00007ff7`458dfbd0)]
    00007ff7`4588109a 8b542420        mov     edx,dword ptr [rsp+20h]
    00007ff7`4588109e 488d0debd20400  lea     rcx,[sixcr!__xt_z+0x58 (00007ff7`458ce390)]
    00007ff7`458810a5 e886000000      call    sixcr!printf (00007ff7`45881130)
    00007ff7`458810aa eb18            jmp     sixcr!main+0x74 (00007ff7`458810c4)  Branch
    
    sixcr!main+0x74:
    00007ff7`458810c4 eba4            jmp     sixcr!main+0x1a (00007ff7`4588106a)  Branch
    
    sixcr!main+0x76:
    00007ff7`458810c6 33c0            xor     eax,eax
    00007ff7`458810c8 4883c438        add     rsp,38h
    00007ff7`458810cc c3              ret

    different results for ecx =1 inside and outside of debugger


    Code:
    :\>sixcr.exe
    lets print some xcrs
                     0 = 1F
                     1 = 3       <<<<<<<<<<<<< outside debugger
    xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
    
    :\>cdb  -c "g;q" sixcr.exe
    
    Microsoft (R) Windows Debugger Version 10.0.17763.132 AMD64
    
    0:000> cdb: Reading initial command 'g;q'
    lets print some xcrs
                     0 = 1F
                     1 = 7     <<<<<<<<<<<< inside debugger 
    (2d5c.2b9c): Access violation - code c0000005 (first chance)
    First chance exceptions are reported before any exception handling.
    This exception may be expected and handled.
    quit:
    Last edited by blabberer; March 10th, 2020 at 09:15.

  3. #3
    Musician member evaluator's Avatar
    Join Date
    Sep 2001
    Posts
    1,489
    Blog Entries
    1
    sorry all! I am ashamed ;(
    mistaped 3d byte opcode, while assembling (0D)..
    well, lets remove this thread. or keep?

    well, on 32bit under ollydbg it returns
    ECX=0 > EAX=1F
    ECX=1 > EAX=3
    Last edited by evaluator; March 10th, 2020 at 09:55.

  4. #4
    Teach, Not Flame Kayaker's Avatar
    Join Date
    Oct 2000
    Posts
    4,124
    Blog Entries
    5
    Is it possible xgetbv isn't emulated in a VM? The test program crashes ("didn't catch AV, unexpected") in VMWare 15 under Win7x64_sp1, compiled with VS2013 (<immintrin.h> required)

    It might be because of Win7 and not the VM, but I also enabled AVX instructions with
    bcdedit /set xsavedisable 0

    But when I copy the same file over to my Win10 desktop it runs just fine. Haven't tested under a debugger yet.
    lets print some xcrs
    0 = 1F
    1 = 3

  5. #5
    Musician member evaluator's Avatar
    Join Date
    Sep 2001
    Posts
    1,489
    Blog Entries
    1
    Kayaker, to clarify thingy, code is from Frie.Fox (32bit), thus it's intriguing, if it will not run under VM :!)
    We will report it and +ask them about unblacklist site, as such a good we are

    download.mozilla.org/?product=firefox-latest-ssl&os=win

  6. #6
    Musician member evaluator's Avatar
    Join Date
    Sep 2001
    Posts
    1,489
    Blog Entries
    1
    mm, I just tested under W1064 > VirtualBox 6.0.18 > W1032, XGETBV works.
    Difference:
    ECX=0 > EAX=7 << (1F is under W1064 real)
    ECX=1 > EAX=3
    (under OllyDbg)

    strange behavior shows CPUID, like with POP SS.
    (new advanced detection for VM!?)

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
  •