http://bugs.winehq.org/show_bug.cgi?id=29448
Anastasius Focht focht@gmx.net changed:
What |Removed |Added ---------------------------------------------------------------------------- Keywords| |obfuscation CC| |focht@gmx.net Component|-unknown |kernel32 Summary|Software Shield demo won't |GameShield/SoftwareShield |start |protected apps/games won't | |start (SetCurrentDirectoryA | |calling W API causes | |detours recursion)
--- Comment #12 from Anastasius Focht focht@gmx.net 2013-08-17 14:23:31 CDT --- Hello folks,
encountered this problem with "Louisiana Adventure Demo" (bug 34275) which is protected by GameShield.
A common symptom is the message:
--- snip --- err:seh:setup_exception_record stack overflow 832 bytes in thread 002c eip 0049fdcf esp 00240ff0 stack 0x240000-0x241000-0x340000 --- snip ---
The protection hooks (detours) a number of win32 API. Example dump from memory:
--- snip --- 00FE2A88 0103ACA0 ; PTR to ASCII 10,"THookCreateFileW" 00FE2A8C 0103ACC0 ; PTR to ASCII 0D,"THookReadFile" 00FE2A90 0103ACE0 ; PTR to ASCII 0F,"THookReadFileEx" 00FE2A94 00000000 00FE2A98 00000000 00FE2A9C 0103AD00 ; PTR to ASCII 10,"THookCloseHandle" 00FE2AA0 0103AD20 ; PTR to ASCII 13,"THookSetFilePointer" 00FE2AA4 0103ADA0 ; PTR to ASCII 17,"THookCreateFileMappingW" 00FE2AA8 0103AD60 ; PTR to ASCII 17,"THookCreateFileMappingA" 00FE2AAC 0103ADE0 ; PTR to ASCII 12,"THookMapViewOfFile" 00FE2AB0 0103AE20 ; PTR to ASCII 18,"THookGetOverlappedResult" 00FE2AB4 0103AE60 ; PTR to ASCII 10,"THookGetFileSize" 00FE2AB8 0103AE80 ; PTR to ASCII 12,"THookGetFileSizeEx" 00FE2ABC 0103AEC0 ; PTR to ASCII 14,"THookUnmapViewOfFile" 00FE2AC0 0103AF00 ; PTR to ASCII 14,"THookMapViewOfFileEx" 00FE2AC4 0103AF40 ; PTR to ASCII 0E,"THookCopyFileW" 00FE2AC8 0103AF60 ; PTR to ASCII 10,"THookCopyFileExW" 00FE2ACC 0103AF80 ; PTR to ASCII 13,"THookFindFirstFileW" 00FE2AD0 0103AFC0 ; PTR to ASCII 15,"THookFindFirstFileExW" 00FE2AD4 0103B000 ; PTR to ASCII 12,"THookFindNextFileW" 00FE2AD8 0103B040 ; PTR to ASCII 0E,"THookFindClose" 00FE2ADC 0103B0C0 ; PTR to ASCII 10,"THookSearchPathW" 00FE2AE0 0103B0E0 ; PTR to ASCII 17,"THookGetFileAttributesW" 00FE2AE4 0103B120 ; PTR to ASCII 19,"THookGetFileAttributesExW" 00FE2AE8 0103B8C0 ; PTR to ASCII 17,"THookAddFontResourceExA" 00FE2AEC 0103B900 ; PTR to ASCII 17,"THookAddFontResourceExW" 00FE2AF0 0103B940 ; PTR to ASCII 1A,"THookRemoveFontResourceExW" 00FE2AF4 0103B140 ; PTR to ASCII 10,"THookGetFileType" 00FE2AF8 0103B160 ; PTR to ASCII 10,"THookGetFileTime" 00FE2AFC 0103B180 ; PTR to ASCII 1F,"THookGetFileInformationByHandle" 00FE2B00 0103B1A0 ; PTR to ASCII 19,"THookSetCurrentDirectoryA" 00FE2B04 0103B1C0 ; PTR to ASCII 19,"THookSetCurrentDirectoryW" 00FE2B08 0103B260 ; PTR to ASCII 1D,"THookGetPrivateProfileStringA" 00FE2B0C 0103B280 ; PTR to ASCII 1D,"THookGetPrivateProfileStringW" 00FE2B10 0103B2A0 ; PTR to ASCII 1E,"THookGetPrivateProfileSectionA" 00FE2B14 0103B2C0 ; PTR to ASCII 1E,"THookGetPrivateProfileSectionW" 00FE2B18 0103B060 ; PTR to ASCII 21,"THookFindFirstChangeNotificationW" 00FE2B1C 0103B080 ; PTR to ASCII 1F,"THookFindNextChangeNotification" 00FE2B20 0103B0A0 ; PTR to ASCII 20,"THookFindCloseChangeNotification" 00FE2B24 0103B220 ; PTR to ASCII 15,"THookSetFilePointerEx" 00FE2B28 0103B1E0 ; PTR to ASCII 14,"THookReadFileScatter" 00FE2B2C 00000000 ... --- snip ---
Each API to be detoured has a descriptor. Example for "SetCurrentDirectoryA":
--- snip --- 0103B1A0 00D6D9F4 ; ASCII 19,"THookSetCurrentDirectoryA" 0103B1A4 01041EE0 ; ASCII "SetCurrentDirectoryA" 0103B1A8 7B810000 ; base 0103B1AC 7FFC04D4 ; detour continuation thunk 0103B1B0 7B8600AB ; KERNEL32.SetCurrentDirectoryA 0103B1B4 00000001 ; ref 0103B1B8 00000000 ; entry terminator --- snip ---
The original entry point detoured:
KERNEL32.SetCurrentDirectoryA(Path)
--- snip --- 7B8600AB E9 13047604 JMP 7FFC04C3 7B8600B0 E4 F0 IN AL,0F0 7B8600B2 FF71 FC PUSH DWORD PTR DS:[ECX-4] 7B8600B5 55 PUSH EBP 7B8600B6 89E5 MOV EBP,ESP 7B8600B8 53 PUSH EBX 7B8600B9 51 PUSH ECX 7B8600BA 83EC 20 SUB ESP,20 7B8600BD E8 EEF2FBFF CALL 7B81F3B0 7B8600C2 81C3 3E8F0500 ADD EBX,58F3E 7B8600C8 89C8 MOV EAX,ECX 7B8600CA C74424 04 00000 MOV DWORD PTR SS:[ESP+4],0 7B8600D2 8B00 MOV EAX,DWORD PTR DS:[EAX] 7B8600D4 890424 MOV DWORD PTR SS:[ESP],EAX 7B8600D7 E8 12D0FDFF CALL 7B83D0EE 7B8600DC 8945 F4 MOV DWORD PTR SS:[EBP-0C],EAX 7B8600DF 837D F4 00 CMP DWORD PTR SS:[EBP-0C],0 7B8600E3 75 07 JNE SHORT 7B8600EC 7B8600E5 B8 00000000 MOV EAX,0 7B8600EA EB 0E JMP SHORT 7B8600FA 7B8600EC 8B45 F4 MOV EAX,DWORD PTR SS:[EBP-0C] 7B8600EF 890424 MOV DWORD PTR SS:[ESP],EAX 7B8600F2 E8 46FFFFFF CALL SetCurrentDirectoryW 7B8600F7 83EC 04 SUB ESP,4 7B8600FA 8D65 F8 LEA ESP,[EBP-8] 7B8600FD 59 POP ECX 7B8600FE 5B POP EBX 7B8600FF 5D POP EBP 7B860100 8D61 FC LEA ESP,[ECX-4] 7B860103 C2 0400 RETN 4 --- snip ---
This is the call sequence leading to failure, gathered from debugging:
--- snip --- SetCurrentDirectoryA[entry] -> THookSetCurrentDirectoryA -> SetCurrentDirectoryA[cont] -> SetCurrentDirectoryW[entry] -> THookSetCurrentDirectoryW -> SetCurrentDirectoryA[cont] (bug) -> SetCurrentDirectoryW[entry] (recursion) --- snip ---
The problem appears with nested hooks. The protection code reads private data from TLS during detour-handling to retrieve the continuation thunk address. Although per thread the code doesn't handle nesting properly, ending with previous (parent) continuation thunk being called, leading to recursion.
Windows SetCurrentDirectoryA() probably doesn't forward the native API call to W API.
I made a small inline wrapper for SetCurrentDirectoryW() code and had both, SetCurrentDirectoryW() and SetCurrentDirectoryA() call it. This avoids hitting both hooks with SetCurrentDirectoryA().
With the patch applied, the protection code is happy. There might be still similar issues for other API left but the game from bug 34275 started to work (only to run into d3dx9 shader compiler bug).
Also "iw4win.exe" (IronWrapper: IronWrap Linker) starts now though I didn't bother to figure out how the thing works. It seems to require an application xml config file as input for further processing.
Regards