[Bug 37785] New: dBASE Plus 9.x demo crashes on startup (custom DRM scheme translates API entry points to dynamic thunks, calling PIC code outside of original code section)

wine-bugs at winehq.org wine-bugs at winehq.org
Fri Dec 26 16:21:19 CST 2014


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

            Bug ID: 37785
           Summary: dBASE Plus 9.x demo crashes on startup (custom DRM
                    scheme translates API entry points to dynamic thunks,
                    calling PIC code outside of original code section)
           Product: Wine
           Version: 1.7.33
          Hardware: x86
                OS: Linux
            Status: NEW
          Severity: normal
          Priority: P2
         Component: kernel32
          Assignee: wine-bugs at winehq.org
          Reporter: focht at gmx.net
      Distribution: ---

Hello folks,

reported by a user in #winehq

The app seems to be protected by a custom DRM scheme which causes some grief.
I couldn't find a known signature using protection scanners ... but that
doesn't matter in the end :)

Another protection that tries to be uberclever, rewriting/translating API entry
points.

Unlike other protection schemes which only target the prolog code, this one
processes *all* entry point opcodes.

It disassembles them and partially replaces opcodes with alternatives which
preserves the original semantics of the code sequence. The "new" sequence is
written out to a dynamic thunk on heap and referred via trampolines from its
own code.

Example API entry, original 'GetStartupInfoW':

--- snip ---
.text:7B83ADE7     push    ebp
.text:7B83ADE8     mov     ebp, esp
.text:7B83ADEA     push    edi
.text:7B83ADEB     push    esi
.text:7B83ADEC     push    ebx
.text:7B83ADED     call    __x86_get_pc_thunk_bx
.text:7B83ADF2     add     ebx, 8420Eh
.text:7B83ADF8     mov     eax, [ebp+8]
.text:7B83ADFB     mov     edx, eax
.text:7B83ADFD     lea     esi, (startup_infoW.cb - 7B8BF000h)[ebx]
.text:7B83AE03     mov     eax, 11h
.text:7B83AE08     mov     edi, edx
.text:7B83AE0A     mov     ecx, eax
.text:7B83AE0C     rep movsd
.text:7B83AE0E     pop     ebx
.text:7B83AE0F     pop     esi
.text:7B83AE10     pop     edi
.text:7B83AE11     pop     ebp
.text:7B83AE12     retn    4
--- snip ---

The protection scheme translates the entry point to a dynamic thunk:

--- snip ---
003E3208    52              PUSH EDX
003E3209    892C24          MOV DWORD PTR SS:[ESP],EBP
003E320C    89E5            MOV EBP,ESP
003E320E    52              PUSH EDX
003E320F    893C24          MOV DWORD PTR SS:[ESP],EDI
003E3212    50              PUSH EAX
003E3213    893424          MOV DWORD PTR SS:[ESP],ESI
003E3216    EB 03           JMP SHORT 003E321B
...
003E321B    50              PUSH EAX
003E321C    891C24          MOV DWORD PTR SS:[ESP],EBX
003E321F    87E4            XCHG ESP,ESP
003E3221    E8 AAC6437B     CALL 7B81F8D0         ; __x86_get_pc_thunk_bx
003E3226    81C3 0E420800   ADD EBX,8420E
003E322C    3E:8B45 08      MOV EAX,DWORD PTR DS:[EBP+8]
003E3230    8D10            LEA EDX,[EAX]
003E3232    8DB3 005B1A00   LEA ESI,[EBX+1A5B00]
003E3238    B8 11000000     MOV EAX,11
003E323D    3E:8D3A         LEA EDI,DS:[EDX]
003E3240    3E:8D08         LEA ECX,DS:[EAX]
003E3243    F3:A5           REP MOVS DWORD PTR ES:[EDI],DWORD PTR DS:[ESI]
003E3245    5B              POP EBX
003E3246    8B3424          MOV ESI,DWORD PTR SS:[ESP]
003E3249    8D6424 04       LEA ESP,[ESP+4]
003E324D    8B3C24          MOV EDI,DWORD PTR SS:[ESP]
003E3250    8D6424 04       LEA ESP,[ESP+4]
003E3254    8B2C24          MOV EBP,DWORD PTR SS:[ESP]
003E3257    8D6424 04       LEA ESP,[ESP+4]
003E325B    C2 0400         RETN 4
...

__x86_get_pc_thunk_bx:

7B81F8D0    8B1C24          MOV EBX,DWORD PTR SS:[ESP]
7B81F8D3    C3              RETN
--- snip --- 

This of course can't work with Wine's PIC code.

'__x86_get_pc_thunk_bx' must be called from within the original code section
otherwise the PC relative offset will be always wrong.

I started placing wrapper functions in between to preserve the PIC semantics
(which works) but gave up after seeing that almost every API call is affected.

I don't think it's worth to waste more time with this unless someone writes a
code generator to wrap every entry point containing PIC code in automated way.

$ sha1sum Plus951b2426Full20141124.exe 
997a7411a0c7b8c1e0598142d1b3c3da9005147b  Plus951b2426Full20141124.exe

$ du -sh Plus951b2426Full20141124.exe 
182M    Plus951b2426Full20141124.exe

$ wine --version
wine-1.7.33-84-gfecbc88

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