From: Paul Gofman pgofman@codeweavers.com
--- dlls/ntdll/signal_x86_64.c | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-)
diff --git a/dlls/ntdll/signal_x86_64.c b/dlls/ntdll/signal_x86_64.c index ef9bfdd99c5..d14b053a148 100644 --- a/dlls/ntdll/signal_x86_64.c +++ b/dlls/ntdll/signal_x86_64.c @@ -37,6 +37,8 @@ WINE_DECLARE_DEBUG_CHANNEL(seh); WINE_DECLARE_DEBUG_CHANNEL(relay); WINE_DECLARE_DEBUG_CHANNEL(threadname);
+void (WINAPI * p_dispatch_wow_exception_thunk)( EXCEPTION_RECORD *, CONTEXT * ); + typedef struct _SCOPE_TABLE { ULONG Count; @@ -614,6 +616,7 @@ NTSTATUS WINAPI dispatch_wow_exception( EXCEPTION_RECORD *rec_ptr, CONTEXT *cont }
+void WINAPI dispatch_wow_exception_thunk( EXCEPTION_RECORD *, CONTEXT * ); __ASM_GLOBAL_FUNC( dispatch_wow_exception_thunk, "movw %cs,%ax\n\t" "cmpw %ax,0x38(%rdx)\n\t" /* context->SegCs */ @@ -628,6 +631,10 @@ __ASM_GLOBAL_FUNC( dispatch_wow_exception_thunk, * KiUserExceptionDispatcher (NTDLL.@) */ __ASM_GLOBAL_FUNC( KiUserExceptionDispatcher, + "nop\n\t" + /* Some anticheats rely on this opcode at exact offset to hook KiUserExceptionDispatcher + * in 64 bit app. */ + "movq " __ASM_NAME("p_dispatch_wow_exception_thunk") "(%rip),%rax\n\t" "mov 0x98(%rsp),%rcx\n\t" /* context->Rsp */ "mov 0xf8(%rsp),%rdx\n\t" /* context->Rip */ "mov %rdx,-0x8(%rcx)\n\t" @@ -649,10 +656,12 @@ __ASM_GLOBAL_FUNC( KiUserExceptionDispatcher, __ASM_CFI(".cfi_rel_offset %rdi,0x8\n\t") __ASM_CFI(".cfi_rel_offset %rsi,0\n\t")
+ "test %rax,%rax\n\t" + "jz 1f\n\t" "mov %rsp,%rdx\n\t" /* context */ "lea 0x4f0(%rsp),%rcx\n\t" /* rec */ - "call " __ASM_NAME("dispatch_wow_exception_thunk") "\n\t" - "mov %rsp,%rdx\n\t" /* context */ + "call *%rax\n\t" + "1:\tmov %rsp,%rdx\n\t" /* context */ "lea 0x4f0(%rsp),%rcx\n\t" /* rec */ "call " __ASM_NAME("dispatch_exception") "\n\t" "int3") @@ -1712,6 +1721,10 @@ __ASM_GLOBAL_FUNC( signal_start_thread, */ void WINAPI LdrInitializeThunk( CONTEXT *context, ULONG_PTR unk2, ULONG_PTR unk3, ULONG_PTR unk4 ) { + if (NtCurrentTeb()->WowTebOffset) + InterlockedCompareExchangePointer( (void * volatile *)&p_dispatch_wow_exception_thunk, + dispatch_wow_exception_thunk, NULL ); + loader_init( context, (void **)&context->Rcx ); TRACE_(relay)( "\1Starting thread proc %p (arg=%p)\n", (void *)context->Rcx, (void *)context->Rdx ); signal_start_thread( context );