https://bugs.winehq.org/show_bug.cgi?id=48997
Bug ID: 48997 Summary: Riot Vanguard (Riot Games) 'vgk.sys' crashes in driver entry (needs more reasonable CR0 register values in instruction emulation) Product: Wine Version: 5.6 Hardware: x86-64 OS: Linux Status: NEW Severity: normal Priority: P2 Component: ntoskrnl Assignee: wine-bugs@winehq.org Reporter: focht@gmx.net Distribution: ---
Hello folks,
as it says.
--- snip --- $ WINEDEBUG=+seh,+loaddll,+process,+ntoskrnl wine net start vgc >>log.txt 2>&1 ... 001b:fixme:ntoskrnl:KeIpiGenericCall stub: 0000000000D61D74 0000000000000000 ... 001b:trace:seh:raise_exception code=c0000096 flags=0 addr=0xf38ec7 ip=f38ec7 tid=001b 001b:trace:seh:raise_exception rax=0000000000000078 rbx=fffffffffff49c55 rcx=0000000000000000 rdx=00000000000fda18 001b:trace:seh:raise_exception rsi=0000000000e07fec rdi=00000000000000e8 rbp=000000000002c1d1 rsp=0000000000c3f4f0 001b:trace:seh:raise_exception r8=00000000000f174d r9=0000000000c3f710 r10=00000000000fda18 r11=0000000000f38ec7 001b:trace:seh:raise_exception r12=00000000000fd8b0 r13=00007fffffea4000 r14=00000000000fda18 r15=0000000000000000 001b:trace:seh:call_vectored_handlers calling handler at 0x18000b9f0 code=c0000096 flags=0 001b:trace:seh:call_vectored_handlers handler at 0x18000b9f0 returned ffffffff ... 001b:trace:seh:raise_exception code=c000001d flags=0 addr=0x104bc20 ip=104bc20 tid=001b 001b:trace:seh:raise_exception rax=0000000000b41d20 rbx=00000000000fda18 rcx=0000000000000000 rdx=000000000000004d 001b:trace:seh:raise_exception rsi=0000000000c3f82c rdi=00000000000fda18 rbp=00000000000fc868 rsp=0000000000c3f740 001b:trace:seh:raise_exception r8=0000000000000000 r9=0000000000000000 r10=0000000000000000 r11=0000000000000000 001b:trace:seh:raise_exception r12=00000000000fd8b0 r13=00007fffffea4000 r14=00000000000fda18 r15=0000000000000000 001b:trace:seh:call_vectored_handlers calling handler at 0x18000b9f0 code=c000001d flags=0 001b:trace:seh:call_vectored_handlers handler at 0x18000b9f0 returned 0 001b:trace:seh:RtlVirtualUnwind type 1 rip 104bc20 rsp c3f740 001b:trace:seh:dump_unwind_info **** func 2ebbd7-2ebc54 ... --- snip ---
Yes, I know 'int' debug channel which shows the faulting/emulated instruction decoding. I forgot to run it in first place before I fixed the problem ;-)
The unhandled invalid instruction exception following the CR0 emulation exception is the result of misguided control flow due to Wine's strange default value.
Relevant driver disassembly:
--- snip --- ... 0000000000F38EC7 | 0F20C2 | mov rdx,cr0 | read CR0 0000000000F38ECA | 81ED 8836F674 | sub ebp,74F63688 | 0000000000F38ED0 | 40:C0F5 36 | shl bpl,36 | 0000000000F38ED4 | 0FB7E9 | movzx ebp,cx | 0000000000F38ED7 | 49:81E9 08000000 | sub r9,8 | 0000000000F38EDE | 40:0F92C5 | setb bpl | 0000000000F38EE2 | 66:0FBAF5 B7 | btr bp,B7 | 0000000000F38EE7 | 66:8BEB | mov bp,bx | 0000000000F38EEA | 49:8911 | mov qword ptr ds:[r9],rdx | save val 0000000000F38EED | 6641:0BEA | or bp,r10w | 0000000000F38EF1 | 48:81EE 04000000 | sub rsi,4 | 0000000000F38EF8 | 48:F7DD | neg rbp | 0000000000F38EFB | 8B2E | mov ebp,dword ptr ds:[rsi] | 0000000000F38EFD | 40:F6C4 F2 | test spl,F2 | 0000000000F38F01 | 41:80FA AD | cmp r10b,AD | 0000000000F38F05 | F8 | clc | 0000000000F38F06 | 41:33E8 | xor ebp,r8d | 0000000000F38F09 | F9 | stc | 0000000000F38F0A | D1CD | ror ebp,1 | 0000000000F38F0C | F9 | stc | 0000000000F38F0D | 0FCD | bswap ebp | 0000000000F38F0F | 6641:3BF3 | cmp si,r11w | 0000000000F38F13 | 81C5 66295D17 | add ebp,175D2966 | 0000000000F38F19 | F9 | stc | 0000000000F38F1A | F8 | clc | 0000000000F38F1B | F7D5 | not ebp | 0000000000F38F1D | E9 D51F0400 | jmp vgk.F7AEF7 | ... --- snip ---
I found this interesting document which shows the system/special register values of many Window versions, Linux and even Wine:
https://github.com/corkami/docs/blob/master/InitialValues.md
--- snip --- Wine
tested under Debian
Detect Wine:
GS (3B/6B) FS (33/63) CR0 (80050033) ... --- snip ---
The document was added to Github repo in April 2017. The Wine version at this point was likely Wine 2.6-ish.
I couldn't find a place in Wine sources where this value 0x80050033 is set. Git history shows it was always 0x10 (x86 instruction emulation).
My guess would be whoever tested under Wine probably used the unprivileged 'smsw' instruction which doesn't cause a trap in usermode (not emulated in Wine). I wrote small test app which is basically 'asm("smsw %0" : "=r"(cr0));' and indeed 0x80050033 value is returned for CR0 in x86_64 Linux.
https://source.winehq.org/git/wine.git/blob/709935314458bd0ce27aab3986ae98cc...
The x86_64 instruction emulation for CRx, DRx was added here:
https://source.winehq.org/git/wine.git/commitdiff/ce09790d29630a6a4c0cd49459... ("ntoskrnl: Add emulation of CRn and DRn registers on x86-64.")
Tracked by bug 44530 ("64-bit Sentinel HASP hardlock.sys kernel driver tries to access to DR7 (not handled in ntoskrnl emulate_instruction)").
---
Anyway, I think Wine using CR0 default value 0x80050031 or 0x80050033 should be fine.
0x80050031 = '1000'0000'0000'0101'0000'0000'0011'0001
From: https://en.wikipedia.org/wiki/Control_register
Only showing the set bits meaning here:
| Bit | Name | Full Name | ---------------------------------------- | 0 | PE | Protected Mode Enable | | 4 | ET | Extension type | | 5 | NE | Numeric error | | 16 | WP | Write protect | | 18 | AM | Alignment mask | | 31 | PG | Paging | ----------------------------------------
Wine source:
https://source.winehq.org/git/wine.git/blob/f65cfbfe9b20e38537c7cb8608e7f411...
--- snip --- ... 691 /* Now look at the actual instruction */ 692 693 switch(*instr) 694 { 695 case 0x0f: /* extended instruction */ 696 switch(instr[1]) 697 { 698 case 0x20: /* mov crX, Rd */ 699 { 700 int reg = REGMODRM_REG( instr[2], rex ); 701 int rm = REGMODRM_RM( instr[2], rex ); 702 DWORD64 *data = get_int_reg( context, rm ); 703 TRACE( "mov cr%u,%s at %lx\n", reg, reg_names[rm], context->Rip ); 704 switch (reg) 705 { 706 case 0: *data = 0x10; break; /* FIXME: set more bits ? */ 707 case 2: *data = 0; break; 708 case 3: *data = 0; break; 709 case 4: *data = 0; break; 710 case 8: *data = 0; break; 711 default: return ExceptionContinueSearch; 712 } 713 context->Rip += prefixlen + 3; 714 return ExceptionContinueExecution; 715 } ... --- snip ---
$ sha1sum setup.exe 08deca4c0b46a3481e706926c0217d1c944d22a3 setup.exe
$ du -sh setup.exe 15M setup.exe
$ wine --version wine-5.6-258-gf31a29b8d1
Regards
https://bugs.winehq.org/show_bug.cgi?id=48997
Anastasius Focht focht@gmx.net changed:
What |Removed |Added ---------------------------------------------------------------------------- Keywords| |download, obfuscation URL| |https://riot-client.secure. | |dyn.riotcdn.net/channels/pu | |blic/rccontent/vanguard/0.3 | |.2.2/setup.exe
https://bugs.winehq.org/show_bug.cgi?id=48997
Fabian Maurer dark.shadow4@web.de changed:
What |Removed |Added ---------------------------------------------------------------------------- CC| |dark.shadow4@web.de
--- Comment #1 from Fabian Maurer dark.shadow4@web.de --- Do you know what they do with that value from CR0? I mean, what's the point when it's always the same?
https://bugs.winehq.org/show_bug.cgi?id=48997
--- Comment #2 from Anastasius Focht focht@gmx.net --- Hello Fabian,
--- quote --- Do you know what they do with that value from CR0? I mean, what's the point when it's always the same? --- quote ---
well in case of CR0 only basic checks are done. If CR0 contains nonsense values like in case Wine one can be sure something is fishy and refuse to run further. Things like not being in protected mode, paging disabled, write protect disabled (no traps of ring0 access to read-only ring3 pages) etc.
For me it looks like the code is part of a "suite" they might have copied from some anti-debug cookbook or general RCE whitepapers to check if Windows runs under control of a Hypervisor/VMM. There are multiple checks of special function/system register values.
Regards
https://bugs.winehq.org/show_bug.cgi?id=48997
--- Comment #3 from Fabian Maurer dark.shadow4@web.de --- Makes sense, are you going to submit a patch for this?
https://bugs.winehq.org/show_bug.cgi?id=48997
Alex Henrie alexhenrie24@gmail.com changed:
What |Removed |Added ---------------------------------------------------------------------------- CC| |alexhenrie24@gmail.com
--- Comment #4 from Alex Henrie alexhenrie24@gmail.com --- (In reply to Fabian Maurer from comment #3)
Makes sense, are you going to submit a patch for this?
Focht never submits patches, he just does the hard work of debugging and then leaves patching to the rest of us :-)
https://bugs.winehq.org/show_bug.cgi?id=48997
Alex Henrie alexhenrie24@gmail.com changed:
What |Removed |Added ---------------------------------------------------------------------------- Status|NEW |RESOLVED Resolution|--- |FIXED Fixed by SHA1| |f83f0e5f13a36a246e12d5838aa | |5bace3ebe5c3e
--- Comment #5 from Alex Henrie alexhenrie24@gmail.com --- Fixed by https://source.winehq.org/git/wine.git/commitdiff/f83f0e5f13a36a246e12d5838a...
https://bugs.winehq.org/show_bug.cgi?id=48997
Alexandre Julliard julliard@winehq.org changed:
What |Removed |Added ---------------------------------------------------------------------------- Status|RESOLVED |CLOSED
--- Comment #6 from Alexandre Julliard julliard@winehq.org --- Closing bugs fixed in 5.12.
https://bugs.winehq.org/show_bug.cgi?id=48997
Anastasius Focht focht@gmx.net changed:
What |Removed |Added ---------------------------------------------------------------------------- URL|https://riot-client.secure. |https://web.archive.org/web |dyn.riotcdn.net/channels/pu |/20200421165713/https://rio |blic/rccontent/vanguard/0.3 |t-client.secure.dyn.riotcdn |.2.2/setup.exe |.net/channels/public/rccont | |ent/vanguard/0.3.2.2/setup. | |exe