http://bugs.winehq.org/show_bug.cgi?id=26701
Summary: exeinfoPE crashes due to PE resource section validation being too strict Product: Wine Version: 1.3.17 Platform: x86 OS/Version: Linux Status: NEW Severity: normal Priority: P2 Component: ntdll AssignedTo: wine-bugs@winehq.org ReportedBy: focht@gmx.net
Hello,
while updating some appdb entries I noticed a breakage with some PE "id" tool.
The app worked some time ago but now crashes instantly. There was a minor version update: the author probably not only added more signatures but tweaked the custom PE protection the app is wrapped with.
--- snip ---
$ wine ./exeinfoPE.exe
wine: Unhandled exception 0x0eedfade at address 0x7b83983a:0x7b83863f (thread 0009), starting debugger... fixme:dbghelp_dwarf:dwarf2_lookup_type Unable to load forward reference for tag 26 fixme:dbghelp_dwarf:dwarf2_lookup_type Unable to load forward reference for tag 26 fixme:dbghelp_dwarf:dwarf2_lookup_type Unable to load forward reference for tag 26 err:seh:setup_exception_record stack overflow 880 bytes in thread 0009 eip 6816b5ea esp 00230fc0 stack 0x230000-0x231000-0x330000 --- snip ---
relay trace yields following:
--- snip --- ... 0021:Call KERNEL32.FindResourceA(00400000,00472384 "tbl_Main",0000000a) ret=00474417 0021:trace:resource:FindResourceExA 0x400000 #000a "tbl_Main" 0000 0021:trace:resource:LdrFindResource_U module 0x400000 type #000a name L"TBL_MAIN" lang 0000 level 3 0021:Ret KERNEL32.FindResourceA() retval=00000000 ret=00474417 0021:Call user32.LoadStringA(00400000,0000ffc3,0032ed34,00001000) ret=00407417 0021:trace:resource:LoadStringA instance = 0x400000, id = ffc3, buffer = 0x32ed34, length = 4096 0021:trace:resource:FindResourceExW 0x400000 #0006 #0ffd 0000 0021:trace:resource:LdrFindResource_U module 0x400000 type #0006 name #0ffd lang 0000 level 3 0021:trace:resource:LoadStringA returning "" 0021:Ret user32.LoadStringA() retval=00000000 ret=00407417 0021:Call KERNEL32.RaiseException(0eedfade,00000001,00000007,0032fd7c) ret=0047444b 0021:trace:seh:raise_exception code=eedfade flags=1 addr=0x7b83863f ip=7b83863f tid=0021 0021:trace:seh:raise_exception info[0]=0047444b 0021:trace:seh:raise_exception info[1]=05701d10 0021:trace:seh:raise_exception info[2]=0053a9e0 0021:trace:seh:raise_exception info[3]=00000000 0021:trace:seh:raise_exception info[4]=00000029 0021:trace:seh:raise_exception info[5]=0032fde8 0021:trace:seh:raise_exception info[6]=0032fd98 0021:trace:seh:raise_exception eax=7b825a75 ebx=7b88fff4 ecx=0047444b edx=0032fc94 esi=0032fd7c edi=0032fcf0 0021:trace:seh:raise_exception ebp=0032fcd8 esp=0032fc74 cs=0073 ds=007b es=007b fs=0033 gs=003b flags=00000203 0021:trace:seh:call_vectored_handlers calling handler at 0x788636c6 code=eedfade flags=1 0021:trace:seh:call_vectored_handlers handler at 0x788636c6 returned 0 0021:trace:seh:call_stack_handlers calling handler at 0x474573 code=eedfade flags=1 0021:trace:seh:call_stack_handlers handler at 0x474573 returned 1 0021:trace:seh:call_stack_handlers calling handler at 0x405149 code=eedfade flags=1 ... --- snip ---
The app unpacks/decrypts PE sections into dynamic memory and patches the PE header to point to new locations.
I dumped the PE header at the right place ;-)
--- snip --- Wine-dbg>p *nt {Signature=0x4550, FileHeader={Machine=0x14c, NumberOfSections=0x3, TimeDateStamp=0x2a425e19, PointerToSymbolTable=0, NumberOfSymbols=0, SizeOfOptionalHeader=0xe0, Characteristics=0x818f}, OptionalHeader={Magic=0x10b, MajorLinkerVersion=2, MinorLinkerVersion=0, SizeOfCode=0x8c000, SizeOfInitializedData=0x5000, SizeOfUninitializedData=0x513a000, AddressOfEntryPoint=0x51c5810, BaseOfCode=0x513b000, BaseOfData=0x51c7000, ImageBase=0x400000, SectionAlignment=0x1000, FileAlignment=0x200, MajorOperatingSystemVersion=0x4, MinorOperatingSystemVersion=0, MajorImageVersion=0, MinorImageVersion=0, MajorSubsystemVersion=0x4, MinorSubsystemVersion=0, Win32VersionValue=0, SizeOfImage=0x51cc000, SizeOfHeaders=0x1000, CheckSum=0x51c5810, Subsystem=0x2, DllCharacteristics=0, SizeOfStackReserve=0x100000, SizeOfStackCommit=0x4000, SizeOfHeapReserve=0x100000, SizeOfHeapCommit=0x1000, LoaderFlags=0, NumberOfRvaAndSizes=0x12, DataDirectory={{VirtualAddress=0x5159000, Size=0x4f}, {VirtualAddress=0x51cb120, Size=0x2c8}, {VirtualAddress=0x51c7000, Size=0}, {VirtualAddress=0, Size=0}, {VirtualAddress=0, Size=0}, {VirtualAddress=0, Size=0}, {VirtualAddress=0, Size=0}, {VirtualAddress=0, Size=0}, {VirtualAddress=0, Size=0}, {VirtualAddress=0x51c63b0, Size=0x18}, {VirtualAddress=0, Size=0}, {VirtualAddress=0, Size=0}, {VirtualAddress=0, Size=0}, {VirtualAddress=0, Size=0}, {VirtualAddress=0, Size=0}, {VirtualAddress=0, Size=0}}}} --- snip ---
The (new) PE resource section is located at 0x051c7000 with size == 0 (not recalculated to real value) Wine's resource directory entry size check is actually the problem, preventing the app from finding its resources.
--- snip ntdll/resource.c --- /********************************************************************** * find_entry * * Find a resource entry */ static NTSTATUS find_entry( HMODULE hmod, const LDR_RESOURCE_INFO *info, ULONG level, const void **ret, int want_dir ) { ULONG size; const void *root; const IMAGE_RESOURCE_DIRECTORY *resdirptr; WORD list[9]; /* list of languages to try */ int i, pos = 0;
root = RtlImageDirectoryEntryToData( hmod, TRUE, IMAGE_DIRECTORY_ENTRY_RESOURCE, &size ); if (!root) return STATUS_RESOURCE_DATA_NOT_FOUND; if (size < sizeof(*resdirptr)) return STATUS_RESOURCE_DATA_NOT_FOUND; resdirptr = root; ...
--- snip ntdll/resource.c ---
This also results in stack overflow because the app's exception handler tries to load resources too which obviously fails.
Removing the size check (size < sizeof(*resdirptr)) lets the app successfully start.
Regards