[Bug 13516] Dynamic HTML Editor 4.2 Demo installs, crashes on startup
wine-bugs at winehq.org
wine-bugs at winehq.org
Thu May 27 10:48:41 CDT 2010
http://bugs.winehq.org/show_bug.cgi?id=13516
Anastasius Focht <focht at gmx.net> changed:
What |Removed |Added
----------------------------------------------------------------------------
CC| |focht at gmx.net
--- Comment #10 from Anastasius Focht <focht at gmx.net> 2010-05-27 10:48:39 ---
Hello,
whenever I encounter vb6 apps I despise Microsoft ... I was tortured years ago,
forced to audit/review/reverse various vb apps :-|
That VB6 app in question is protected with tElock 0.981b.
After getting rid of this minor nuisance chances got better analysing/debugging
vb junk code ;-)
The bug in Wine is actually unearthed by some kind of unicode subclass
wrapper/framework for VB6 forms.
Basically junk^H^H^H^Hthunk code gets written and patched in dynamic memory at
runtime to provide subclassing/hooking facility.
I provide an annotated app code snippet to illustrate the idea how thunks get
written and to understand the Wine traces:
--- snip ---
...
mov edx, 004CB67Ch ; thunk opcode snippet string
"5589E583C4F85731C08945FC8945F8EB0EE8xxxxx01x83F802742185C07424E830000000837DF800750AE838000000E84D0000005F8B45FCC9C21000E826000000EBF168xxxxx02x6AFCFF7508E8xxxxx03xEBE031D24ABFxxxxx04xB9xxxxx05xE82D000000C3FF7514FF7510FF750CFF750868xxxxx06xE8xxxxx07x8945FCC331D2BFxxxxx08xB9xxxxx09xE801000000C3E32F09C978078B450CF2AF75248D4514508D4510508D450C508D4508508D45FC508D45F85052B8xxxxx0Ax508B00FF501CC3"
; "xxxx" will be patched later (jmp/call destinations)
...
call MSVBVM60.DLL.__vbaStrCopy
...
call [004010C4h] ; Len(arg)
mov edi, MSVBVM60.DLL.__vbaStrMove
...
opcode_bstr_loop:
cmp ebx, var_1C ; all opcodes copied?
jnle opcode_bstr_loop_end
...
push 004ADF0Ch ; "&H"
push ecx
push ebx
push edx
call [00401210h] ; Mid$(arg1, arg2, arg3)
mov edx, eax
lea ecx, var_28
call edi
push eax
call [00401118h] ; operator "&"
...
push eax
call [0040150Ch] ; Val(arg)
call MSVBVM60.DLL.__vbaFpUI1
push eax
call MSVBVM60.DLL.rtcBstrFromByte
...
call [00401118h] ; operator "&"
...
jmp opcode_bstr_loop
opcode_bstr_loop_end:
...
push eax
call [00401138h] ; LenB(arg)
mov edi, eax
push 00000040h
push 00003000h
push edi ; length of opcode snippet (thunk) in bytes
push 00000000h
mov [esi+50h], edi
VirtualAlloc(%x1, %x2, %x3, %x4)
mov var_58, eax
call MSVBVM60.DLL.__vbaSetSystemError
...
call [00401398h] ; VarPtr(arg)
push edi
mov edi, CopyMemory(%x1, %x2, %x3)
mov var_58, eax
push eax
mov eax, [esi+48h]
push eax
call edi ; copy BSTR thunk code snippet to final location
...
--- snip ---
With that annotated code snippet in mind we can now make a meaning of
corresponding Wine traces:
0xC3 (ret) is the last opcode (iteration) from that specific thunk snippet.
+tid,+seh,+relay,+ole,+variant
--- snip ---
0046:Call oleaut32.VarBstrCat(004adf0c L"&H",0016fcb4 L"C3",0032eb20)
ret=733867fd
...
0046:Call oleaut32.VarParseNumFromStr(0016f6ec
L"&HC3",00000409,80000000,0032eadc,0032eabc) ret=73373408
...
0046:Call oleaut32.VariantChangeType(0032eb0c,0032eb0c,00000000,00000005)
ret=733734a9
0046:trace:variant:VariantChangeTypeEx
(0x32eb0c->(VT_I4),0x32eb0c->(VT_I4),0x00000400,0x0000,VT_R8)
...
0046:Call oleaut32.SysAllocStringByteLen(0032eb24,00000001) ret=73380bf5
0046:Call ntdll.RtlAllocateHeap(00110000,00000000,00000007) ret=68b29e68
0046:Ret ntdll.RtlAllocateHeap() retval=0016f6e8 ret=68b29e68
0046:Ret oleaut32.SysAllocStringByteLen() retval=0016f6ec ret=73380bf5
0046:Call oleaut32.VarBstrCat(0016fce4 L"",0016f6ec L"\00c3",0032eb24)
ret=733867fd
0046:trace:variant:VarBstrCat L"",L"",0x32eb24
0046:Call ntdll.RtlAllocateHeap(00110000,00000000,00000006) ret=68b29f0b
0046:Ret ntdll.RtlAllocateHeap() retval=0016f700 ret=68b29f0b
0046:trace:variant:VarBstrCat L""
0046:Ret oleaut32.VarBstrCat() retval=00000000 ret=733867fd
0046:Call oleaut32.SysFreeString(0016fce4 L"") ret=733869b7
...
--- snip ---
After the binary opcode snippet is stuffed into a BSTR it should get written
out to memory...
Unfortunately the thunk code allocator is called with zero length:
--- snip ---
0046:Call KERNEL32.VirtualAlloc(00000000,00000000,00003000,00000040)
ret=00aa1b04
0046:Ret KERNEL32.VirtualAlloc() retval=00000000 ret=00aa1b04
0046:Call KERNEL32.GetLastError() ret=7336c0c7
0046:Ret KERNEL32.GetLastError() retval=00000057 ret=7336c0c7
0046:Call KERNEL32.TlsGetValue(00000005) ret=7336c0d5
0046:Ret KERNEL32.TlsGetValue() retval=0013d280 ret=7336c0d5
0046:Call ntdll.RtlMoveMemory(00000000,0016f704,00000000) ret=00aa1b2e
0046:Ret ntdll.RtlMoveMemory() retval=00000000 ret=00aa1b2e
--- snip ---
When the jmp/call destinations contained in that thunk are to be resolved, the
app crashes:
--- snip ---
...
0046:Call ntdll.RtlMoveMemory(0000004e,0032eb20,00000004) ret=00aa245a
0046:trace:seh:raise_exception code=c0000005 flags=0 addr=0x681f2043
ip=681f2043 tid=0046
0046:trace:seh:raise_exception info[0]=00000001
0046:trace:seh:raise_exception info[1]=0000004e
0046:trace:seh:raise_exception eax=ffcd152e ebx=7bc98440 ecx=00000001
edx=0032eb1c esi=0032eb20 edi=0000004e
0046:trace:seh:raise_exception ebp=0032ea68 esp=0032ea48 cs=0023 ds=002b
es=002b fs=0063 gs=006b flags=00010202
--- snip ---
dest ptr = 0x4e is the offset from the thunks block base address (base should
be 0x02220000 in this example but due to previous failure it returned NULL).
Thunk code to be patched:
--- snip ---
02220000 55 PUSH EBP
...
02220043 68 00000002 PUSH 2000000
02220048 6A FC PUSH -4
0222004A FF75 08 PUSH DWORD PTR SS:[EBP+8]
0222004D E8 00000003 CALL 05220052
...
--- snip ---
The final BSTR containing the opcodes is actually empty, so the previous
concatenations failed.
The culprit in Wine seems to be a misunderstanding what BSTR really are and the
relation to WCHAR*.
This app (mis)uses BSTRs to not only store/move unicode strings but to also
move binary data around (like thunk opcodes).
That means the BSTR _can_ actually contain an odd number of bytes - simple
case: the opcode loop which converts each opcode byte to 1-byte BSTR and
concats them into a binary (byte) array -> BSTR.
Unfortunately Wine code like oleaut32's VarBstrCat() deals with BSTRs as they
were true UNICODE strings.
--- snip dlls/oleaut32/vartype.c ---
HRESULT WINAPI VarBstrCat(BSTR pbstrLeft, BSTR pbstrRight, BSTR *pbstrOut)
{
unsigned int lenLeft, lenRight;
TRACE("%s,%s,%p\n",
debugstr_wn(pbstrLeft, SysStringLen(pbstrLeft)),
debugstr_wn(pbstrRight, SysStringLen(pbstrRight)), pbstrOut);
if (!pbstrOut)
return E_INVALIDARG;
lenLeft = pbstrLeft ? SysStringLen(pbstrLeft) : 0;
lenRight = pbstrRight ? SysStringLen(pbstrRight) : 0;
*pbstrOut = SysAllocStringLen(NULL, lenLeft + lenRight);
if (!*pbstrOut)
return E_OUTOFMEMORY;
(*pbstrOut)[0] = '\0';
if (pbstrLeft)
memcpy(*pbstrOut, pbstrLeft, lenLeft * sizeof(WCHAR));
if (pbstrRight)
memcpy(*pbstrOut + lenLeft, pbstrRight, lenRight * sizeof(WCHAR));
TRACE("%s\n", debugstr_wn(*pbstrOut, SysStringLen(*pbstrOut)));
return S_OK;
}
--- snip dlls/oleaut32/vartype.c ---
That means incorrect behaviour if for example "ansi" BSTRs with odd length are
passed (SysStringLen() determines the length in wide-characters).
Make sure the test suite contains such cases and passes to not break other
stuff ;-)
Regards
--
Configure bugmail: http://bugs.winehq.org/userprefs.cgi?tab=email
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