[Bug 49221] New: Denuvo Anti-Cheat 'denuvo-anti-cheat.sys' needs instruction emulation for querying VMX capabilities via MSR 0x480..0x490
WineHQ Bugzilla
wine-bugs at winehq.org
Fri May 22 07:36:07 CDT 2020
https://bugs.winehq.org/show_bug.cgi?id=49221
Bug ID: 49221
Summary: Denuvo Anti-Cheat 'denuvo-anti-cheat.sys' needs
instruction emulation for querying VMX capabilities
via MSR 0x480..0x490
Product: Wine
Version: 5.8
Hardware: x86-64
OS: Linux
Status: NEW
Severity: normal
Priority: P2
Component: ntoskrnl
Assignee: wine-bugs at winehq.org
Reporter: focht at gmx.net
Distribution: ---
Hello folks,
continuation of bug 49219 (split out from bug 49194).
--- snip ---
$ WINEDEBUG=+seh,+relay,+int,+ntoskrnl,+ntdll wine net start "Denuvo
Anti-Cheat" >>log.txt 2>&1
...
00d0:Call driver init 0000000000C81184
(obj=000000000078EE10,str=L"\\Registry\\Machine\\System\\CurrentControlSet\\Services\\Denuvo
Anti-Cheat")
...
00d0:Call ntoskrnl.exe.KeQueryActiveProcessorCountEx(0000ffff) ret=00c83d3a
00d0:fixme:ntoskrnl:KeQueryActiveProcessorCountEx GroupNumber 65535 semi-stub.
00d0:Call KERNEL32.GetSystemInfo(00b5f2f0) ret=00232926
00d0:Call ntdll.NtQuerySystemInformation(00000000,00b5f200,00000040,00000000)
ret=7b02c721
00d0:trace:ntdll:NtQuerySystemInformation
(0x00000000,0xb5f200,0x00000040,(nil))
00d0:Ret ntdll.NtQuerySystemInformation() retval=00000000 ret=7b02c721
00d0:Call ntdll.NtQuerySystemInformation(00000001,00b5f1f0,0000000c,00000000)
ret=7b02c751
00d0:trace:ntdll:NtQuerySystemInformation
(0x00000001,0xb5f1f0,0x0000000c,(nil))
00d0:Ret ntdll.NtQuerySystemInformation() retval=00000000 ret=7b02c751
00d0:Ret KERNEL32.GetSystemInfo() retval=00000006 ret=00232926
00d0:Ret ntoskrnl.exe.KeQueryActiveProcessorCountEx() retval=00000008
ret=00c83d3a
00d0:Call ntoskrnl.exe.KeSetSystemAffinityThreadEx(ffffffffffffffff)
ret=00c83d56
00d0:fixme:ntoskrnl:KeSetSystemAffinityThreadEx (0xffffffff) semi-stub
00d0:Call
ntdll.NtQueryInformationThread(fffffffffffffffe,0000001e,00b5f300,00000010,00000000)
ret=00232aa8
00d0:Ret ntdll.NtQueryInformationThread() retval=00000000 ret=00232aa8
00d0:Call
ntdll.NtSetInformationThread(fffffffffffffffe,0000001e,00b5f310,00000010)
ret=00232b00
00d0:Ret ntdll.NtSetInformationThread() retval=c000000d ret=00232b00
00d0:fixme:ntoskrnl:KeSetSystemAffinityThreadEx Set affinity, status
0xc000000d.
00d0:fixme:ntoskrnl:KeSetSystemAffinityThreadEx old.Group 0, old.Mask 0xff.
00d0:Ret ntoskrnl.exe.KeSetSystemAffinityThreadEx() retval=000000ff
ret=00c83d56
00d0:Call ntoskrnl.exe.KeSetSystemAffinityThreadEx(00000001) ret=00c83d86
00d0:fixme:ntoskrnl:KeSetSystemAffinityThreadEx (0x1) semi-stub
00d0:Call
ntdll.NtQueryInformationThread(fffffffffffffffe,0000001e,00b5f300,00000010,00000000)
ret=00232aa8
00d0:Ret ntdll.NtQueryInformationThread() retval=00000000 ret=00232aa8
00d0:Call
ntdll.NtSetInformationThread(fffffffffffffffe,0000001e,00b5f310,00000010)
ret=00232b00
00d0:Ret ntdll.NtSetInformationThread() retval=00000000 ret=00232b00
00d0:fixme:ntoskrnl:KeSetSystemAffinityThreadEx old.Group 0, old.Mask 0xff.
00d0:Ret ntoskrnl.exe.KeSetSystemAffinityThreadEx() retval=000000ff
ret=00c83d86
00d0:trace:seh:raise_exception code=c0000096 flags=0 addr=0xc88ac3 ip=c88ac3
tid=00d0
00d0:trace:seh:raise_exception rax=0000000000000000 rbx=0000000000000000
rcx=00000000008e0370 rdx=000000009c000400
00d0:trace:seh:raise_exception rsi=00000000008e1f70 rdi=00000000008e0370
rbp=0000000000b5f370 rsp=0000000000b5f2f8
00d0:trace:seh:raise_exception r8=000000000027efb1 r9=00000000008e0370
r10=0000000000000000 r11=0000000000000000
00d0:trace:seh:raise_exception r12=0000000000000000 r13=00007fffffea4000
r14=0000000000000000 r15=0000000080000008
00d0:trace:seh:call_vectored_handlers calling handler at 0x22cfa0 code=c0000096
flags=0
00d0:trace:int:emulate_instruction mov cr4,rax at c88ac3
00d0:trace:int:vectored_handler next instruction rip=c88ac6
00d0:trace:int:vectored_handler rax=0000000000000000 rbx=0000000000000000
rcx=00000000008e0370 rdx=000000009c000400
00d0:trace:int:vectored_handler rsi=00000000008e1f70 rdi=00000000008e0370
rbp=0000000000b5f370 rsp=0000000000b5f2f8
00d0:trace:int:vectored_handler r8=000000000027efb1 r9=00000000008e0370
r10=0000000000000000 r11=0000000000000000
00d0:trace:int:vectored_handler r12=0000000000000000 r13=00000000ffea4000
r14=0000000000000000 r15=0000000080000008
00d0:trace:seh:call_vectored_handlers handler at 0x22cfa0 returned ffffffff
00d0:trace:seh:raise_exception code=c0000005 flags=0 addr=0xc88ad4 ip=c88ad4
tid=00d0
00d0:trace:seh:raise_exception info[0]=0000000000000000
00d0:trace:seh:raise_exception info[1]=ffffffffffffffff
00d0:trace:seh:raise_exception rax=0000000000000000 rbx=0000000000000000
rcx=0000000000000480 rdx=000000009c000400
00d0:trace:seh:raise_exception rsi=00000000008e1f70 rdi=00000000008e0370
rbp=0000000000b5f370 rsp=0000000000b5f2f8
00d0:trace:seh:raise_exception r8=000000000027efb1 r9=00000000008e0370
r10=0000000000000000 r11=0000000000000000
00d0:trace:seh:raise_exception r12=0000000000000000 r13=00007fffffea4000
r14=0000000000000000 r15=0000000080000008
00d0:trace:seh:call_vectored_handlers calling handler at 0x22cfa0 code=c0000005
flags=0
00d0:trace:int:emulate_instruction rdmsr CR 0x00000480
00d0:trace:seh:call_vectored_handlers handler at 0x22cfa0 returned 0
00d0:warn:seh:virtual_unwind exception data not found in
L"denuvo-anti-cheat.sys"
--- snip ---
Relevant disassembly snippet of driver:
--- snip ---
0000000140008AC0 | 4C:8BC9 | mov r9,rcx |
0000000140008AC3 | 0F20E0 | mov rax,cr4 |
0000000140008AC6 | 48:C1E8 0D | shr rax,D |
0000000140008ACA | 24 01 | and al,1 |
0000000140008ACC | 8841 51 | mov byte ptr ds:[rcx+51],al |
--- snip ---
CR4 -> bit 13 set -> VMXE
--- snip ---
0000000140008ACF | B9 80040000 | mov ecx,480 |
0000000140008AD4 | 0F32 | rdmsr |
0000000140008AD6 | 48:C1E2 20 | shl rdx,20 |
0000000140008ADA | B9 81040000 | mov ecx,481 |
0000000140008ADF | 48:0BC2 | or rax,rdx |
0000000140008AE2 | 49:8941 58 | mov qword ptr ds:[r9+58],rax |
0000000140008AE6 | 0F32 | rdmsr |
0000000140008AE8 | 48:C1E2 20 | shl rdx,20 |
0000000140008AEC | B9 82040000 | mov ecx,482 |
0000000140008AF1 | 48:0BC2 | or rax,rdx |
0000000140008AF4 | 49:8941 60 | mov qword ptr ds:[r9+60],rax |
0000000140008AF8 | 0F32 | rdmsr |
0000000140008AFA | 48:C1E2 20 | shl rdx,20 |
0000000140008AFE | B9 83040000 | mov ecx,483 |
0000000140008B03 | 48:0BC2 | or rax,rdx |
0000000140008B06 | 4C:8BC0 | mov r8,rax |
0000000140008B09 | 49:8941 68 | mov qword ptr ds:[r9+68],rax |
0000000140008B0D | 0F32 | rdmsr |
0000000140008B0F | 48:C1E2 20 | shl rdx,20 |
0000000140008B13 | B9 84040000 | mov ecx,484 |
0000000140008B18 | 48:0BC2 | or rax,rdx |
0000000140008B1B | 49:8941 70 | mov qword ptr ds:[r9+70],rax |
0000000140008B1F | 0F32 | rdmsr |
0000000140008B21 | 48:C1E2 20 | shl rdx,20 |
0000000140008B25 | B9 85040000 | mov ecx,485 |
0000000140008B2A | 48:0BC2 | or rax,rdx |
0000000140008B2D | 49:8941 78 | mov qword ptr ds:[r9+78],rax |
0000000140008B31 | 0F32 | rdmsr |
0000000140008B33 | 48:C1E2 20 | shl rdx,20 |
0000000140008B37 | B9 86040000 | mov ecx,486 |
0000000140008B3C | 48:0BC2 | or rax,rdx |
0000000140008B3F | 49:8981 80000000 | mov qword ptr ds:[r9+80],rax |
0000000140008B46 | 0F32 | rdmsr |
0000000140008B48 | 48:C1E2 20 | shl rdx,20 |
0000000140008B4C | B9 87040000 | mov ecx,487 |
0000000140008B51 | 48:0BC2 | or rax,rdx |
0000000140008B54 | 49:8981 88000000 | mov qword ptr ds:[r9+88],rax |
0000000140008B5B | 0F32 | rdmsr |
0000000140008B5D | 48:C1E2 20 | shl rdx,20 |
0000000140008B61 | B9 88040000 | mov ecx,488 |
0000000140008B66 | 48:0BC2 | or rax,rdx |
0000000140008B69 | 49:8981 90000000 | mov qword ptr ds:[r9+90],rax |
0000000140008B70 | 0F32 | rdmsr |
0000000140008B72 | 48:C1E2 20 | shl rdx,20 |
0000000140008B76 | B9 89040000 | mov ecx,489 |
0000000140008B7B | 48:0BC2 | or rax,rdx |
0000000140008B7E | 49:8981 98000000 | mov qword ptr ds:[r9+98],rax |
0000000140008B85 | 0F32 | rdmsr |
0000000140008B87 | 48:C1E2 20 | shl rdx,20 |
0000000140008B8B | B9 8A040000 | mov ecx,48A |
0000000140008B90 | 48:0BC2 | or rax,rdx |
0000000140008B93 | 49:8981 A0000000 | mov qword ptr ds:[r9+A0],rax |
0000000140008B9A | 0F32 | rdmsr |
0000000140008B9C | 48:C1E2 20 | shl rdx,20 |
0000000140008BA0 | 45:33D2 | xor r10d,r10d |
0000000140008BA3 | 48:0BC2 | or rax,rdx |
0000000140008BA6 | 49:8981 A8000000 | mov qword ptr ds:[r9+A8],rax |
0000000140008BAD | 4D:85C0 | test r8,r8 |
0000000140008BB0 | 79 3B | jns denuvo-anti-cheat.140008BED |
0000000140008BB2 | B9 8B040000 | mov ecx,48B |
0000000140008BB7 | 0F32 | rdmsr |
0000000140008BB9 | 48:C1E2 20 | shl rdx,20 |
0000000140008BBD | 48:B9 0000000022000000 | mov rcx,2200000000 |
0000000140008BC7 | 48:0BC2 | or rax,rdx |
0000000140008BCA | 49:8981 B0000000 | mov qword ptr ds:[r9+B0],rax |
0000000140008BD1 | 48:85C1 | test rcx,rax |
0000000140008BD4 | 74 1E | je denuvo-anti-cheat.140008BF4 |
0000000140008BD6 | B9 8C040000 | mov ecx,48C |
0000000140008BDB | 0F32 | rdmsr |
0000000140008BDD | 48:C1E2 20 | shl rdx,20 |
0000000140008BE1 | 48:0BC2 | or rax,rdx |
0000000140008BE4 | 49:8981 B8000000 | mov qword ptr ds:[r9+B8],rax |
0000000140008BEB | EB 0E | jmp denuvo-anti-cheat.140008BFB |
0000000140008BED | 4D:8991 B0000000 | mov qword ptr ds:[r9+B0],r10 |
0000000140008BF4 | 4D:8991 B8000000 | mov qword ptr ds:[r9+B8],r10 |
0000000140008BFB | 48:B9 0000000000008000 | mov rcx,80000000000000 |
0000000140008C05 | 49:8549 58 | test qword ptr ds:[r9+58],rcx |
0000000140008C09 | 74 5D | je denuvo-anti-cheat.140008C68 |
0000000140008C0B | B9 8D040000 | mov ecx,48D |
0000000140008C10 | 0F32 | rdmsr |
0000000140008C12 | 48:C1E2 20 | shl rdx,20 |
0000000140008C16 | B9 8E040000 | mov ecx,48E |
0000000140008C1B | 48:0BC2 | or rax,rdx |
0000000140008C1E | 49:8981 C0000000 | mov qword ptr ds:[r9+C0],rax |
0000000140008C25 | 0F32 | rdmsr |
0000000140008C27 | 48:C1E2 20 | shl rdx,20 |
0000000140008C2B | B9 8F040000 | mov ecx,48F |
0000000140008C30 | 48:0BC2 | or rax,rdx |
0000000140008C33 | 49:8981 C8000000 | mov qword ptr ds:[r9+C8],rax |
0000000140008C3A | 0F32 | rdmsr |
0000000140008C3C | 48:C1E2 20 | shl rdx,20 |
0000000140008C40 | B9 90040000 | mov ecx,490 |
0000000140008C45 | 48:0BC2 | or rax,rdx |
0000000140008C48 | 49:8981 D0000000 | mov qword ptr ds:[r9+D0],rax |
0000000140008C4F | 0F32 | rdmsr |
0000000140008C51 | 48:C1E2 20 | shl rdx,20 |
0000000140008C55 | 48:0BC2 | or rax,rdx |
0000000140008C58 | 49:8981 D8000000 | mov qword ptr ds:[r9+D8],rax |
0000000140008C5F | 41:C741 54 11000000 | mov dword ptr ds:[r9+54],11 |
0000000140008C67 | C3 | ret |
0000000140008C68 | 4D:8991 D8000000 | mov qword ptr ds:[r9+D8],r10 |
0000000140008C6F | 4D:8991 D0000000 | mov qword ptr ds:[r9+D0],r10 |
0000000140008C76 | 4D:8991 C8000000 | mov qword ptr ds:[r9+C8],r10 |
0000000140008C7D | 4D:8991 C0000000 | mov qword ptr ds:[r9+C0],r10 |
0000000140008C84 | 41:C741 54 11000000 | mov dword ptr ds:[r9+54],11 |
0000000140008C8C | C3 | ret |
--- snip ---
The patch (hack) from https://bugs.winehq.org/show_bug.cgi?id=49194#c1 returns
zero rax and rdx for any MSR which isn't recognized in 'emulate_instruction()'
Wine source:
https://source.winehq.org/git/wine.git/blob/b65ca133052ed9053e48c571155a764d4d711277:/dlls/ntoskrnl.exe/instr.c#l769
--- snip ---
769 case 0x32: /* rdmsr */
770 {
771 ULONG reg = context->Rcx;
772 TRACE("rdmsr CR 0x%08x\n", reg);
773 switch (reg)
774 {
775 case MSR_LSTAR:
776 {
777 ULONG_PTR syscall_address =
(ULONG_PTR)fake_syscall_function;
778 context->Rdx = (ULONG)(syscall_address >> 32);
779 context->Rax = (ULONG)syscall_address;
780 break;
781 }
782 default: return ExceptionContinueSearch;
783 }
784 context->Rip += prefixlen + 2;
785 return ExceptionContinueExecution;
786 }
--- snip ---
Since the VMX MSR range is well known there could be a default handler for
these regs, returning fake (0) values.
---
Tidbits:
Python app to dump VMX capabilities from userspace:
https://github.com/qemu/qemu/blob/master/scripts/kvm/vmxcap
--- snip ---
$ sudo ./vmxcap.py
Basic VMX Information
Hex: 0xda040000000012
Revision 18
VMCS size 1024
VMCS restricted to 32 bit addresses no
Dual-monitor support yes
VMCS memory type 6
INS/OUTS instruction information yes
IA32_VMX_TRUE_*_CTLS support yes
pin-based controls
External interrupt exiting yes
NMI exiting yes
Virtual NMIs yes
Activate VMX-preemption timer yes
Process posted interrupts no
primary processor-based controls
Interrupt window exiting yes
Use TSC offsetting yes
HLT exiting yes
INVLPG exiting yes
MWAIT exiting yes
RDPMC exiting yes
RDTSC exiting yes
CR3-load exiting default
CR3-store exiting default
CR8-load exiting yes
CR8-store exiting yes
Use TPR shadow yes
NMI-window exiting yes
MOV-DR exiting yes
Unconditional I/O exiting yes
Use I/O bitmaps yes
Monitor trap flag yes
Use MSR bitmaps yes
MONITOR exiting yes
PAUSE exiting yes
Activate secondary control yes
secondary processor-based controls
Virtualize APIC accesses yes
Enable EPT yes
Descriptor-table exiting yes
Enable RDTSCP yes
Virtualize x2APIC mode yes
Enable VPID yes
WBINVD exiting yes
Unrestricted guest yes
APIC register emulation no
Virtual interrupt delivery no
PAUSE-loop exiting yes
RDRAND exiting yes
Enable INVPCID yes
Enable VM functions yes
VMCS shadowing no
Enable ENCLS exiting no
RDSEED exiting no
Enable PML no
EPT-violation #VE no
Conceal non-root operation from PT no
Enable XSAVES/XRSTORS no
Mode-based execute control (XS/XU) no
Sub-page write permissions no
GPA translation for PT no
TSC scaling no
User wait and pause no
ENCLV exiting no
VM-Exit controls
Save debug controls default
Host address-space size yes
Load IA32_PERF_GLOBAL_CTRL yes
Acknowledge interrupt on exit yes
Save IA32_PAT yes
Load IA32_PAT yes
Save IA32_EFER yes
Load IA32_EFER yes
Save VMX-preemption timer value yes
Clear IA32_BNDCFGS no
Conceal VM exits from PT no
Clear IA32_RTIT_CTL no
VM-Entry controls
Load debug controls default
IA-32e mode guest yes
Entry to SMM yes
Deactivate dual-monitor treatment yes
Load IA32_PERF_GLOBAL_CTRL yes
Load IA32_PAT yes
Load IA32_EFER yes
Load IA32_BNDCFGS no
Conceal VM entries from PT no
Load IA32_RTIT_CTL no
Miscellaneous data
Hex: 0x300481e5
VMX-preemption timer scale (log2) 5
Store EFER.LMA into IA-32e mode guest control yes
HLT activity state yes
Shutdown activity state yes
Wait-for-SIPI activity state yes
PT in VMX operation no
IA32_SMBASE support yes
Number of CR3-target values 4
MSR-load/store count recommendation 0
IA32_SMM_MONITOR_CTL[2] can be set to 1 yes
VMWRITE to VM-exit information fields yes
Inject event with insn length=0 no
MSEG revision identifier 0
VPID and EPT capabilities
Hex: 0xf0106334141
Execute-only EPT translations yes
Page-walk length 4 yes
Paging-structure memory type UC yes
Paging-structure memory type WB yes
2MB EPT pages yes
1GB EPT pages yes
INVEPT supported yes
EPT accessed and dirty flags yes
Advanced VM-exit information for EPT violations no
Single-context INVEPT yes
All-context INVEPT yes
INVVPID supported yes
Individual-address INVVPID yes
Single-context INVVPID yes
All-context INVVPID yes
Single-context-retaining-globals INVVPID yes
VM Functions
Hex: 0x1
EPTP Switching yes
--- snip ---
Poor man's version (msr-tools):
--- snip ---
$ for i in `seq 0x480 0x490` ; do sudo rdmsr -x $i ; done
da040000000012
7f00000016
fff9fffe0401e172
7fffff00036dff
ffff000011ff
300481e5
80000021
ffffffff
2000
1727ff
2a
3cff00000000
f0106334141
7f00000016
fff9fffe04006172
7fffff00036dfb
ffff000011fb
--- snip ---
$ wine --version
wine-5.8-321-gf0a8061663
Regards
--
Do not reply to this email, post in Bugzilla using the
above URL to reply.
You are receiving this mail because:
You are watching all bug changes.
More information about the wine-bugs
mailing list