https://bugs.winehq.org/show_bug.cgi?id=44617
Bug ID: 44617 Summary: Multiple Blizzard games need Win7+ 'user32.GetWindowDisplayAffinity' and 'user32.SetWindowDisplayAffinity' stubs (Diablo III v2. 6. 1. 49286+) Product: Wine Version: 3.2 Hardware: x86-64 OS: Linux Status: NEW Severity: normal Priority: P2 Component: user32 Assignee: wine-bugs@winehq.org Reporter: focht@gmx.net Distribution: ---
Hello folks,
continuation of bug 44616
After ntdll.LdrRegisterDllNotification(), the obfuscated code resolves another bunch of imports. The module and API function names to be resolved are obfuscated using pre-computed hashes. Basically the in-memory export table for 'ntdll, 'kernel32', 'user32' and 'gdi32' modules is walked, all the function names are hashed and compared against the precomputed hashes for matches. There is even a Windows version awareness in this phase. Depending on the WinVer setting (WinXP vs. Win7), few different APIs are resolved.
Tidbit:
If the Windows version is configured to 'Windows XP' in WINEPREFIX this API is not resolved. It was introduced with Windows 7+ and is related to on-screen content protection (DRM). This is a non-default anyway and the game/launcher will complain about Windows XP being no longer unsupported (end-of-life).
Trace log with patches applied:
NOTE: The actual calls for this API are very late, hence not seen here. It's only to document the place where the (invisible) imports resolver process took place: in between 'ntdll.LdrRegisterDllNotification' and 'ntdll.NtCreateFile' calls.
--- snip --- $ pwd /home/focht/wine-games/wineprefix64-bnet/drive_c/Program Files (x86)/Diablo III
$ WINEDEBUG=+loaddll,+ntdll,+seh,+process,+relay wine ./Diablo\ III.exe -launch >>log.txt 2>&1 ... 0009:Call ntdll.LdrRegisterDllNotification(00000000,006a0ce0,00000000,0033e628) ret=004db5d0 0009:Ret ntdll.LdrRegisterDllNotification() retval=00000000 ret=004db5d0 0009:Call ntdll.NtCreateFile(0033e3a8,00120089,0033e32c,0033e324,00000000,00000000,00000001,00000001,00000020,00000000,00000000) ret=004e0a5f 0009:trace:ntdll:FILE_CreateFile handle=0x33e3a8 access=00120089 name=L"\??\C:\windows\system32\ntdll.dll" objattr=00000040 root=(nil) sec=(nil) io=0x33e324 alloc_size=(nil) attr=00000000 sharing=00000001 disp=1 options=00000020 ea=(nil).0x00000000 0009:Ret ntdll.NtCreateFile() retval=00000000 ret=004e0a5f 0009:Call ntdll.NtQueryInformationFile(000000ac,0033e31c,0033e304,00000018,00000005) ret=004e0f91 0009:trace:ntdll:NtQueryInformationFile (0xac,0x33e31c,0x33e304,0x00000018,0x00000005) 0009:Ret ntdll.NtQueryInformationFile() retval=00000000 ret=004e0f91 0009:Call ntdll.NtAllocateVirtualMemory(ffffffff,0033e404,00000000,0033e374,00001000,00000040) ret=004e143d 0009:Ret ntdll.NtAllocateVirtualMemory() retval=00000000 ret=004e143d 0009:Call ntdll.NtReadFile(000000ac,00000000,00000000,00000000,0033e324,05070000,00001000,00000000,00000000) ret=004e1786 0009:trace:ntdll:NtReadFile (0xac,(nil),(nil),(nil),0x33e324,0x5070000,0x00001000,(nil),(nil)),partial stub! 0009:trace:ntdll:NtReadFile = SUCCESS (2468) 0009:Ret ntdll.NtReadFile() retval=00000000 ret=004e1786 0009:Call ntdll.NtAllocateVirtualMemory(ffffffff,0033e638,00000000,0033e698,00001000,00000004) ret=004dbcee 0009:Ret ntdll.NtAllocateVirtualMemory() retval=00000000 ret=004dbcee 0009:Call ntdll.NtProtectVirtualMemory(ffffffff,0033e6e4,0033e6e8,00000040,0033e69c) ret=004dcdae 0009:Ret ntdll.NtProtectVirtualMemory() retval=00000000 ret=004dcdae 0009:Call ntdll.NtProtectVirtualMemory(ffffffff,0033e6e4,0033e6e8,00000020,0033e69c) ret=004dcf8c 0009:Ret ntdll.NtProtectVirtualMemory() retval=00000000 ret=004dcf8c 0009:Call ntdll.NtProtectVirtualMemory(ffffffff,0033e6e4,0033e6e8,00000040,0033e69c) ret=004dcdae 0009:Ret ntdll.NtProtectVirtualMemory() retval=00000000 ret=004dcdae 0009:Call ntdll.NtProtectVirtualMemory(ffffffff,0033e6e4,0033e6e8,00000020,0033e69c) ret=004dcf8c 0009:Ret ntdll.NtProtectVirtualMemory() retval=00000000 ret=004dcf8c 0009:Call ntdll.NtCreateThreadEx(0033e620,001f03ff,00000000,ffffffff,006a3e90,00000000,00000006,00000000,00000000,00000000,00000000) ret=004dd373 0009:fixme:thread:NtCreateThreadEx 0x33e620, 1f03ff, (nil), 0xffffffff, 0x6a3e90, (nil), 6, 0, 0, 0, (nil) semi-stub! 0009:Ret ntdll.NtCreateThreadEx() retval=00000000 ret=004dd373 0029:Call PE DLL (proc=0x7ec4ae82,module=0x7eba0000 L"user32.dll",reason=THREAD_ATTACH,res=(nil)) 0029:Ret PE DLL (proc=0x7ec4ae82,module=0x7eba0000 L"user32.dll",reason=THREAD_ATTACH,res=(nil)) retval=1 0029:Call PE DLL (proc=0x7e7facd4,module=0x7e7f0000 L"imm32.dll",reason=THREAD_ATTACH,res=(nil)) 0029:Ret PE DLL (proc=0x7e7facd4,module=0x7e7f0000 L"imm32.dll",reason=THREAD_ATTACH,res=(nil)) retval=1 0029:Call TLS callback (proc=0x6aa080,module=0x400000,reason=THREAD_ATTACH,reserved=0) 0029:trace:seh:raise_exception code=c000001d flags=0 addr=0x6aa143 ip=006aa143 tid=0029 0029:trace:seh:raise_exception eax=0518e9f0 ebx=f75c5000 ecx=1675b829 edx=0518e9f0 esi=0518e9d8 edi=05193b40 0029:trace:seh:raise_exception ebp=0518e9b8 esp=0518e994 cs=0023 ds=002b es=002b fs=0063 gs=006b flags=00010246 0029:trace:seh:call_stack_handlers calling handler at 0x111e8c8 code=c000001d flags=0 0029:Call ntdll.NtDuplicateObject(ffffffff,fffffffe,ffffffff,0518e3ec,00000000,00000000,00000006) ret=006a7804 0029:Ret ntdll.NtDuplicateObject() retval=00000000 ret=006a7804 0029:Call ntdll.NtQueryInformationThread(000000b4,00000009,0518e404,00000004,00000000) ret=006a80e9 0029:Ret ntdll.NtQueryInformationThread() retval=00000000 ret=006a80e9 0029:Call ntdll.NtSetInformationThread(000000b4,00000011,00000000,00000000) ret=006a8997 0029:Ret ntdll.NtSetInformationThread() retval=00000000 ret=006a8997 ... --- snip ---
ProtectionID scan for exact version:
--- snip --- -=[ ProtectionID v0.6.9.0 DECEMBER]=- (c) 2003-2017 CDKiLLER & TippeX Build 24/12/17-21:05:42 Ready... Scanning -> Z:\home\focht\wine-games\wineprefix64-bnet\drive_c\Program Files (x86)\Diablo III\Diablo III.exe File Type : 32-Bit Exe (Subsystem : Win GUI / 2), Size : 31663592 (01E325E8h) Byte(s) | Machine: 0x14C (I386) Compilation TimeStamp : 0x5A839757 -> Wed 14th Feb 2018 01:56:39 (GMT) [TimeStamp] 0x5A839757 -> Wed 14th Feb 2018 01:56:39 (GMT) | PE Header | - | Offset: 0x00000178 | VA: 0x00400178 | - [TimeStamp] 0x5A83974F -> Wed 14th Feb 2018 01:56:31 (GMT) | Export | - | Offset: 0x0176EC84 | VA: 0x01B70484 | - [TimeStamp] 0x5A839757 -> Wed 14th Feb 2018 01:56:39 (GMT) | DebugDirectory | - | Offset: 0x015380D4 | VA: 0x019398D4 | - [TimeStamp] 0x5A839757 -> Wed 14th Feb 2018 01:56:39 (GMT) | DebugDirectory | - | Offset: 0x015380F0 | VA: 0x019398F0 | - [TimeStamp] 0x5A839757 -> Wed 14th Feb 2018 01:56:39 (GMT) | DebugDirectory | - | Offset: 0x0153810C | VA: 0x0193990C | - -> File Appears to be Digitally Signed @ Offset 01E30E00h, size : 017E8h / 06120 byte(s) [!] Executable uses TLS callbacks (3 total... 0 invalid addresses) [LoadConfig] Struct determined as v8 (Expected size 140 | Actual size 64) [!] Executable uses SEH Tables (/SAFESEH) (33371 calculated 33199 recorded... 70 invalid addresses) [!] * table may be compressed / encrypted * [LoadConfig] CodeIntegrity -> Flags 0x7C34 | Catalog 0xBFD3 (49107) | Catalog Offset 0x2FE93D5F | Reserved 0x49CB461F [LoadConfig] GuardAddressTakenIatEntryTable 0x4F29FF9C | Count 0x992AA633 (2569709107) [LoadConfig] GuardLongJumpTargetTable 0x12E9CCF3 | Count 0xB9F3D522 (3119764770) [LoadConfig] HybridMetadataPointer 0x21CA7CB6 | DynamicValueRelocTable 0xF1654DDC [LoadConfig] FailFastIndirectProc 0x64AE2974 | FailFastPointer 0xCA03C693 [LoadConfig] UnknownZero1 0x6B52C00 [!] Warning: Imports (+size) goes outside of the file [File Heuristics] -> Flag #1 : 00000100000001001101000100110100 (0x0404D134) [Entrypoint Section Entropy] : 8.00 (section #0) ".text " | Size : 0x132F368 (20116328) byte(s) [DllCharacteristics] -> Flag : (0x8140) -> ASLR | DEP | TSA [SectionCount] 9 (0x9) | ImageSize 0x21D7000 (35483648) byte(s) [Export] 96% of function(s) (357 of 369) are in file | 0 are forwarded | 343 code | 26 data | 0 uninit data | 0 unknown | [VersionInfo] Company Name : Blizzard Entertainment [VersionInfo] Product Name : Diablo III [VersionInfo] Product Version : Version 2.6 [VersionInfo] File Description : Diablo III Retail [VersionInfo] File Version : 2. 6. 1. 49286 [VersionInfo] Original FileName : Diablo III.exe [VersionInfo] Internal Name : Diablo III [VersionInfo] Legal Copyrights : Copyright © 2011-2014 [ModuleReport] [IAT] Modules -> USER32.dll [Debug Info] (record 1 of 3) (file offset 0x15380D0) Characteristics : 0x0 | TimeDateStamp : 0x5A839757 (Wed 14th Feb 2018 01:56:39 (GMT)) | MajorVer : 0 / MinorVer : 0 -> (0.0) Type : 2 (0x2) -> CodeView | Size : 0x53 (83) AddressOfRawData : 0x158C96C | PointerToRawData : 0x158B16C CvSig : 0x53445352 | SigGuid E65D58F8-37DC-47BC-B32D251EF458F1F8 Age : 0x1 (1) | Pdb : D:\BuildServer\4\work\code\branches\Release\Diablo III.pdb [Debug Info] (record 2 of 3) (file offset 0x15380EC) Characteristics : 0x0 | TimeDateStamp : 0x5A839757 (Wed 14th Feb 2018 01:56:39 (GMT)) | MajorVer : 0 / MinorVer : 0 -> (0.0) Type : 12 (0xC) -> Undocumented | Size : 0x14 (20) AddressOfRawData : 0x158C9C0 | PointerToRawData : 0x158B1C0 [Debug Info] (record 3 of 3) (file offset 0x1538108) Characteristics : 0x0 | TimeDateStamp : 0x5A839757 (Wed 14th Feb 2018 01:56:39 (GMT)) | MajorVer : 0 / MinorVer : 0 -> (0.0) Type : 13 (0xD) -> Undocumented | Size : 0x828 (2088) AddressOfRawData : 0x158C9D4 | PointerToRawData : 0x158B1D4 [CdKeySerial] found "Invalid code" @ VA: 0x0133D078 / Offset: 0x0133B878 [CdKeySerial] found "SerialNumber" @ VA: 0x0147899F / Offset: 0x0147719F [CdKeySerial] found "Invalid code" @ VA: 0x014C7980 / Offset: 0x014C6180 [CompilerDetect] -> Visual C++ 14.0 (Visual Studio 2015) [!] File appears to have no protection or is using an unknown protection - Scan Took : 5.583 Second(s) [000001529h (5417) tick(s)] [506 of 580 scan(s) done] --- snip ---
$ wine --version wine-3.2-173-g7c7aa125bf
Regards
https://bugs.winehq.org/show_bug.cgi?id=44617
Anastasius Focht focht@gmx.net changed:
What |Removed |Added ---------------------------------------------------------------------------- URL| |https://eu.battle.net/accou | |nt/download/ Staged patchset| |https://github.com/wine-sta | |ging/wine-staging/tree/mast | |er/patches/user32-WindowDis | |playAffinity Keywords| |download, obfuscation Status|NEW |STAGED Depends on| |44616
--- Comment #1 from Anastasius Focht focht@gmx.net --- Hello folks,
filling fields.
MSDN for reference: https://msdn.microsoft.com/en-us/library/windows/desktop/dd375338(v=vs.85).a...
Regards
https://bugs.winehq.org/show_bug.cgi?id=44617
--- Comment #2 from Anastasius Focht focht@gmx.net --- Hello folks,
with this and previous patches for bug 44585 and bug 44616 applied to Wine 3.2, the game starts and shows login screen.
Regards
https://bugs.winehq.org/show_bug.cgi?id=44617
Ker noa blue-t@web.de changed:
What |Removed |Added ---------------------------------------------------------------------------- CC| |blue-t@web.de
--- Comment #3 from Ker noa blue-t@web.de --- Is it possible to enhance wines debug output so that future games that use this kind of hidden imports get them automatically translated to cleartext?
https://bugs.winehq.org/show_bug.cgi?id=44617
--- Comment #4 from Anastasius Focht focht@gmx.net --- Hello,
--- quote --- Is it possible to enhance wines debug output so that future games that use this kind of hidden imports get them automatically translated to cleartext? --- quote ---
I'm not sure if I can further "ELI5" my comment #0
These type of apps/games/malware implement their own custom imports resolver. The win32/64 API function resolving is done on the application side with no visible API calls - it's walking/processing of in-memory data structures (tables/lists). Even if you would be able to trap memory accesses to the export table (outside of Wine's scope) .. you wouldn't even know which API the code is trying to lookup in case of Wine missing APIs (= reads until the end of list). One could certainly trace the access and record the "index" of the API the hash was generated for and later translate it back to real API in case of match ... but that requires debugging and deep understanding of the code, along with some fancy tracing. There is no way Wine could be of help here.
To make things more difficult it doesn't decrypt the encrypted (obfuscated) module/API name strings to compare "cleartext" against data from the loader linked lists/export tables. Instead it encrypts all the names and compares against precomputed encrypted ones. That's a much more effective way to hide all your doing - one is essentially forced to debug to see what's going on.
In short: No.
Regards
https://bugs.winehq.org/show_bug.cgi?id=44617
tokktokk fdsfgs@krutt.org changed:
What |Removed |Added ---------------------------------------------------------------------------- CC| |fdsfgs@krutt.org
https://bugs.winehq.org/show_bug.cgi?id=44617 Bug 44617 depends on bug 44616, which changed state.
Bug 44616 Summary: Multiple Blizzard games need 'ntdll.NtCreateThreadEx' implementation (Diablo III v2. 6. 1. 49286+, World of Warcraft, Overwatch) https://bugs.winehq.org/show_bug.cgi?id=44616
What |Removed |Added ---------------------------------------------------------------------------- Status|STAGED |RESOLVED Resolution|--- |FIXED
https://bugs.winehq.org/show_bug.cgi?id=44617
Alistair Leslie-Hughes leslie_alistair@hotmail.com changed:
What |Removed |Added ---------------------------------------------------------------------------- CC| |leslie_alistair@hotmail.com Resolution|--- |FIXED Status|STAGED |RESOLVED Fixed by SHA1| |76f135e599a191203c352edd020 | |9b640b2497810
--- Comment #5 from Alistair Leslie-Hughes leslie_alistair@hotmail.com --- Fixed by https://source.winehq.org/git/wine.git/?a=commit;h=76f135e599a191203c352edd0...
https://bugs.winehq.org/show_bug.cgi?id=44617
Alexandre Julliard julliard@winehq.org changed:
What |Removed |Added ---------------------------------------------------------------------------- Status|RESOLVED |CLOSED
--- Comment #6 from Alexandre Julliard julliard@winehq.org --- Closing bugs fixed in 3.4.