[Bug 33698] Opera Next 15.x and 18.x crashes on startup (native API sandboxing/hooking scheme incompatible with Wine)

wine-bugs at winehq.org wine-bugs at winehq.org
Tue Nov 19 15:55:00 CST 2013


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

Anastasius Focht <focht at gmx.net> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
             Status|UNCONFIRMED                 |RESOLVED
                URL|                            |http://ftp.opera.com/ftp/pu
                   |                            |b/opera-next/15.0.1147.24/w
                   |                            |in/
           Keywords|                            |download, obfuscation
          Component|-unknown                    |ntdll
                 CC|                            |focht at gmx.net
         Resolution|                            |WONTFIX
            Summary|Opera Next 15 crashes.      |Opera Next 15.x and 18.x
                   |                            |crashes on startup (native
                   |                            |API sandboxing/hooking
                   |                            |scheme incompatible with
                   |                            |Wine)

--- Comment #3 from Anastasius Focht <focht at gmx.net> 2013-11-19 15:55:00 CST ---
Hello folks,

confirming.

In short: Opera Next seems to employ a process sandboxing scheme by low-level
hooking several native API (Ntxxx) expecting NT-style entry point layout.
The way the hooking is done won't work for Wine.

The following message can be spotted among the terminal spam when the second
Opera process is being started (child=sandbox):

--- snip ---
...
err:module:attach_process_dlls "KERNEL32.dll" failed to initialize, aborting
err:module:LdrInitializeThunk Main exe initialization for L"C:\\Program
Files\\Opera Next\\15.0.1147.24\\opera.exe" failed, status c0000005
...
--- snip ---

The parent process creates a suspended child and patches several native API
entry points in the remote process.

+relay doesn't give it away (relay thunks interfere here = won't work) but
+server does ...

I trimmed the log a bit from interleaving threads and other spam...

Example sequence for patching one native API entry point:

