https://bugs.winehq.org/show_bug.cgi?id=45936
Anastasius Focht focht@gmx.net changed:
What |Removed |Added ---------------------------------------------------------------------------- Ever confirmed|0 |1 URL| |https://github.com/Jawesome | |99/IW4x/releases/tag/0.5.4- | |dirty-client Component|-unknown |winecrt0 CC| |focht@gmx.net Status|UNCONFIRMED |NEW Summary|IW4x crashes on keyboard |IW4x 0.5.4 crashes on |input |keyboard input, failure to | |delay load | |'imm32.dll.ImmProcessKey' | |('kernel32.dll.LoadLibraryA | |' made no-op by protection | |scheme, breaks | |'__wine_spec_delay_load') Product|Wine-staging |Wine Keywords| |download, obfuscation
--- Comment #4 from Anastasius Focht focht@gmx.net --- Hello folks,
confirming.
Instructions for install:
https://iw4x.tumblr.com/post/161974206329/install-iw4x
NOTE: Although Wine-Staging is required for reproducing the issue (figure out which patchset is needed later), using vanilla Wine as product here. I want to have the traceability in mainline.
The problem is caused by one of the anti-hack/debug protection mechanisms used by the client. Relay tracing interferes with it too, hence it has to be debugged ;-)
Executable modules map (excerpt):
--- snip --- Base Size Name File version Path 00400000 06C71000 iw4x 4.2.0.0 C:\games\MW2\iw4x.exe 0A0A0000 00020000 mssmp3 C:\games\MW2\miles\mssmp3.asi 0A0C0000 0002A000 mssvoice C:\games\MW2\miles\mssvoice.asi 0A0F0000 0001D000 milesEq C:\games\MW2\miles\milesEq.flt 0A110000 00006000 mssds3d C:\games\MW2\miles\mssds3d.flt 0A120000 00012000 mssdsp 7.0w C:\games\MW2\miles\mssdsp.flt 0A140000 00011000 msseax C:\games\MW2\miles\msseax.flt 10000000 00521000 iw4x_1pi 0.5.4 C:\games\MW2\iw4x.dll 18000000 00033000 binkw32 1.8x C:\games\MW2\binkw32.dll 21100000 00097000 mss32 7.0w C:\games\MW2\mss32.dll 7A840000 00109000 opengl32 5.1.2600.2082 C:\windows\system32\opengl32.dll 7B420000 003D6000 KERNEL32 5.01.2600.2180 C:\windows\system32\KERNEL32.dll 7BC40000 000EC000 ntdll 6.1.7601.24059 C:\windows\system32\ntdll.dll ... --- snip ---
Relevant list of hooked API entry points:
--- snip --- Address Name Destination 7B46589B LoadLibraryA E9 B0FDDC94 JMP iw4x_1pi.10235650 7B465710 LoadLibraryExA E9 33FFDC94 JMP iw4x_1pi.10235648 7B4658DF LoadLibraryW E9 6CFDDC94 JMP iw4x_1pi.10235650 7B465779 LoadLibraryExW E9 CAFEDC94 JMP iw4x_1pi.10235648 --- snip ---
--- snip --- 10235648 33C0 XOR EAX,EAX 1023564A C2 0C00 RETN 0C ... 10235650 33C0 XOR EAX,EAX 10235652 C2 0400 RETN 4 --- snip ---
As you can see the protection scheme essentially no-ops LoadLibrary() after the hooks have been set up which harms Wine later.
https://source.winehq.org/git/wine.git/blob/HEAD:/dlls/user32/message.c#l239...
--- snip --- 2395 /*********************************************************************** 2396 * process_keyboard_message 2397 * 2398 * returns TRUE if the contents of 'msg' should be passed to the application 2399 */ 2400 static BOOL process_keyboard_message( MSG *msg, UINT hw_id, HWND hwnd_filter, 2401 UINT first, UINT last, BOOL remove ) 2402 { 2403 EVENTMSG event; ... 2466 accept_hardware_message( hw_id, remove ); 2467 msg->pt = point_phys_to_win_dpi( msg->hwnd, msg->pt ); 2468 2469 if ( remove && msg->message == WM_KEYDOWN ) 2470 if (ImmProcessKey(msg->hwnd, GetKeyboardLayout(0), msg->wParam, msg->lParam, 0) ) 2471 msg->wParam = VK_PROCESSKEY; 2472 2473 return TRUE; 2474 } --- snip ---
https://source.winehq.org/git/wine.git/blob/HEAD:/dlls/user32/Makefile.in
--- snip --- 6 DELAYIMPORTS = hid imm32 setupapi usp10 --- snip ---
https://source.winehq.org/git/wine.git/blob/HEAD:/dlls/winecrt0/delay_load.c...
--- snip --- 40 41 FARPROC WINAPI DECLSPEC_HIDDEN __wine_spec_delay_load( unsigned int id ) 42 { 43 struct ImgDelayDescr *descr = __wine_spec_delay_imports + HIWORD(id); 44 WORD func = LOWORD(id); 45 FARPROC proc; 46 47 if (!*descr->phmod) *descr->phmod = LoadLibraryA( descr->szName ); 48 if (!*descr->phmod || 49 !(proc = GetProcAddress( *descr->phmod, (LPCSTR)descr->pINT[func].u1.Function ))) 50 proc = DelayLoadFailureHook( descr->szName, (LPCSTR)descr->pINT[func].u1.Function ); 51 descr->pIAT[func].u1.Function = (ULONG_PTR)proc; 52 return proc; 53 } 54 55 #if defined(__GNUC__) && !defined(__APPLE__) /* we can't support destructors properly on Mac OS */ 56 static void free_delay_imports(void) __attribute__((destructor)); 57 static void free_delay_imports(void) 58 { 59 struct ImgDelayDescr *descr; 60 for (descr = __wine_spec_delay_imports; descr->szName; descr++) 61 if (*descr->phmod) FreeLibrary( *descr->phmod ); 62 } 63 #endif --- snip ---
Wine's delay load implementation uses LoadLibraryA() which has been made a no-op by the client protection, hence the failure.
There are multiple ways to fix this:
* don't delay load 'imm32.dll' from user32.dll' * use native API for loading the module * try GetModuleHandleExA() first before LoadLibraryA()
For quick testing I went for the third option. GetModuleHandleExA() has to be used which increments the module's reference count as free_delay_imports() uses FreeLibrary().
ProtectionID scan:
--- snip --- -=[ ProtectionID v0.6.9.0 DECEMBER]=- (c) 2003-2017 CDKiLLER & TippeX Build 24/12/17-21:05:42 Ready... Scanning -> C:\games\MW2\iw4x.exe File Type : 32-Bit Exe (Subsystem : Win CUI / 3), Size : 4186112 (03FE000h) Byte(s) | Machine: 0x14C (I386) Compilation TimeStamp : 0x00000000 -> Thu 01st Jan 1970 00:00:00 (GMT) [LoadConfig] Struct determined as v8 (Expected size 140 | Actual size 64) [!] Executable uses SEH Tables (/SAFESEH) (16 calculated 16 recorded... 0 invalid addresses) [LoadConfig] CodeIntegrity -> Flags 0x0 | Catalog 0x0 (0) | Catalog Offset 0x53445352 | Reserved 0x92C634B2 [LoadConfig] GuardAddressTakenIatEntryTable 0x4C7E25DE | Count 0xFC1760AC (4229390508) [LoadConfig] GuardLongJumpTargetTable 0x1DA6F819 | Count 0x0 (0) [LoadConfig] HybridMetadataPointer 0x5C5C785C | DynamicValueRelocTable 0x6D347769 [LoadConfig] FailFastIndirectProc 0x64702E70 | FailFastPointer 0x62 [LoadConfig] UnknownZero1 0x0 [File Heuristics] -> Flag #1 : 00000100000000001000000000000000 (0x04008000) [Entrypoint Section Entropy] : 6.71 (section #0) ".text " | Size : 0x2D531F (2970399) byte(s) [DllCharacteristics] -> Flag : (0x0000) -> NONE [SectionCount] 6 (0x6) | ImageSize 0x6C71000 (113709056) byte(s) [VersionInfo] Product Name : IW4x [VersionInfo] Product Version : 4.2.0.0 [VersionInfo] File Description : IW4x Multiplayer [VersionInfo] File Version : 4.2.0.0 [VersionInfo] Original FileName : iw4x.exe [VersionInfo] Internal Name : iw4x [VersionInfo] Legal Copyrights : No rights reserved. [ModuleReport] [IAT] Modules -> WINMM.dll | WSOCK32.dll | iw4x.dll | mss32.dll | binkw32.dll | d3d9.dll | DSOUND.dll | POWRPROF.dll | KERNEL32.dll | USER32.dll | GDI32.dll | ADVAPI32.dll | SHELL32.dll | ole32.dll | DDRAW.dll [Debug Info] (record 1 of 1) (file offset 0x339AD0) Characteristics : 0x0 | TimeDateStamp : 0x0 () | MajorVer : 0 / MinorVer : 0 -> (0.0) Type : 2 (0x2) -> CodeView | Size : 0x6B (107) AddressOfRawData : 0x390E18 | PointerToRawData : 0x390E18 CvSig : 0x53445352 | SigGuid 92C634B2-25DE-4C7E-AC6017FC19F8A61D Age : 0x0 (0) | Pdb : \x\iw4mp.pdb [i] additional feature : Valve CEG - Custom Executable Generation [.] CEG Build Version : 1, 1, 0, 1525 [.] CEG Product Version : 1, 1, 0, 1525 [.] CEG Build GUID : 3AE713D6-1855-4e8e-B3E7-8803674E1496 [.] CEG Build Machine : neilk2 [.] CEG Build Client Spec : neilk2_main2 [CdKeySerial] found "CDKey" @ VA: 0x002EEB9B / Offset: 0x002EEB9B [CdKeySerial] found "Unregistered" @ VA: 0x002F0B9D / Offset: 0x002F0B9D [CdKeySerial] found "Unregistered" @ VA: 0x00304BC6 / Offset: 0x00304BC6 [CdKeySerial] found "Unregistered" @ VA: 0x00306352 / Offset: 0x00306352 [CdKeySerial] found "Unregistered" @ VA: 0x0032BEAA / Offset: 0x0032BEAA [CompilerDetect] -> Visual C++ 8.0 (Visual Studio 2005) - Scan Took : 1.982 Second(s) [0000003FAh (1018) tick(s)] [506 of 580 scan(s) done]
Scanning -> C:\games\MW2\iw4x.dll File Type : 32-Bit Dll (Subsystem : Win GUI / 2), Size : 3061760 (02EB800h) Byte(s) | Machine: 0x14C (I386) Compilation TimeStamp : 0x5B7C4380 -> Tue 21st Aug 2018 16:53:20 (GMT) [TimeStamp] 0x5B7C4380 -> Tue 21st Aug 2018 16:53:20 (GMT) | PE Header | - | Offset: 0x00000120 | VA: 0x10000120 | - [TimeStamp] 0xFFFFFFFF -> Sun 07th Feb 2106 06:28:15 (GMT) | Export | - | Offset: 0x002C8A84 | VA: 0x104FC484 | - [!] Executable uses TLS callbacks (2 total... 0 invalid addresses) [LoadConfig] Struct determined as v8 (Expected size 140 | Actual size 64) [!] Executable uses SEH Tables (/SAFESEH) (2078 calculated 2062 recorded... 14 invalid addresses) [!] * table may be compressed / encrypted * [LoadConfig] CodeIntegrity -> Flags 0x0 | Catalog 0x0 (0) | Catalog Offset 0x0 | Reserved 0x0 [LoadConfig] GuardAddressTakenIatEntryTable 0x0 | Count 0x0 (0) [LoadConfig] GuardLongJumpTargetTable 0x0 | Count 0x0 (0) [LoadConfig] HybridMetadataPointer 0x0 | DynamicValueRelocTable 0x0 [LoadConfig] FailFastIndirectProc 0x0 | FailFastPointer 0x0 [LoadConfig] UnknownZero1 0x0 [File Heuristics] -> Flag #1 : 00000000000000001101000100000000 (0x0000D100) [Entrypoint Section Entropy] : 6.59 (section #0) ".UPX0 " | Size : 0x21FC60 (2227296) byte(s) [DllCharacteristics] -> Flag : (0x0140) -> ASLR | DEP [SectionCount] 5 (0x5) | ImageSize 0x521000 (5378048) byte(s) [Export] 100% of function(s) (65 of 65) are in file | 0 are forwarded | 64 code | 1 data | 0 uninit data | 0 unknown | [VersionInfo] Company Name : IW4x [VersionInfo] Product Name : IW4x [VersionInfo] Product Version : 0.5.4 [VersionInfo] File Description : IW4 client modification [VersionInfo] File Version : 0.5.4 [VersionInfo] Original FileName : iw4x.dll [VersionInfo] Internal Name : iw4x [VersionInfo] Legal Copyrights : Copyright 2017 The IW4x Team. All rights reserved. [ModuleReport] [IAT] Modules -> KERNEL32.DLL | ADVAPI32.dll | d3d9.dll | d3dx9_40.dll | dbghelp.dll | SHELL32.dll | SHLWAPI.dll | urlmon.dll | USER32.dll | WININET.dll | WINMM.dll | WS2_32.dll [Raw/Hidden Debug Record] (File Offset 0x292FA8) CvSig : 0x53445352 | SigGuid 83F25363-D6E3-4E6C-A99E39AA34FA867B Age : 0xD (13) | Pdb : F:\Git\iw4x\build\bin\Release\iw4x.pdb [CdKeySerial] found "Invalid code" @ VA: 0x004AD2A0 / Offset: 0x002798A0 [CdKeySerial] found "Invalid code" @ VA: 0x004AD2D8 / Offset: 0x002798D8 [!] File appears to have no protection or is using an unknown protection - Scan Took : 0.734 Second(s) [0000002DEh (734) tick(s)] [246 of 580 scan(s) done] --- snip ---
$ sha1sum * 5954d619517fd1db1fb8d3ea8a433e493f745fa5 installer_legacy.exe f82b22e39458212a4dbc3794624a967e28f24628 iw4x_files.zip 00b63831ed7b8abf5191fc308bd135a63d15a000 MW2.zip
$ du -sh * 2.4M installer_legacy.exe 99M iw4x_files.zip 12G MW2.zip
$ wine --version wine-3.17-74-gee206a3760
Regards