https://bugs.winehq.org/show_bug.cgi?id=49224
Bug ID: 49224 Summary: Denuvo Anti-Cheat 'denuvo-anti-cheat.sys' crashes on unimplemented function ntoskrnl.exe.{KeGenericCallDpc,KeSignalCallDpcSynchron ize,KeSignalCallDpcDone} Product: Wine Version: 5.8 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,
continuation of bug 49222 (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.KeRevertToUserAffinityThreadEx(000000ff) ret=00c84cf7 00d0:fixme:ntoskrnl:KeRevertToUserAffinityThreadEx Affinity 0xff stub. 00d0:Call ntdll.NtSetInformationThread(fffffffffffffffe,0000001e,00b5f170,00000010) ret=00232c8d 00d0:Ret ntdll.NtSetInformationThread() retval=00000000 ret=00232c8d 00d0:Ret ntoskrnl.exe.KeRevertToUserAffinityThreadEx() retval=00000000 ret=00c84cf7 00d0:Call ntoskrnl.exe.NtQuerySystemInformation(00000000,00b5f220,00000040,00b5f210) ret=00c85cc2 00d0:Call ntdll.NtQuerySystemInformation(00000000,00b5f220,00000040,00b5f210) ret=7bca040f 00d0:trace:ntdll:NtQuerySystemInformation (0x00000000,0xb5f220,0x00000040,0xb5f210) 00d0:Ret ntdll.NtQuerySystemInformation() retval=00000000 ret=7bca040f 00d0:Ret ntoskrnl.exe.NtQuerySystemInformation() retval=00000000 ret=00c85cc2 00d0:Call ntoskrnl.exe.NtQuerySystemInformation(000000b6,00b5f228,00000038,00b5f220) ret=00c85a01 00d0:Call ntdll.NtQuerySystemInformation(000000b6,00b5f228,00000038,00b5f220) ret=7bca040f 00d0:trace:ntdll:NtQuerySystemInformation (0x000000b6,0xb5f228,0x00000038,0xb5f220) 00d0:fixme:ntdll:NtQuerySystemInformation (0x000000b6,0xb5f228,0x00000038,0xb5f220) stub 00d0:Ret ntdll.NtQuerySystemInformation() retval=c0000003 ret=7bca040f 00d0:Ret ntoskrnl.exe.NtQuerySystemInformation() retval=c0000003 ret=00c85a01 00d0:trace:seh:raise_exception code=80000100 flags=1 addr=0x7bc6cb0c ip=7bc6cb0c tid=00d0 00d0:trace:seh:raise_exception info[0]=0000000000e00266 00d0:trace:seh:raise_exception info[1]=0000000000dffc02 00d0:trace:seh:call_vectored_handlers calling handler at 0x22cfc0 code=80000100 flags=1 ... wine: Call from 0x7bc6cb0c to unimplemented function ntoskrnl.exe.KeGenericCallDpc, aborting --- snip ---
Relevant disassembly snippet of driver:
---- snip --- 0000000140005ADF | mov rax,qword ptr ds:[rdi] | 0000000140005AE2 | call qword ptr ds:[rax+98] | schedule DPC 0000000140005AE8 | movaps xmm0,xmmword ptr ss:[rsp+40] | 0000000140005AED | lea r8,qword ptr ss:[rbp-30] | 0000000140005AF1 | movaps xmm1,xmmword ptr ss:[rsp+50] | 0000000140005AF6 | test al,al | 0000000140005AF8 | movups xmmword ptr ss:[rbp-28],xmm0 | 0000000140005AFC | mov dword ptr ss:[rbp-30],6E | 0000000140005B03 | movaps xmm0,xmmword ptr ss:[rsp+60] | 0000000140005B08 | setne byte ptr ss:[rbp-38] | ... 0000000140005770 | sub rsp,28 | 0000000140005774 | lea rdx,qword ptr ss:[rsp+38] | 0000000140005779 | mov qword ptr ss:[rsp+38],1 | 0000000140005782 | lea rcx,qword ptr ds:[1400057A0] | 1400057A0 = DPC 0000000140005789 | call qword ptr ds:[140077130] | KeGenericCallDpc 000000014000578F | cmp qword ptr ss:[rsp+38],1 | 0000000140005795 | sete al | 0000000140005798 | add rsp,28 | 000000014000579C | ret | ... --- snip ---
KeGenericCallDpc, KeSignalCallDpcSynchronize, KeSignalCallDpcDone API are used to implement a kernel-level barrier. I grouped them in this ticket because the functionality is intrinsically linked together.
The DPC itself (checks for IA32_EFER.NXE):
--- snip --- 00000001400057A0 | mov qword ptr ss:[rsp+8],rbx | 00000001400057A5 | mov qword ptr ss:[rsp+10],rsi | 00000001400057AA | push rdi | 00000001400057AB | sub rsp,20 | 00000001400057AF | mov rsi,r8 | 00000001400057B2 | mov rdi,rdx | 00000001400057B5 | mov ecx,C0000080 | IA32_EFER 00000001400057BA | rdmsr | 00000001400057BC | shl rdx,20 | 00000001400057C0 | mov rcx,r9 | 00000001400057C3 | or rax,rdx | rax |= (rdx << 32) 00000001400057C6 | mov rbx,rax | 00000001400057C9 | call qword ptr ds:[140077140] | KeSignalCallDpcSynchronize 00000001400057CF | shr rbx,B | IA32_EFER.NXE 00000001400057D3 | test bl,1 | 00000001400057D6 | jne denuvo-anti-cheat.1400057DF | 00000001400057D8 | mov qword ptr ds:[rdi],0 | 00000001400057DF | mov rcx,rsi | 00000001400057E2 | mov rbx,qword ptr ss:[rsp+30] | 00000001400057E7 | mov rsi,qword ptr ss:[rsp+38] | 00000001400057EC | add rsp,20 | 00000001400057F0 | pop rdi | 00000001400057F1 | jmp qword ptr ds:[140077138] | KeSignalCallDpcDone --- snip ---
MSR 0xC0000080
--- quote --- Extended Feature Enable Register (EFER) is a model-specific register added in the AMD K6 processor, to allow enabling the SYSCALL/SYSRET instruction, and later for entering and exiting long mode. This register becomes architectural in AMD64 and has been adopted by Intel as IA32_EFER. Its MSR number is 0xC0000080. --- quote ---
https://software.intel.com/sites/default/files/managed/7c/f1/253668-sdm-vol-...
Bit 11 = IA32_EFER.NXE = NXE/XD (No-Execute Enable/Execute Disable)
$ wine --version wine-5.8-324-g2c571df40b
Regards