[Bug 34623] New: NCsoft's Aion (MMORPG) crashes on startup (WinLicense software protection, avoid forwarding some msvcr80 API to msvcrt)

wine-bugs at winehq.org wine-bugs at winehq.org
Sun Sep 29 10:55:24 CDT 2013


http://bugs.winehq.org/show_bug.cgi?id=34623

             Bug #: 34623
           Summary: NCsoft's Aion (MMORPG) crashes on startup (WinLicense
                    software protection, avoid forwarding some msvcr80 API
                    to msvcrt)
           Product: Wine
           Version: 1.7.3
          Platform: x86
        OS/Version: Linux
            Status: NEW
          Severity: normal
          Priority: P2
         Component: msvcrt
        AssignedTo: wine-bugs at winehq.org
        ReportedBy: focht at gmx.net
    Classification: Unclassified


Hello folks,

continuation of bug 34470
We're still 'purist' here, no winetricks (VC++ runtimes).

With msvcp80 fordwards fixed, the dll entry points from crysystem.dll and
friends are successfully passed (no more exceptions with loader lock held).

Crashes at this point now invoke the registered crash handler/debugger which is
obviously more helpful ;-)

Besides Winedbg, AION's own crash tool "SendLogClient.exe" gives a bit of
information:

--- snip ---
...
Registers:
EAX=0343e13c CS=0023 EIP=f348e160 EFLGS=00010246
EBX=5653ffd8 SS=002b ESP=0032c63c EBP=0032c6a0
ECX=0349a9c0 DS=002b ESI=564dff90 FS=0063
EDX=032fe560 ES=002b EDI=0349a9c0 GS=006b
Bytes at CS:EIP:
6d 73 76 63 72 74 2e 3f 3f 39 74 79 70 65 5f 69 
Stack dump:
0032C63C: 032FE5AD 0349A9C0 03455245 0343E13D 564DFF90 00000000 00000000
00000000
0032C65C: 00000000 00000000 00000000 00000000 00000000 00000000 00000000
00000000
0032C67C: 00000000 00000000 00000000 00000000 F73EE680 00000000 00000000
00000000
...
Call Stack Information
F348E160  0032C6A0  0002:00008160 C:\windows\system32\msvcr80.dll
Params: 0343E13C 0349A9C0 5653FFD8 5649FE00
[msvcr80.dll] Bytes at CS:EIP: 6d 73 76 63 72 74 2e 3f 3f 39 74 79 70 65 5f 69 

0338A3F1  0032C710  0001:000B93F1 C:\Program
Files\NCSOFT\Aion\bin32\CrySystem.dll
Params: 0343E13C 0349A9C0 5653FFD8 5653FFC0
[CrySystem.dll] Bytes at CS:EIP: 5f b0 01 5e 88 43 09 5b 8b e5 5d c2 0c 00 5f
5e 
...
--- snip ---

The protection actually detects certain debuggers when being attached at
runtime/crash time and kills them off through watcher threads.

Using tools like Imprec and LordPE one can dissemble/dump from process address
space without attaching to the actual process (non-invasive method).

Using last good return address -> 0x0338A3F1 (CrySystem.dll):

--- snip ---
0338A3DC  8B45 10                   mov eax,[ebp+10]
0338A3DF  8B4D 0C                   mov ecx,[ebp+C]
0338A3E2  8B13                      mov edx,[ebx]
0338A3E4  8B52 04                   mov edx,[edx+4]
0338A3E7  50                        push eax
0338A3E8  8B45 08                   mov eax,[ebp+8]
0338A3EB  51                        push ecx
0338A3EC  50                        push eax
0338A3ED  8BCB                      mov ecx,ebx
0338A3EF  FFD2                      call edx
0338A3F1  5F                        pop edi
0338A3F2  B0 01                     mov al,1
0338A3F4  5E                        pop esi
0338A3F5  8843 09                   mov [ebx+9],al
0338A3F8  5B                        pop ebx
0338A3F9  8BE5                      mov esp,ebp
0338A3FB  5D                        pop ebp
0338A3FC  C2 0C00                   retn C
--- snip ---

"call edx" -> edx from faulting thread context = 0x032fe560 gets the callee
address:

