https://bugs.winehq.org/show_bug.cgi?id=24374
Anastasius Focht focht@gmx.net changed:
What |Removed |Added ---------------------------------------------------------------------------- Keywords| |obfuscation Status|UNCONFIRMED |NEW CC| |focht@gmx.net Component|-unknown |kernel32 Summary|Driller fails to start |Driller crashes in process | |PE entry point due to | |Wine's mis-align workaround | |for 32-bit entry point asm | |wrapper (MoleBox Ultra | |v4.x) Ever confirmed|0 |1
--- Comment #7 from Anastasius Focht focht@gmx.net --- Hello folks,
confirming. The app is protected by 'MoleBox Ultra v4.x'
Wine implements a workaround for broken apps when setting up the stack for the process entry point (misaligns the stack). This harms the protection code because it expects specific values/layout on the process entry stack.
A trace log with +relay is not really useful here since it influences stack layout/values and the crash is at entry point anyway.
The protection code at PE entry point:
--- snip --- 10001004 6A 28 PUSH 28 10001006 68 70204000 PUSH 402070 1000100B E8 74020000 CALL Driller.10001284 ; see next chunk 10001010 33FF XOR EDI,EDI 10001012 57 PUSH EDI 10001013 FF15 00D02910 CALL DWORD PTR DS:[<&kernel32.GetModuleHandleA> 10001019 66:8138 4D5A CMP WORD PTR DS:[EAX],5A4D ... 10001284 68 D0124000 PUSH 4012D0 10001289 64:A1 00000000 MOV EAX,DWORD PTR FS:[0] 1000128F 50 PUSH EAX 10001290 8B4424 10 MOV EAX,DWORD PTR SS:[ESP+10] 10001294 896C24 10 MOV DWORD PTR SS:[ESP+10],EBP 10001298 8D6C24 10 LEA EBP,DWORD PTR SS:[ESP+10] 1000129C 2BE0 SUB ESP,EAX 1000129E 53 PUSH EBX 1000129F 56 PUSH ESI 100012A0 57 PUSH EDI 100012A1 8B45 F8 MOV EAX,DWORD PTR SS:[EBP-8] 100012A4 8965 E8 MOV DWORD PTR SS:[EBP-18],ESP 100012A7 50 PUSH EAX 100012A8 8B45 FC MOV EAX,DWORD PTR SS:[EBP-4] 100012AB C745 FC FFFFFFFF MOV DWORD PTR SS:[EBP-4],-1 100012B2 8945 F8 MOV DWORD PTR SS:[EBP-8],EAX 100012B5 8D45 F0 LEA EAX,DWORD PTR SS:[EBP-10] ; 0x0033FE10 100012B8 8B70 C8 MOV ESI,DWORD PTR DS:[EAX-38] 100012BB 8B40 20 MOV EAX,DWORD PTR DS:[EAX+20] ; [0x0033FE30] -> 0x23 100012BE 8D40 04 LEA EAX,DWORD PTR DS:[EAX+4] ; -> 0x27 100012C1 50 PUSH EAX 100012C2 8B76 05 MOV ESI,DWORD PTR DS:[ESI+5] 100012C5 FF16 CALL DWORD PTR DS:[ESI] ; kernel32.GetModuleHandleA --- snip ---
'kernel32.GetModuleHandleA(0x27)' -> *boom*
Callstack at PE entry point, annotated:
--- snip --- 0033FE24 7B8642D4 ; return from asm wrapper 'CALL DWORD PTR SS:[EBP+C]' 0033FE28 7FFDF000 ; PEB *peb 0033FE2C 7B8642CB ; mis-align workaround, offset to 'call_process_entry' 0033FE30 00000023 ; mis-align workaround, garbage ---> *problem* 0033FE34 00000302 ; mis-align workaround, garbage 0033FE38 0033FE98 ; saved EBP 0033FE3C 7B864421 ; return from KERNEL32.call_process_entry 0033FE40 7FFDF000 ; PEB *peb 0033FE44 10001004 ; LPTHREAD_START_ROUTINE entry --- snip ---
Source: http://source.winehq.org/git/wine.git/blob/fd6c5490dfe8818b1f9fa19e6502e22ae...
--- snip --- 1048 #ifdef __i386__ 1049 extern DWORD call_process_entry( PEB *peb, LPTHREAD_START_ROUTINE entry ); 1050 __ASM_GLOBAL_FUNC( call_process_entry, 1051 "pushl %ebp\n\t" 1052 __ASM_CFI(".cfi_adjust_cfa_offset 4\n\t") 1053 __ASM_CFI(".cfi_rel_offset %ebp,0\n\t") 1054 "movl %esp,%ebp\n\t" 1055 __ASM_CFI(".cfi_def_cfa_register %ebp\n\t") 1056 "subl $12,%esp\n\t" /* deliberately mis-align the stack by 8, Doom 3 needs this */ 1057 "pushl 8(%ebp)\n\t" 1058 "call *12(%ebp)\n\t" 1059 "leave\n\t" 1060 __ASM_CFI(".cfi_def_cfa %esp,4\n\t") 1061 __ASM_CFI(".cfi_same_value %ebp\n\t") 1062 "ret" ) 1063 #else 1064 static inline DWORD call_process_entry( PEB *peb, LPTHREAD_START_ROUTINE entry ) 1065 { 1066 return entry( peb ); 1067 } 1068 #endif --- snip ---
The mis-align workaround moves potentially garbage values into view from PE entry point perspective when it examines the caller stack.
The protection code ought to read 'call_process_entry' caller return address from stack, adding four(?) and passing this address as module name to 'kernel32.GetModuleHandleA' (see previous entry point disassembly).
This (garbage) module name is not really useful at all - but it has an important property: it points into mapped 'kernel32 .text' section (four bytes after 'call_process_entry' caller return address) - hence the "string" is readable. The API call is expected to fail (returning NULL).
If you really need to mis-align the stack in the 32-bit asm wrapper you need to put valid/mapped addresses as stack value(s) into misalignment area.
Protection scan:
--- snip --- -=[ ProtectionID v0.6.5.5 OCTOBER]=- (c) 2003-2013 CDKiLLER & TippeX Build 31/10/13-21:09:09 Ready... Scanning -> Z:\home\focht\Downloads\Driller.exe File Type : 32-Bit Exe (Subsystem : Win GUI / 2), Size : 23620456 (01686B68h) Byte(s) -> File has 22539112 (0157EB68h) bytes of appended data starting at offset 0108000h [File Heuristics] -> Flag : 00000000000000000000000000000100 (0x00000004) [Entrypoint Section Entropy] : 7.73 [!] MoleBox Ultra v4.x detected ! [i] relinked sections: yes - Scan Took : 0.639 Second(s) [00000027Fh tick(s)] [533 scan(s) done] --- snip ---
$ sha1sum install-driller.zip bd737b9bbd3c8fcb3000e532db987a505876af2a install-driller.zip
$ du -sh install-driller.zip 23M install-driller.zip
$ wine --version wine-1.7.23-90-gbdeb761
Regards