[Bug 35788] Planetside 2 crashes on launch (uninitialized/implausible MONITORINFOA.cbSize passed to GetMonitorInfoA, causing stack buffer overwrite)
wine-bugs at winehq.org
wine-bugs at winehq.org
Sat Apr 12 10:41:23 CDT 2014
https://bugs.winehq.org/show_bug.cgi?id=35788
Anastasius Focht <focht at gmx.net> changed:
What |Removed |Added
----------------------------------------------------------------------------
Keywords| |obfuscation
CC| |focht at gmx.net
Component|-unknown |user32
Depends on| |32342
Summary|Planetside 2 crashes on |Planetside 2 crashes on
|launch |launch
| |(uninitialized/implausible
| |MONITORINFOA.cbSize passed
| |to GetMonitorInfoA, causing
| |stack buffer overwrite)
--- Comment #4 from Anastasius Focht <focht at gmx.net> ---
Hello folks,
confirming.
--- snip ---
$ pwd
/home/focht/.wine/drive_c/Program Files/Sony Online Entertainment/Installed
Games/PlanetSide 2
$ WINEDEBUG=+tid,+seh,+relay wine ./LaunchPad.exe >>log.txt 2>&1
...
004a:Call user32.CreateWindowExA(00040100,04ca729c "Planetside2 PlayClient
(Stage) x86",0c49a3fc "Planetside2 v0.133.17.273288
x86",10ca0000,00000000,00000000,00000780,00000438,00000000,00000000,00000000,0c4ac360)
ret=0094c712
...
004a:Call window proc 0x94e170
(hwnd=0x30088,msg=WM_CREATE,wp=00000000,lp=0033e450)
004a:Call user32.MonitorFromWindow(00030088,00000001) ret=0094e21d
004a:Call winex11.drv.EnumDisplayMonitors(00000000,00000000,7ecf9f30,0033dc04)
ret=7ecfa5e5
004a:Call winex11.drv.GetMonitorInfo(00000001,0033da84) ret=7ecfa515
004a:Ret winex11.drv.GetMonitorInfo() retval=00000001 ret=7ecfa515
004a:Ret winex11.drv.EnumDisplayMonitors() retval=00000001 ret=7ecfa5e5
004a:Ret user32.MonitorFromWindow() retval=00000001 ret=0094e21d
004a:Call user32.GetMonitorInfoA(00000001,0033ddec) ret=0094e228
004a:Call winex11.drv.GetMonitorInfo(00000001,0033dc70) ret=7ecfa515
004a:Ret winex11.drv.GetMonitorInfo() retval=00000001 ret=7ecfa515
004a:Ret user32.GetMonitorInfoA() retval=00000001 ret=0094e228
004a:Call user32.DefWindowProcA(00030088,00000001,00000000,0033e450)
ret=0094e256
004a:Ret user32.DefWindowProcA() retval=00000000 ret=0094e256
004a:Call KERNEL32.IsDebuggerPresent() ret=012586ed
004a:Ret KERNEL32.IsDebuggerPresent() retval=00000000 ret=012586ed
004a:Call KERNEL32.SetUnhandledExceptionFilter(00000000) ret=01258702
004a:Ret KERNEL32.SetUnhandledExceptionFilter() retval=0091cf00 ret=01258702
004a:Call KERNEL32.UnhandledExceptionFilter(0289d718) ret=0125870d
wine: Unhandled exception 0xc0000409 in thread 4a at address 0x94e263 (thread
004a), starting debugger...
004a:trace:seh:start_debugger Starting debugger "winedbg --auto 73 1388"
004a:trace:process:create_process_impl app (null) cmdline L"winedbg --auto 73
1388"
004a:trace:process:find_exe_file looking for L"winedbg"
004a:trace:process:find_exe_file Trying native exe
L"C:\\windows\\system32\\winedbg.exe"
004a:trace:process:create_process_impl starting
L"C:\\windows\\system32\\winedbg.exe" as Win32 binary (0x10000000-0x10017000,
arch 014c)
004a:trace:process:create_process_impl started process pid 0061 tid 0062
...
004a:Ret KERNEL32.UnhandledExceptionFilter() retval=00000000 ret=0125870d
005f:Call KERNEL32.Sleep(00000064) ret=0092d4fd
004a:Call KERNEL32.TerminateProcess(ffffffff,c0000409) ret=01258730
004a:Call KERNEL32.FreeLibrary(f7270000) ret=f70a242a
004a:Call PE DLL (proc=0xf7285318,module=0xf7270000
L"uxtheme.dll",reason=PROCESS_DETACH,res=(nil))
004a:Ret PE DLL (proc=0xf7285318,module=0xf7270000
L"uxtheme.dll",reason=PROCESS_DETACH,res=(nil)) retval=1
004a:trace:loaddll:free_modref Unloaded module
L"C:\\windows\\system32\\uxtheme.dll" : builtin
004a:Ret KERNEL32.FreeLibrary() retval=00000001 ret=f70a242a
Process of pid=0049 has terminated
No process loaded, cannot execute 'echo Modules:'
Cannot get info on module while no process is loaded
No process loaded, cannot execute 'echo Threads:'
process tid prio (all id:s are in hex)
00000008 notepad.exe
00000009 0
0000000e services.exe
0000001d 0
0000001c 0
00000014 0
00000010 0
0000000f 0
00000012 winedevice.exe
0000001b 0
00000018 0
00000017 0
00000013 0
00000019 plugplay.exe
0000001f 0
0000001e 0
0000001a 0
00000020 explorer.exe
00000021 0
winedbg: Internal crash at 0x7edc33b7
--- snip ---
First, the crash reporting suffers from bug 24038
In this case 'winedbg' races against the process termination hence the internal
crash.
Relevant disassembly after dumping the main executable from memory and
rebuilding the IAT (also annotated to depict the important variables):
--- snip ---
0094E170 push ebp
0094E171 mov ebp, esp
0094E173 sub esp, 0D0h
0094E179 mov eax, _stack_canary_magic
0094E17E xor eax, ebp
0094E180 mov [ebp+stack_canary], eax
...
0094E207 mov ecx, [ebp+hwnd]
0094E20D mov eax, [esi]
0094E20F push 1 ; dwFlags
0094E211 push ecx ; hwnd
0094E212 mov dword_2DA1730, eax
0094E217 call ds:MonitorFromWindow
0094E21D lea edx, [ebp+mi]
0094E220 push edx ; lpmi
0094E221 push eax ; hMonitor
0094E222 call ds:GetMonitorInfoA
0094E228 mov eax, [ebp+mi.rcMonitor.bottom]
0094E22B sub eax, [ebp+mi.rcMonitor.top]
0094E22E mov edx, [ebp+mi.rcMonitor.right]
0094E231 mov ecx, dword_2DA1730
0094E237 sub edx, [ebp+mi.rcMonitor.left]
0094E23A push esi ; lParam
0094E23B push edi ; wParam
0094E23C mov [ecx+1303Ch], eax
0094E242 mov eax, [ebp+hwnd]
0094E248 push ebx ; Msg
0094E249 push eax ; hWnd
0094E24A mov [ecx+13038h], edx
0094E250 call ds:DefWindowProcA
0094E256 pop edi
0094E257 pop esi
0094E258 pop ebx
0094E259 mov ecx, [ebp+_stack_canary]
0094E25C xor ecx, ebp
0094E25E call _check_stack_canary
0094E263 mov esp, ebp
0094E265 pop ebp
0094E266 retn 10h
...
_check_stack_canary:
0124BC85 cmp ecx, _stack_canary_magic
0124BC8B jnz short loc_124BC8F
0124BC8D rep retn
0124BC8F jmp _exception_stack_buffer_overrun
--- snip ---
Stack layout:
--- snip ---
-000000DC
...
-000000D0
-000000CC
-000000C8 ; hwnd
-000000C4
-000000C3
-0000002C ; 'mi' -> MONITORINFO (sizeof=0x28)
-00000004 ; stack_canary
+00000000
+00000004 ; ret addr
+00000008 ; arg_0
+0000000C ; arg_4_Msg
+00000010 ; arg_8_wParam
+00000014 ; arg_C_lParam
--- snip ---
Well, to make story short: some 'genius' forgot to initialize the 'cbSize'
member of 'MONITORINFOA' struct passed to GetMonitorInfoA().
There is a stack canary living adjacent to 'MONITORINFO' struct which gets
overwritten by Wine.
This is detected in function epilog code hence the exception (stack buffer
overrun).
There are two calls to GetMonitorInfoA() during startup, I printed the values:
--- snip ---
GetMonitorInfoA lpMonitorInfo->cbSize = 0x48
GetMonitorInfoA lpMonitorInfo->cbSize = 0x7d9ae2fc
--- snip ---
Wine needs to check for maximum allowed size -> sizeof(MONITORINFOEXA) struct
to protect against stupid apps.
This is not 100% foolproof because the uninitialized 'cbSize' value could be
still within 'sizeof(MONITORINFOA)+[1..CCHDEVICENAME]' range, allowing to write
past the buffer.
Wine:
http://source.winehq.org/git/wine.git/blob/bd262c606a5dca79aa2ec0d863bad04e4b776087:/dlls/user32/misc.c#l416
--- snip ---
416 BOOL WINAPI GetMonitorInfoA(HMONITOR hMonitor, LPMONITORINFO lpMonitorInfo)
417 {
418 MONITORINFOEXW miW;
419 MONITORINFOEXA *miA = (MONITORINFOEXA*)lpMonitorInfo;
420 BOOL ret;
421
422 miW.cbSize = sizeof(miW);
423
424 ret = GetMonitorInfoW(hMonitor, (MONITORINFO*)&miW);
425 if(!ret) return ret;
426
427 miA->rcMonitor = miW.rcMonitor;
428 miA->rcWork = miW.rcWork;
429 miA->dwFlags = miW.dwFlags;
430 if(miA->cbSize >= offsetof(MONITORINFOEXA, szDevice) +
sizeof(miA->szDevice))
431 WideCharToMultiByte(CP_ACP, 0, miW.szDevice, -1, miA->szDevice,
sizeof(miA->szDevice), NULL, NULL);
432 return ret;
433 }
--- snip ---
The game starts successfully if you add the upper bound check, catching
implausible values (I reached the lobby).
$ sha1sum PS2_setup.exe
acc50d2d6c70a1da8b5fc1315d53a639b55451b5 PS2_setup.exe
$ du -sh PS2_setup.exe
7.8M PS2_setup.exe
$ wine --version
wine-1.7.16-133-gd8ca8c2
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