http://bugs.winehq.org/show_bug.cgi?id=6893
Anastasius Focht focht@gmx.net changed:
What |Removed |Added ---------------------------------------------------------------------------- CC| |focht@gmx.net
--- Comment #8 from Anastasius Focht focht@gmx.net 2010-08-21 17:14:17 --- Hello,
this 16-bit garbage is nasty to look at .. do we really need this? ;-)
It seems the corruption happens much earlier. The files under "c:\CBLIGHT\MESSAGES[locale]" are key-value like (message) text files. Even the german "c:\CBLIGHT\MESSAGES\DEUTSCH\texts.msg" which is unpacked earlier is corrupted (you can tell by looking at the end). Interestingly it's not detected as CRC failure unlike the english one.
The files are stored as embedded "resources" in the 16 bit .exe file. Seek to resource "header" offset:
--- snip --- 001c:Call KERNEL32.CreateFileW(0094d318 L"z:\home\focht\down~ntg\cblight.exe",80000000,00000001,00000000,00000003,00000000,00000000) ret=68554575 ... 001c:Ret KERNEL32.CreateFileW() retval=00000090 ret=68554575 ... 001c:Call KERNEL32.SetFilePointer(00000090,00233d7a,00000000,00000000) ret=68558499 001c:Ret KERNEL32.SetFilePointer() retval=00233d7a ret=68558499 ... --- snip ---
The compressed resources come with a block header:
--- snip --- Offset 0 1 2 3 4 5 6 7 8 9 A B C D E F Ascii
00233D70 42 4C 43 4B 00 02 BLCK. 00233D80 47 00 21 00 00 00 20 0B 00 00 1A 6D 65 73 73 61 G.!......messa 00233D90 67 65 73 5C 65 6E 67 6C 69 73 68 5C 74 65 78 74 ges\english\text 00233DA0 73 2E 6D 73 67 52 1F 00 00 20 0B 00 00 20 00 00 s.msgR........ 00233DB0 00 54 57 3D 24 00 00 00 00 00 00 00 00 9A 5B F3 .TW=$........š[ó --- snip ---
being read in:
--- snip --- 001c:Call KERNEL32.ReadFile(00000090,004028fc,00000010,0094da40,00000000) ret=685586dc 001c:Ret KERNEL32.ReadFile() retval=00000001 ret=685586dc ... 001c:Call KERNEL32.ReadFile(00000090,0040256f,00000001,0094da40,00000000) ret=685586dc 001c:Ret KERNEL32.ReadFile() retval=00000001 ret=685586dc ... 001c:Call KERNEL32.ReadFile(00000090,0040290c,0000001a,0094da40,00000000) ret=685586dc 001c:Ret KERNEL32.ReadFile() retval=00000001 ret=685586dc ... 001c:Call KERNEL32.ReadFile(00000090,00402a0c,0000001c,0094da40,00000000) ret=685586dc 001c:Ret KERNEL32.ReadFile() retval=00000001 ret=685586dc ... 001c:Call USER.92: SETDLGITEMTEXT(005c,0064,126f:18c6 "Processing...") ret=1257:1595 ds=126f ... 001c:Call USER.92: SETDLGITEMTEXT(005c,0082,126f:d964 "c:\cblight\messages\english\texts.msg") ret=1257:161d ds=126f ... --- snip ---
The output is created empty:
--- snip --- 001c:Call KERNEL32.CreateFileW(0094d318 L"c:\cblight\messages\english\texts.msg",c0000000,00000003,00000000,00000002,00000000,00000000) ret=68554575 ... 001c:Ret KERNEL32.CreateFileW() retval=00000094 ret=68554575 ... 001c:Call USER.92: SETDLGITEMTEXT(005c,0064,126f:18c6 "Extracting...") ret=1257:1595 ds=126f ... --- snip ----
compressed chunk read (0xb20 bytes taken from header info):
--- snip --- 001c:Call KERNEL32.ReadFile(00000090,009fd2e0,00000b20,0094da40,00000000) ret=685586dc 001c:Ret KERNEL32.ReadFile() retval=00000001 ret=685586dc ... --- snip ---
In between message (gui) processing there are notable exceptions:
--- snip --- 001c:trace:seh:raise_exception code=c0000005 flags=0 addr=0x3f4f ip=00003f4f tid=001c 001c:trace:seh:raise_exception info[0]=00000000 001c:trace:seh:raise_exception info[1]=ffffffff 001c:trace:seh:raise_exception eax=00000000 ebx=00710000 ecx=00000b20 edx=00001317 esi=00000b20 edi=0000d6e2 001c:trace:seh:raise_exception ebp=0000d6be esp=0000d6ba cs=1257 ds=126f es=126f fs=0063 gs=006b flags=00010246 ... 001c:trace:seh:raise_exception code=c0000005 flags=0 addr=0x3f58 ip=00003f58 tid=001c ... 001c:trace:seh:raise_exception code=c0000005 flags=0 addr=0x3f96 ip=00003f96 tid=001c ... 001c:trace:seh:raise_exception code=c0000005 flags=0 addr=0x3f9b ip=00003f9b tid=001c ... 001c:trace:seh:raise_exception code=c0000005 flags=0 addr=0x3fa5 ip=00003fa5 tid=001c ... 001c:trace:seh:raise_exception code=c0000005 flags=0 addr=0x3faa ip=00003faa tid=001c ... --- snip ---
They are caused by privileged "cli" and "sti" instructions. Disassembling around that place it looks like the 16 bit code switches stacks before and after leaving some kind of unpacking routine (even within unpacking there are stack switches).
--- snip --- seg16:3F4B mov alt_bp_save_word_13FFA, bp seg16:3F4F cli seg16:3F50 mov alt_ss_save_word_13FFC, ss seg16:3F54 mov alt_sp_save_word_13FFE, sp seg16:3F58 sti --- snip ---
New stack: some reserved space in data segment
--- snip --- seg16:3F86 mov ax, ds seg16:3F88 xor dx, dx seg16:3F8A add dx, 1D58h seg16:3F8E add dx, 200h seg16:3F92 mov bx, ss seg16:3F94 mov cx, sp seg16:3F96 cli seg16:3F97 mov ss, ax seg16:3F99 mov sp, dx seg16:3F9B sti ... <unpack routine> (also stack switches in between) ... <switch stack back> --- snip ---
Now the uncompressed chunk (8018 bytes) as is written:
(this is also described in xxxxxxxx.TMP/setup.stx file)
--- snip --- messages\english\texts.msg="texts.msg" 8018 A 0 C A --- snip ---
--- snip --- 001c:Call KERNEL.102: DOS3CALL() ret=1257:6c8c ds=1317 AX=4052 BX=0007 CX=1f52 DX=0000 SI=0b20 DI=0000 ES=1317 EFL=00000246 001c:Call KERNEL32._hwrite(00000094,009ff2f0,00001f52) ret=685585fc 001c:Ret KERNEL32._hwrite() retval=00001f52 ret=685585fc 001c:Ret KERNEL.102: DOS3CALL() retval=none ret=1257:6c8c ds=1317 AX=1f52 BX=0007 CX=1f52 DX=0000 SI=0b20 DI=0000 ES=1317 EFL=00000246
001c:Call USER.92: SETDLGITEMTEXT(005c,0064,126f:18c6 "Processing...") ret=1257:1595 ds=126f ... --- snip ---
The corruption is detected:
--- snip --- ... 001c:Call KERNEL32.CloseHandle(00000094) ret=685472ef 001c:Ret KERNEL32.CloseHandle() retval=00000001 ret=685472ef ... 001c:Call KERNEL32.DeleteFileW(0094d838 L"c:\cblight\messages\english\texts.msg") ret=68558556 ... 001c:Ret KERNEL32.DeleteFileW() retval=00000001 ret=68558556 ... 001c:Call user32.MessageBoxA(0004005c,004027cc "Unable to copy file "messages\english\texts.msg".\n\nIncorrect file checksum.",00407498 "ChessBase Light",00000030) ret=448565f2 --- snip ---
I placed a breakpoint in _hwrite() and dumped the buffer - it seems the plain text is already corrupted at this point. So it seems to happen while unpacking the memory chunk... unfortunately there aren't any visible 16/32-bit Windows API calls at this place. That 16 bit unpacking code works on internal storage so neither +heap nor valgrind can detect internal memory overwrites, if any.
The stack switching shouldn't be a problem - as long as no other 16 bit code from other threads accesses areas where the unpacker switched its stack on (same ds segment). There is only one other thread present which pulls in when this thread triggers message processing:
--- snip --- 001c:Call USER.109: PEEKMESSAGE(126f:d530,0000,0000,0000,0001) ret=1257:7de0 ds=126f 001c:Call user32.PeekMessageA(0094dd30,00000000,00000000,00000000,00000001) ret=448482eb ... 001c:Call krnl386.exe16.ReleaseThunkLock(0094db9c) ret=4484387e 001c:Ret krnl386.exe16.ReleaseThunkLock() retval=00000000 ret=4484387e 0019:Ret krnl386.exe16.RestoreThunkLock() retval=685a8838 ret=448438b6 001c:Call krnl386.exe16.RestoreThunkLock(00000003) ret=448438b6 0019:Ret user32.PeekMessageA() retval=00000000 ret=448482eb ... 0019:Ret USER.109: PEEKMESSAGE() retval=00000000 ret=11e7:1d1a ds=11f7 ... 0019:Call USER.109: PEEKMESSAGE(11f7:b178,0000,0000,0000,0001) ret=11e7:1d1a ds=11f7 0019:Call user32.PeekMessageA(0080e430,00000000,00000000,00000000,00000001) ret=448482eb ... 0019:Call krnl386.exe16.ReleaseThunkLock(0080e29c) ret=4484387e 0019:Ret krnl386.exe16.ReleaseThunkLock() retval=00000000 ret=4484387e 001c:Ret krnl386.exe16.RestoreThunkLock() retval=685a8838 ret=448438b6 001c:Ret user32.PeekMessageA() retval=00000000 ret=448482eb 0019:Call krnl386.exe16.RestoreThunkLock(00000002) ret=448438b6 001c:Ret USER.109: PEEKMESSAGE() retval=00000000 ret=1257:7de0 ds=126f 001c:Call USER.124: UPDATEWINDOW(005c) ret=1257:1655 ds=126f 001c:Call user32.RedrawWindow(0004005c,00000000,00000000,00000180) ret=44853ec2 001c:Ret user32.RedrawWindow() retval=00000001 ret=44853ec2 001c:Ret USER.124: UPDATEWINDOW() retval=00000001 ret=1257:1655 ds=126f ... --- snip ---
It might be worthwile to check if the internal memory buffer gets corrupted in between leaving the unpacking code and _hwrite() call.
Continued ...
Regards