[Bug 43656] 64-bit World of Warcraft client reports ' Game Initialization Failed!' or crashes on startup with stack overflow due to improper mapping of exception code

wine-bugs at winehq.org wine-bugs at winehq.org
Sat Mar 3 10:49:56 CST 2018


https://bugs.winehq.org/show_bug.cgi?id=43656

Anastasius Focht <focht at gmx.net> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |focht at gmx.net
          Component|-unknown                    |ntdll
     Ever confirmed|0                           |1
                URL|                            |https://eu.battle.net/accou
                   |                            |nt/download/
           Keywords|                            |download, obfuscation
             Status|UNCONFIRMED                 |NEW
            Summary|World of Warcraft crash on  |64-bit World of Warcraft
                   |startup with stack overflow |client reports 'Game
                   |                            |Initialization Failed!' or
                   |                            |crashes on startup with
                   |                            |stack overflow due to
                   |                            |improper mapping of
                   |                            |exception code

--- Comment #13 from Anastasius Focht <focht at gmx.net> ---
Hello folks,

confirming.

Relevant part of trace log:

--- snip ---
$ pwd
/home/focht/wine-games/wineprefix64-bnet/drive_c/Program Files (x86)/World of
Warcraft

$ WINEDEBUG=+seh,+relay,+ntdll wine ./Wow-64.exe >>log2.txt 2>&1
...
002a:Call TLS callback
(proc=0x1400039c0,module=0x140000000,reason=PROCESS_ATTACH,reserved=0)
002a:Call KERNEL32.VirtualProtect(14129b430,00000110,00000004,0023e468,)
ret=140004f3e
002a:Ret  KERNEL32.VirtualProtect() retval=00000001 ret=140004f3e
002a:Call KERNEL32.VirtualProtect(14129b430,00000110,00000002,0023e480,)
ret=1400051da
002a:Ret  KERNEL32.VirtualProtect() retval=00000001 ret=1400051da
002a:Ret  TLS callback
(proc=0x140373710,module=0x140000000,reason=PROCESS_ATTACH,reserved=0)
002a:Call TLS callback
(proc=0x14000e530,module=0x140000000,reason=PROCESS_ATTACH,reserved=0)
002a:Call ntdll.RtlAddVectoredExceptionHandler(00000001,14002f870,)
ret=14000c52b
002a:Ret  ntdll.RtlAddVectoredExceptionHandler() retval=000419c0 ret=14000c52b
002a:trace:seh:NtRaiseException code=c0000005 flags=0 addr=0x14000c5df
ip=14000c5df tid=002a
002a:trace:seh:NtRaiseException  rax=0000000000000055 rbx=0000000000000000
rcx=000000007bdb321f rdx=000000007bdb31d0
002a:trace:seh:NtRaiseException  rsi=000000007bd97758 rdi=0000000000003a68
rbp=000000000023dd70 rsp=000000000023dd20
002a:trace:seh:NtRaiseException   r8=0000000000000009  r9=000000014000c52b
r10=0000000000000000 r11=0000000000000246
002a:trace:seh:NtRaiseException  r12=00000000fd25be65 r13=0000000000000000
r14=000000007bd95170 r15=000000007bd98a4c
002a:trace:seh:call_vectored_handlers calling handler at 0x14002f870
code=c0000005 flags=0
002a:trace:seh:call_vectored_handlers handler at 0x14002f870 returned 0
002a:trace:seh:RtlVirtualUnwind type 1 rip 14000c5df rsp 23dd20
002a:trace:seh:dump_unwind_info **** func c030-e52d
002a:trace:seh:dump_unwind_info unwind info at 0x14150e9bc flags 0 prolog 0xf7
bytes function 0x14000c030-0x14000e52d
002a:trace:seh:dump_unwind_info     0xf7: movq %r15,0x28(%rsp)
002a:trace:seh:dump_unwind_info     0xec: movq %r14,0x30(%rsp)
002a:trace:seh:dump_unwind_info     0xe7: movq %rdi,0x38(%rsp)
002a:trace:seh:dump_unwind_info     0xde: movq %rsi,0x40(%rsp)
002a:trace:seh:dump_unwind_info     0xd9: movq %rbx,0x48(%rsp)
002a:trace:seh:dump_unwind_info     0x16: subq $0x50,%rsp
002a:trace:seh:dump_unwind_info     0xf: pushq %r13
002a:trace:seh:dump_unwind_info     0xd: pushq %r12
002a:trace:seh:dump_unwind_info     0xb: pushq %rbp
002a:trace:seh:RtlVirtualUnwind type 1 rip 14000f2cb rsp 23dd90
002a:trace:seh:dump_unwind_info **** func e5a0-1562d
002a:trace:seh:dump_unwind_info unwind info at 0x14150e9f4 flags 0 prolog 0x30
bytes function 0x14000e5a0-0x14001562d
...
002a:trace:seh:call_stack_handlers found wine frame 0x23e630 rsp 23e790 handler
0x7bd4a517
002a:trace:seh:call_teb_handler calling TEB handler 0x7bd4a517 (rec=0x23dbe0,
frame=0x23e630 context=0x23ce90, dispatch=0x23d360) 
...
002a:trace:seh:RtlRestoreContext returning to 7bd4a290 stack 23e620
002a:exception in TLS callback
(proc=0x14129b438,module=0x140000000,reason=PROCESS_ATTACH,reserved=0)
002a:Starting process L"C:\\Program Files (x86)\\World of Warcraft\\Wow-64.exe"
(entryproc=0x1400b4f50)
002a:trace:ntdll:NtQueryInformationProcess
(0xffffffffffffffff,0x00000007,0x23fda8,0x00000008,(nil))
002a: get_process_info( handle=ffffffff )
002a: get_process_info() = 0 { pid=0029, ppid=0000, affinity=000000ff,
peb=7fffffeaf000, start_time=1d3b2efbed2f538 (-0.0964970), end_time=0,
exit_code=259, priority=2, cpu=x86_64, debugger_present=0, debug_children=1 }
002a:Call user32.MessageBoxW(00000000,0023fd10 L"Game Initialization
Failed!",0023fd00 L"ERROR",00000010,) ret=1400b55ec 
...
--- snip ---

The actual problem is not visible. One has to debug the code in the TLS
callbacks which is another problem as 'winedbg' can't do this (unless one hacks
Wine).