--- snip ---
032FE560  55                        push ebp
032FE561  8BEC                      mov ebp,esp
032FE563  83EC 50                   sub esp,50
032FE566  833D B00B4C03 00          cmp dword ptr [34C0BB0],0
032FE56D  53                        push ebx
032FE56E  8B5D 10                   mov ebx,[ebp+10]
032FE571  56                        push esi
032FE572  57                        push edi
032FE573  8B7D 0C                   mov edi,[ebp+C]
032FE576  8BF1                      mov esi,ecx
032FE578  74 27                     je short 032FE5A1
032FE57A  68 7CA54903               push 349A57C
032FE57F  B9 C0A94903               mov ecx,349A9C0
032FE584  90                        nop
032FE585  E8 B5FB18F0               call F348E13F
032FE58A  84C0                      test al,al
032FE58C  74 13                     je short 032FE5A1
032FE58E  8D46 10                   lea eax,[esi+10]
032FE591  50                        push eax
032FE592  53                        push ebx
032FE593  57                        push edi
032FE594  FF15 B00B4C03             call [34C0BB0]
...
--- snip ---

The interesting call is at 0x032FE585 -> "call F348E13F"

No need to disassemble the call target as it's obvious from the backtrace that
the fault is caused by executing ascii characters and not opcodes.

" Bytes at CS:EIP: 6d 73 76 63 72 74 2e 3f 3f 39 74 79 70 65 5f 69 "

Dump gives:

--- snip ---
F348E13F   6D 73 76 63 72 74 2E 3F 3F 38 74 79 70 65 5F 69   msvcrt.??8type_i
F348E14F   6E 66 6F 40 40 51 42 45 48 41 42 56 30 40 40 5A   nfo@@QBEHABV0@@Z
F348E15F   00 6D 73 76 63 72 74 2E 3F 3F 39 74 79 70 65 5F   .msvcrt.??9type_
F348E16F   69 6E 66 6F 40 40 51 42 45 48 41 42 56 30 40 40   info@@QBEHABV0@@
F348E17F   5A 00 6D 73 76 63 72 74 2E 3F 3F 5F 37 5F 5F 6E   Z.msvcrt.??_7__n
F348E18F   6F 6E 5F 72 74 74 69 5F 6F 62 6A 65 63 74 40 40   on_rtti_object@@
--- snip ---

It wants msvcr80.dll "??8type_info@@QBE_NABV0@@Z" which is unfortunately
forwarded to msvcrt.dll

Source:
http://source.winehq.org/git/wine.git/blob/dadb2fdfa9f73ef49a71837c3a21483056950d09:/dlls/msvcr80/msvcr80.spec#l49

--- snip ---
 49 @ thiscall -arch=i386 ??8type_info@@QBE_NABV0@@Z(ptr ptr)
msvcrt.??8type_info@@QBEHABV0@@Z
--- snip ---

Source:
http://source.winehq.org/git/wine.git/blob/e931b5d17ee481798a72de2bd3103ed2d7afb131:/dlls/msvcrt/cpp.c#l538

--- quote ---
538 /******************************************************************
539 * ??8type_info@@QBEHABV0@@Z (MSVCRT.@)
540 */
541 DEFINE_THISCALL_WRAPPER(MSVCRT_type_info_opequals_equals,8)
542 int __thiscall MSVCRT_type_info_opequals_equals(type_info * _this, const
type_info * rhs)
543 {
544 int ret = !strcmp(_this->mangled + 1, rhs->mangled + 1);
545 TRACE("(%p %p) returning %d\n", _this, rhs, ret);
546 return ret;
547 }
--- quote ---

Figuring out the list imports that can't be forwarded to msvcrt is usually done
using following approach (assuming no IAT/indirect calls)...

Basically you search the mapped range of unpacked dll code section(s), checking
all call/jmp destinations that match the range of mapped system dll (all
sections), throw away the ones that point to code section and analyse the ones
that point to other (data) section(s). 

The following APIs that should not be forwarded to msvcrt:

--- quote ---
msvcr80.dll.??0exception at std@@QAE at ABQBD@Z
msvcr80.dll.??0exception at std@@QAE at ABQBDH@Z
msvcr80.dll.??0exception at std@@QAE at ABV01@@Z
msvcr80.dll.??0exception at std@@QAE at XZ
msvcr80.dll.??1exception at std@@UAE at XZ
msvcr80.dll.??8type_info@@QBE_NABV0@@Z
msvcr80.dll.??9type_info@@QBE_NABV0@@Z
msvcr80.dll.?_name_internal_method at type_info@@QBEPBDPAU__type_info_node@@@Z
--- quote ---

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