[Bug 29448] GameShield/SoftwareShield protected apps/games won't start (SetCurrentDirectoryA calling W API causes detours recursion)

wine-bugs at winehq.org wine-bugs at winehq.org
Sat Aug 17 14:23:31 CDT 2013


http://bugs.winehq.org/show_bug.cgi?id=29448

Anastasius Focht <focht at gmx.net> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
           Keywords|                            |obfuscation
                 CC|                            |focht at 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 at 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

-- 
Configure bugmail: http://bugs.winehq.org/userprefs.cgi?tab=email
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