This is were 'x64dbg' (https://x64dbg.com/) comes handy which allows to stop in
TLS callbacks before the entry point is called. Unfortunately it's also ridden
with a number of Wine bugs that have to be worked around to be somewhat usable.

During execution of the second TLS callback, a vectored exception handler is
installed which ought to handle privileged instructions and set trap flag to
cause single step events.

--- snip ---
...
000000014000C511  48 05 89 .. add    rax, FFFFFFFFFFFFF989
000000014000C517  48 89 45 .. mov    qword ptr ss:[rbp+30], rax
000000014000C51B  48 8B 05 .. mov    rax, qword ptr ds:[141813C50]
000000014000C522  48 8B 55 .. mov    rdx, qword ptr ss:[rbp+30]
000000014000C526  49 33 C1    xor    rax, r9
000000014000C529  FF D0       call   rax ; ntdll.RtlAddVectoredExceptionHandler
000000014000C52B  48 89 05 .. mov    qword ptr ds:[1418D6C00], rax
000000014000C532  48 85 C0    test   rax, rax
000000014000C535  0F 84 CD .. je     wow-64.14000E508
000000014000C53B  48 89 5D .. mov    qword ptr ss:[rbp+30], rbx
...
000000014000C5D7  0F B6 45 .. movzx  eax, byte ptr ss:[rbp+30]
000000014000C5DB  84 C0       test   al, al
000000014000C5DD  74 B4       je     wow-64.14000C593
000000014000C5DF  F4          hlt  ; <---- EXCEPTION_PRIV_INSTRUCTION
000000014000C5E0  4C 8B 5D .. mov    r11, qword ptr ss:[rbp+20]
...
--- snip ---

Unfortunately Wine's exception handling maps the 'hlt' instruction to
EXCEPTION_ACCESS_VIOLATION which leads to a different code path in vectored
handler which later leads to things going haywire.

It seems there was a typo introduced by:

https://source.winehq.org/git/wine.git/commitdiff/e1d68b2e169580be8dc6f8927e01a19c60f79d65
("ntdll: Implement handling of int $0x2d for x86_64.")

https://source.winehq.org/git/wine.git/blob/39c8875ff8aa543eaa50e52db0c546717de691af:/dlls/ntdll/signal_x86_64.c#l2750

--- snip ---
2750 static void segv_handler( int signal, siginfo_t *siginfo, void *sigcontext
)
2751 {
2752     EXCEPTION_RECORD *rec;
2753     ucontext_t *ucontext = sigcontext;
...
2770     rec = setup_exception( sigcontext, raise_segv_exception );
2771     if (rec->ExceptionCode == EXCEPTION_STACK_OVERFLOW) return;
2772 
2773     switch(TRAP_sig(ucontext))
2774     {
...
2789     case TRAP_x86_UNKNOWN:   /* Unknown fault code */
2790         {
2791             CONTEXT *win_context = get_exception_context( rec );
2792             WORD err = ERROR_sig(ucontext);
2793             if ((err & 7) == 2 && handle_interrupt( err >> 3, rec,
win_context )) break;
2794             rec->ExceptionCode = err ? EXCEPTION_ACCESS_VIOLATION :
EXCEPTION_PRIV_INSTRUCTION;
2795             rec->ExceptionCode = EXCEPTION_ACCESS_VIOLATION;
2796         }
2797         break;
--- snip ---

Line 2795 has to be removed.

Fixing this will likely fix a number of apps and games that depend on proper
privileged instruction handling (part of DRM schemes -> decrypt, anti-debugging
etc.).

NOTE: With this fix applied the entry point is successfully reached and the
client runs further but ends up in other bugs I've already documented for
Diablo III (bug 44585 , bug 44616 , bug 44617)

$ wine --version
wine-3.3

Regards

-- 
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