[v2] kernel32: Read entry before LdrInitializeThunk

Andrew Wesie awesie at gmail.com
Fri Feb 3 04:39:58 CST 2017


Overwatch overwrites the PE header contents in a TLS callback. This results in
a crash on wine, because the entry point will be incorrect in start_process.

Fix the issue by reading the entry point before LdrInitializeThunk is called,
and using this stored value in start_process instead of the PE header.

Signed-off-by: Andrew Wesie <awesie at gmail.com>
---
 dlls/kernel32/process.c | 19 +++++++++----------
 1 file changed, 9 insertions(+), 10 deletions(-)

diff --git a/dlls/kernel32/process.c b/dlls/kernel32/process.c
index 5a9fea2..48bb7bb 100644
--- a/dlls/kernel32/process.c
+++ b/dlls/kernel32/process.c
@@ -88,6 +88,7 @@ static const BOOL is_win64 = (sizeof(void *) > sizeof(int));
 
 HMODULE kernel32_handle = 0;
 SYSTEM_BASIC_INFORMATION system_info = { 0 };
+LPTHREAD_START_ROUTINE entry_proc = NULL;
 
 const WCHAR *DIR_Windows = NULL;
 const WCHAR *DIR_System = NULL;
@@ -1085,14 +1086,7 @@ static inline DWORD call_process_entry( PEB *peb, LPTHREAD_START_ROUTINE entry )
  */
 static DWORD WINAPI start_process( PEB *peb )
 {
-    IMAGE_NT_HEADERS *nt;
-    LPTHREAD_START_ROUTINE entry;
-
-    nt = RtlImageNtHeader( peb->ImageBaseAddress );
-    entry = (LPTHREAD_START_ROUTINE)((char *)peb->ImageBaseAddress +
-                                     nt->OptionalHeader.AddressOfEntryPoint);
-
-    if (!nt->OptionalHeader.AddressOfEntryPoint)
+    if (entry_proc == (LPTHREAD_START_ROUTINE)peb->ImageBaseAddress)
     {
         ERR( "%s doesn't have an entry point, it cannot be executed\n",
              debugstr_w(peb->ProcessParameters->ImagePathName.Buffer) );
@@ -1101,11 +1095,11 @@ static DWORD WINAPI start_process( PEB *peb )
 
     if (TRACE_ON(relay))
         DPRINTF( "%04x:Starting process %s (entryproc=%p)\n", GetCurrentThreadId(),
-                 debugstr_w(peb->ProcessParameters->ImagePathName.Buffer), entry );
+                 debugstr_w(peb->ProcessParameters->ImagePathName.Buffer), entry_proc );
 
     SetLastError( 0 );  /* clear error code */
     if (peb->BeingDebugged) DbgBreakPoint();
-    return call_process_entry( peb, entry );
+    return call_process_entry( peb, entry_proc );
 }
 
 
@@ -1186,6 +1180,7 @@ void CDECL __wine_kernel_init(void)
     RTL_USER_PROCESS_PARAMETERS *params = peb->ProcessParameters;
     HANDLE boot_events[2];
     BOOL got_environment = TRUE;
+    IMAGE_NT_HEADERS *nt;
 
     /* Initialize everything */
 
@@ -1299,6 +1294,10 @@ void CDECL __wine_kernel_init(void)
 
     if (!params->CurrentDirectory.Handle) chdir("/"); /* avoid locking removable devices */
 
+    nt = RtlImageNtHeader( peb->ImageBaseAddress );
+    entry_proc = (LPTHREAD_START_ROUTINE)((char *)peb->ImageBaseAddress +
+                                          nt->OptionalHeader.AddressOfEntryPoint);
+
     LdrInitializeThunk( start_process, 0, 0, 0 );
 
  error:
-- 
2.7.4




More information about the wine-patches mailing list