michael@0: // Copyright (c) 2006-2010 The Chromium Authors. All rights reserved. michael@0: // Use of this source code is governed by a BSD-style license that can be michael@0: // found in the LICENSE file. michael@0: michael@0: #include "sandbox/win/src/resolver.h" michael@0: michael@0: #include "sandbox/win/src/sandbox_nt_util.h" michael@0: michael@0: namespace { michael@0: michael@0: #pragma pack(push, 1) michael@0: struct InternalThunk { michael@0: // This struct contains roughly the following code: michael@0: // sub esp, 8 // Create working space michael@0: // push edx // Save register michael@0: // mov edx, [esp + 0xc] // Get return adddress michael@0: // mov [esp + 8], edx // Store return address michael@0: // mov dword ptr [esp + 0xc], 0x7c401200 // Store extra argument michael@0: // mov dword ptr [esp + 4], 0x40010203 // Store address to jump to michael@0: // pop edx // Restore register michael@0: // ret // Jump to interceptor michael@0: // michael@0: // This code only modifies esp and eip so it must work with to normal calling michael@0: // convention. It is assembled as: michael@0: // michael@0: // 00 83ec08 sub esp,8 michael@0: // 03 52 push edx michael@0: // 04 8b54240c mov edx,dword ptr [esp + 0Ch] michael@0: // 08 89542408 mov dword ptr [esp + 8], edx michael@0: // 0c c744240c0012407c mov dword ptr [esp + 0Ch], 7C401200h michael@0: // 14 c744240403020140 mov dword ptr [esp + 4], 40010203h michael@0: // 1c 5a pop edx michael@0: // 1d c3 ret michael@0: InternalThunk() { michael@0: opcodes_1 = 0x5208ec83; michael@0: opcodes_2 = 0x0c24548b; michael@0: opcodes_3 = 0x08245489; michael@0: opcodes_4 = 0x0c2444c7; michael@0: opcodes_5 = 0x042444c7; michael@0: opcodes_6 = 0xc35a; michael@0: extra_argument = 0; michael@0: interceptor_function = 0; michael@0: }; michael@0: ULONG opcodes_1; // = 0x5208ec83 michael@0: ULONG opcodes_2; // = 0x0c24548b michael@0: ULONG opcodes_3; // = 0x08245489 michael@0: ULONG opcodes_4; // = 0x0c2444c7 michael@0: ULONG extra_argument; michael@0: ULONG opcodes_5; // = 0x042444c7 michael@0: ULONG interceptor_function; michael@0: USHORT opcodes_6; // = 0xc35a michael@0: }; michael@0: #pragma pack(pop) michael@0: michael@0: }; // namespace michael@0: michael@0: namespace sandbox { michael@0: michael@0: bool ResolverThunk::SetInternalThunk(void* storage, size_t storage_bytes, michael@0: const void* original_function, michael@0: const void* interceptor) { michael@0: if (storage_bytes < sizeof(InternalThunk)) michael@0: return false; michael@0: michael@0: InternalThunk* thunk = new(storage, NT_PLACE) InternalThunk; michael@0: michael@0: #pragma warning(push) michael@0: #pragma warning(disable: 4311) michael@0: // These casts generate warnings because they are 32 bit specific. michael@0: thunk->interceptor_function = reinterpret_cast(interceptor); michael@0: thunk->extra_argument = reinterpret_cast(original_function); michael@0: #pragma warning(pop) michael@0: michael@0: return true; michael@0: } michael@0: michael@0: size_t ResolverThunk::GetInternalThunkSize() const { michael@0: return sizeof(InternalThunk); michael@0: } michael@0: michael@0: NTSTATUS ResolverThunk::ResolveTarget(const void* module, michael@0: const char* function_name, michael@0: void** address) { michael@0: const void** casted = const_cast(address); michael@0: return ResolverThunk::ResolveInterceptor(module, function_name, casted); michael@0: } michael@0: michael@0: } // namespace sandbox