--- snip ---
...
0039:trace:module:LdrGetDllHandle L"ntdll.dll" -> 0x7bc10000 (load path
L"C:\\Program Files\\Opera
Next\\15.0.1147.24;.;C:\\windows\\system32;C:\\windows\\system;C:\\windows;C:\\windows\\system32;C:\\windows;C:\\windows\\system32\\wbem")
...
0039: read_process_memory( handle=0294, addr=7bc44a1f )
0039: read_process_memory() = 0 {
data={55,89,e5,83,e4,f0,83,ec,30,8b,45,30,89,44,24,28} }
0039: write_process_memory( handle=0294, addr=02a1a410,
data={55,89,e5,83,e4,f0,83,ec,30,8b,45,30,89,44,24,28,88,7a,f5,02,10,00,00,00,83,ec,08,52,8b,54,24,0c,89,54,24,08,c7,44,24,0c,10,a4,a1,02,c7,44,24,04,00,64,60,00,5a,c3}
)
0039: write_process_memory() = 0
0039:trace:virtual:NtProtectVirtualMemory 0x294 0x7bc44a1f 0000000c 00000008
...
0039: write_process_memory( handle=0294, addr=7bc44a1f,
data={b8,89,e5,83,e4,ba,28,a4,a1,02,ff,e2} )
0039: write_process_memory() = 0
...
--- snip ---

List of native API entry points being patched:

0x7bc44a1f -> NtCreateFile -> chunk 0x02a1a410
0x7bc449bc -> NtOpenFile -> chunk 0x02a1a490
0x7bc499c8 -> NtQueryFullAttributesFile -> chunk 0x02a1a4d0
0x7bc49059 -> NtSetInformationFile -> chunk 0x02a1a510
0x7bc8d03e -> NtOpenThread -> chunk 0x02a1a550
0x7bc69008 -> NtOpenProcess -> chunk 0x02a1a590
0x7bc5b6d5 -> NtOpenProcessToken -> chunk 0x02a1a5d0
0x7bc8e602 -> NtSetInformationThread -> chunk 0x02a1a610
0x7bc5b874 -> NtOpenThreadToken -> chunk 0x02a1a650
0x7bc5b723 -> NtOpenProcessTokenEx -> chunk 0x02a1a690
0x7bc5b8d0 -> NtOpenThreadTokenEx -> chunk 0x02a1a6d0
0x7bc9b647 -> NtMapViewOfSection -> chunk 0x02a1a710
0x7bc9c01f -> NtUnmapViewOfSection -> chunk 0x02a1a750

chunk = partial copy of original entry point code + dispatcher code to Opera PE
image

The parent resumes the execution of child when the child process has been
'prepared':

--- snip ---
...
0039: resume_thread( handle=0274 )
0025: *wakeup* signaled=258
0039: resume_thread() = 0 { count=1 }
0025: get_suspend_context( )
...
0039: close_handle( handle=0274 )
0039: close_handle() = 0 
...
0025:trace:module:process_attach (L"opera.exe",0x1) - START
0025:trace:module:process_attach (L"cryptui.dll",0x1) - START
0025:trace:module:process_attach (L"crypt32.dll",0x1) - START
0025:trace:module:process_attach (L"user32.dll",0x1) - START
0025:trace:module:process_attach (L"gdi32.dll",0x1) - START
0025:trace:module:process_attach (L"advapi32.dll",0x1) - START
0025:trace:module:process_attach (L"KERNEL32.dll",0x1) - START
0039: send_message( id=002b, type=6, flags=0, win=0001004a, msg=00000401,
wparam=02f21c80, lparam=00000000, timeout=infinite, data={} )
0025:trace:module:process_attach (L"ntdll.dll",0x1) - START
0025:trace:module:MODULE_InitDLL (0x7bc10000 L"ntdll.dll",PROCESS_ATTACH,0x1) -
CALL
0025:trace:module:MODULE_InitDLL (0x7bc10000,PROCESS_ATTACH,0x1) - RETURN 1
0039: send_message() = 0
0025:trace:module:process_attach (L"ntdll.dll",0x1) - END
0025:trace:module:MODULE_InitDLL (0x7b810000
L"KERNEL32.dll",PROCESS_ATTACH,0x1) - CALL
0025:trace:ntdll:NtQuerySystemInformation
(0x00000000,0x7ba5fd60,0x0000002c,(nil))
0039: select( flags=2, cookie=04c2e4bc, timeout=infinite, prev_apc=0000,
result={}, data={WAIT,handles={0134}} )
0025:trace:seh:raise_exception code=c0000005 flags=0 addr=0x2a1a65f ip=02a1a65f
tid=0025
0039: select() = PENDING { timeout=infinite, call={APC_NONE}, apc_handle=0000 }
0025:trace:seh:raise_exception  info[0]=00000001
0025:trace:seh:raise_exception  info[1]=1004f582
0025:trace:seh:raise_exception  eax=00020008 ebx=7bcd0000 ecx=0033f794
edx=00000000 esi=0033f870 edi=00000000
0025:trace:seh:raise_exception  ebp=0033f788 esp=0033f780 cs=0023 ds=002b
es=002b fs=0063 gs=006b flags=00010206
0025:trace:seh:call_stack_handlers calling handler at 0x7bc9df5c code=c0000005
flags=0
0025:trace:seh:__regs_RtlUnwind code=c0000005 flags=2
0025:trace:seh:__regs_RtlUnwind calling handler at 0x7bc819c1 code=c0000005
flags=2
0025:trace:seh:__regs_RtlUnwind handler at 0x7bc819c1 returned 1
0025:trace:module:MODULE_InitDLL (0x7b810000,PROCESS_ATTACH,0x1) - RETURN 0
0025:trace:module:MODULE_InitDLL (0x7b810000
L"KERNEL32.dll",PROCESS_DETACH,0x1) - CALL
0025:trace:module:MODULE_InitDLL (0x7b810000,PROCESS_DETACH,0x1) - RETURN 1
0025:warn:module:process_attach Initialization of L"KERNEL32.dll" failed
0025:trace:module:process_attach (L"KERNEL32.dll",0x1) - END
0025:trace:module:process_attach (L"advapi32.dll",0x1) - END
0025:trace:module:process_attach (L"gdi32.dll",0x1) - END
0025:trace:module:process_attach (L"user32.dll",0x1) - END
0039: *wakeup* signaled=0
0025:trace:module:process_attach (L"crypt32.dll",0x1) - END
0025:trace:module:process_attach (L"cryptui.dll",0x1) - END
0025:trace:module:process_attach (L"opera.exe",0x1) - END
0025:err:module:attach_process_dlls "KERNEL32.dll" failed to initialize,
aborting
0039: set_process_info( handle=0250, mask=1, priority=2, affinity=00000000 )
0025:err:module:LdrInitializeThunk Main exe initialization for L"C:\\Program
Files\\Opera Next\\15.0.1147.24\\opera.exe" failed, status c0000005 
--- snip ---

Faulting instruction address 0x2a1a65f lies within range of chunk 0x02a1a650
which is NtOpenThreadToken.

NtOpenThreadToken entry point *before* patch:

--- snip ---
7BC5B874    8D4C24 04       LEA ECX,[ESP+4]
7BC5B878    83E4 F0         AND ESP,FFFFFFF0
7BC5B87B    FF71 FC         PUSH DWORD PTR DS:[ECX-4]
7BC5B87E    55              PUSH EBP
7BC5B87F    89E5            MOV EBP,ESP
7BC5B881    53              PUSH EBX
7BC5B882    51              PUSH ECX
7BC5B883    83EC 20         SUB ESP,20
7BC5B886    E8 6530FCFF     CALL 7BC1E8F0
7BC5B88B    81C3 75470700   ADD EBX,74775
7BC5B891    89C8            MOV EAX,ECX
7BC5B893    8B50 08         MOV EDX,DWORD PTR DS:[EAX+8]
...
--- snip ---

NtOpenThreadToken entry point *after* patch:

--- snip ---
7BC5B874    B8 4C240483     MOV EAX,8304244C
7BC5B879    BA 68A6A102     MOV EDX,2A1A668
7BC5B87E    FFE2            JMP EDX
7BC5B880    E5 53           IN EAX,53
7BC5B882    51              PUSH ECX
7BC5B883    83EC 20         SUB ESP,20
7BC5B886    E8 6530FCFF     CALL 7BC1E8F0
7BC5B88B    81C3 75470700   ADD EBX,74775
--- snip ---

So what about chunk 0x02a1a650 ...

$+0 = 2A1A650
$+18 = 2A1A668 (JMP EDX target)

--- snip ---
$+0     8D4C24 04           LEA ECX,[ESP+4]
$+4     83E4 F0             AND ESP,FFFFFFF0
$+7     FF71 FC             PUSH DWORD PTR DS:[ECX-4]
$+A     55                  PUSH EBP
$+B     89E5                MOV EBP,ESP
$+D     53                  PUSH EBX
$+E     51                  PUSH ECX
$+F     8388 7AF50210 00    OR DWORD PTR DS:[EAX+1002F57A],00000000
$+16    0000                ADD BYTE PTR DS:[EAX],AL
$+18    83EC 08             SUB ESP,8
$+1B    52                  PUSH EDX
$+1C    8B5424 0C           MOV EDX,DWORD PTR SS:[ESP+0C]
$+20    895424 08           MOV DWORD PTR SS:[ESP+8],EDX
$+24    C74424 0C 50A6A102  MOV DWORD PTR SS:[ESP+0C],2A1A650 ; org entry start
$+2C    C74424 04 60056000  MOV DWORD PTR SS:[ESP+4],600560 ; opera PE image
$+34    5A                  POP EDX
$+35    C3                  RETN
--- snip ---

Faulting instruction: 0x2a1a65f -> "OR DWORD PTR DS:[EAX+1002F57A],00000000"
which is just garbage as only 16 bytes will be copied.

Opera's sandboxing scheme relies on standard NT-style entry point layout for
x86 which has 4 instructions (mov eax, syscall ordinal, mov edx, ptr to syscall
stub, indirect jmp to stub, ret xx = cleanup /w args).
It copies 16 bytes from native API entry (enough to cover all four opcodes)
into a dynamically allocated chunk in remote/child address space and appends
its own redirector code which sets up a 'ret' trampoline for final sandbox
dispatcher.

After the sandbox dispatcher code prepared/modified the arguments, the original
entry point code will be reached (set up by $+24).
The original API code must be entirely within $+F (remember: only 16 bytes get
copied).

This obviously can't work for Wine.
Wine can't mimic native NT API entry point signature by design -> I'd say this
is a WONTFIX.

$ sha1sum Opera_Next_15.0.1147.24_Setup.exe 
8d8e3664fb6ed84db80a6afe0d60158eac595347  Opera_Next_15.0.1147.24_Setup.exe

$ du -sh Opera_Next_15.0.1147.24_Setup.exe 
25M    Opera_Next_15.0.1147.24_Setup.exe

$ wine --version
wine-1.7.6-273-ga4d8627

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