From: Sebastian Lackner Subject: [2/6] ntdll: Add support for ATL thunk 'MOV this,edx; MOV func,ecx; JMP ecx'. Message-Id: <5445FE28.9060506@fds-team.de> Date: Tue, 21 Oct 2014 08:33:12 +0200 --- dlls/kernel32/tests/virtual.c | 16 ++++++++++++++++ dlls/ntdll/signal_i386.c | 19 +++++++++++++++++++ 2 files changed, 35 insertions(+) From 5f55f3358900b9ac53c877cb96736b96dc07ff4b Mon Sep 17 00:00:00 2001 From: Sebastian Lackner Date: Tue, 21 Oct 2014 06:00:20 +0200 Subject: ntdll: Add support for ATL thunk 'MOV this,edx; MOV func,ecx; JMP ecx'. --- dlls/kernel32/tests/virtual.c | 16 ++++++++++++++++ dlls/ntdll/signal_i386.c | 19 +++++++++++++++++++ 2 files changed, 35 insertions(+) diff --git a/dlls/kernel32/tests/virtual.c b/dlls/kernel32/tests/virtual.c index 5f83ead..a89f1e3 100644 --- a/dlls/kernel32/tests/virtual.c +++ b/dlls/kernel32/tests/virtual.c @@ -1912,6 +1912,7 @@ static void test_atl_thunk_emulation( ULONG dep_flags ) static const char code_jmp[] = {0xE9, 0x00, 0x00, 0x00, 0x00}; static const char code_atl1[] = {0xC7, 0x44, 0x24, 0x04, 0x44, 0x33, 0x22, 0x11, 0xE9, 0x00, 0x00, 0x00, 0x00}; static const char code_atl2[] = {0xB9, 0x44, 0x33, 0x22, 0x11, 0xE9, 0x00, 0x00, 0x00, 0x00}; + static const char code_atl3[] = {0xBA, 0x44, 0x33, 0x22, 0x11, 0xB9, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xE1}; static const char cls_name[] = "atl_thunk_class"; DWORD ret, size, old_prot; ULONG old_flags = MEM_EXECUTE_OPTION_ENABLE; @@ -2098,6 +2099,21 @@ static void test_atl_thunk_emulation( ULONG dep_flags ) else ok( num_execute_fault_calls == 0, "expected no STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls ); + memcpy( base, code_atl3, sizeof(code_atl3) ); + *(DWORD *)(base + 6) = (DWORD_PTR)atl_test_func; + + success = VirtualProtect( base, size, PAGE_READWRITE, &old_prot ); + ok( success, "VirtualProtect failed %u\n", GetLastError() ); + + ret = send_message_excpt( hWnd, WM_USER + 1, 0, 0 ); + /* FIXME: we don't check the content of the registers ECX/EDX yet */ + ok( ret == 43, "call returned wrong result, expected 43, got %d\n", ret ); + ok( num_guard_page_calls == 0, "expected no STATUS_GUARD_PAGE_VIOLATION exception, got %d exceptions\n", num_guard_page_calls ); + if ((dep_flags & MEM_EXECUTE_OPTION_DISABLE) && (dep_flags & MEM_EXECUTE_OPTION_DISABLE_THUNK_EMULATION)) + ok( num_execute_fault_calls == 1, "expected one STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls ); + else + ok( num_execute_fault_calls == 0, "expected no STATUS_ACCESS_VIOLATION exception, got %d exceptions\n", num_execute_fault_calls ); + /* Restore the JMP instruction, set to executable, and then destroy the Window */ memcpy( base, code_jmp, sizeof(code_jmp) ); diff --git a/dlls/ntdll/signal_i386.c b/dlls/ntdll/signal_i386.c index dde4e2d..e8c6a77 100644 --- a/dlls/ntdll/signal_i386.c +++ b/dlls/ntdll/signal_i386.c @@ -1632,6 +1632,14 @@ union atl_thunk BYTE jmp; /* jmp func */ int func; } t2; + struct + { + BYTE movl1; /* movl this,edx */ + DWORD this; + BYTE movl2; /* movl func,ecx */ + DWORD func; + WORD jmp; /* jmp ecx */ + } t3; }; #include "poppack.h" @@ -1670,6 +1678,17 @@ static BOOL check_atl_thunk( EXCEPTION_RECORD *rec, CONTEXT *context ) thunk, context->Eip, context->Ecx ); return TRUE; } + else if (thunk_len >= sizeof(thunk_copy.t3) && thunk_copy.t3.movl1 == 0xba && + thunk_copy.t3.movl2 == 0xb9 && + thunk_copy.t3.jmp == 0xe1ff) + { + context->Edx = thunk_copy.t3.this; + context->Ecx = thunk_copy.t3.func; + context->Eip = thunk_copy.t3.func; + TRACE( "emulating ATL thunk type 3 at %p, func=%08x ecx=%08x edx=%08x\n", + thunk, context->Eip, context->Ecx, context->Edx ); + return TRUE; + } return FALSE; } -- 2.1.2