[Bug 45936] IW4x 0.5.4 crashes on keyboard input, failure to delay load ' imm32.dll.ImmProcessKey' ('kernel32.dll.LoadLibraryA' made no-op by protection scheme, breaks '__wine_spec_delay_load')

wine-bugs at winehq.org wine-bugs at winehq.org
Fri Oct 5 18:03:44 CDT 2018


https://bugs.winehq.org/show_bug.cgi?id=45936

Anastasius Focht <focht at 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 at 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 at 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#l2395

--- 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#l41

--- 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

-- 
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