http://bugs.winehq.org/show_bug.cgi?id=8306
------- Additional Comments From focht@gmx.net 2007-07-05 16:45 ------- Hello,
although this bug has already been marked as duplicate i post my analysis here, because it did it on *this* target. It possibly applies to several other bug reports. Go and figure.
--- snip --- fixme:seh:set_cpu_context setting partial context (13) not supported --- snip ---
To get around first blocker you need to work around missing partial context support in wine. As i did for other bugs, i modified as follows:
--- snip dlls/ntdll/signal_i386.c ---
set_cpu_context()
... if (flags & CONTEXT_FULL) { /* if ((flags & CONTEXT_FULL) != (CONTEXT_FULL & ~CONTEXT_i386)) FIXME( "setting partial context (%x) not supported\n", flags ); else */ __wine_call_from_32_restore_regs( context ); } --- snip dlls/ntdll/signal_i386.c ---
Ignoring the partial flags 0x13: CONTEXT86_CONTROL | CONTEXT86_INTEGER | CONTEXT86_DEBUG and calling __wine_call_from_32_restore_regs().
Restoring the missing CONTEXT86_SEGMENTS seem to have no negative effect for all bug reports of same category i tested so far.
Now the interesting one. The app crashes due to unhandled access violation (previous exceptions are anti-debugging related).
--- snip --- 0009:trace:seh:raise_exception code=c0000005 flags=0 addr=0x4e9f16 0009:trace:seh:raise_exception info[0]=00000000 0009:trace:seh:raise_exception info[1]=0000003c 0009:trace:seh:raise_exception eax=7bc951ec ebx=00000000 ecx=0001d920 edx=1f010607 esi=0059a20e edi=7ffdf000 0009:trace:seh:raise_exception ebp=0034fe98 esp=0034fe84 cs=0073 ds=007b es=007b fs=0033 gs=003b flags=00210213 0009:trace:seh:call_stack_handlers calling handler at 0x7b82bf70 code=c0000005 flags=0 --- snip ---
The code that leads to this (after decryption):
--- snip --- drb7gcm1:004CE716 mov eax, large fs:30h drb7gcm1:004CE71D mov eax, [eax+0Ch] drb7gcm1:004CE720 mov eax, [eax+0Ch] ... drb7gcm1:004E9F13 mov ebx, [eax+18h] drb7gcm1:004E9F16 mov ecx, [ebx+3Ch] drb7gcm1:004E9F19 mov ecx, [ebx+ecx+78h] drb7gcm1:004E9F1D or ecx, ecx ... --- snip ---
Well, this app walks the OS loader structures. Roughly translated:
head = &NtCurrentTeb()->Peb->LdrData->InLoadOrderModuleList; for (entry = head->Flink; entry != head; entry = entry->Flink) { LDR_MODULE *mod = CONTAINING_RECORD(entry, LDR_MODULE, InLoadOrderModuleList); export_table_ptr = mod->DllBase + PE_header_offset + export_table_offset; // verify export directory ... }
This works - usually :-)
While walking the loader module list and processing module entries, this application checks for internal IMAGE_EXPORT_DIRECTORY module name (not filename!). Bascially it xor's the first 2 dwords of module name and compares it to some constant. The constant is designed to match "kernel32" part of "KERNEL32.dll" module name.
Due to the way, fake wine dlls (placeholders) are designed, no match is encountered while walking the whole list. Due to a bug in this protector, it walks past entry, dereferences the list flink directly (as entry) and crashes. This never happens on windows, because kernel32.dll has a valid export directory and module name entry there.
As long as kernel32 placeholder doesnt have fake export directory, applications/software protections which do this stuff remain broken on wine.
Regards