1// Copyright (c) 2006-2010 The Chromium Authors. All rights reserved. 2// Use of this source code is governed by a BSD-style license that can be 3// found in the LICENSE file. 4 5#include "sandbox/win/src/resolver.h" 6 7// For placement new. This file must not depend on the CRT at runtime, but 8// placement operator new is inline. 9#include <new> 10 11#include "sandbox/win/src/sandbox_nt_util.h" 12 13namespace { 14 15#pragma pack(push, 1) 16struct InternalThunk { 17 // This struct contains roughly the following code: 18 // sub esp, 8 // Create working space 19 // push edx // Save register 20 // mov edx, [esp + 0xc] // Get return adddress 21 // mov [esp + 8], edx // Store return address 22 // mov dword ptr [esp + 0xc], 0x7c401200 // Store extra argument 23 // mov dword ptr [esp + 4], 0x40010203 // Store address to jump to 24 // pop edx // Restore register 25 // ret // Jump to interceptor 26 // 27 // This code only modifies esp and eip so it must work with to normal calling 28 // convention. It is assembled as: 29 // 30 // 00 83ec08 sub esp,8 31 // 03 52 push edx 32 // 04 8b54240c mov edx,dword ptr [esp + 0Ch] 33 // 08 89542408 mov dword ptr [esp + 8], edx 34 // 0c c744240c0012407c mov dword ptr [esp + 0Ch], 7C401200h 35 // 14 c744240403020140 mov dword ptr [esp + 4], 40010203h 36 // 1c 5a pop edx 37 // 1d c3 ret 38 InternalThunk() { 39 opcodes_1 = 0x5208ec83; 40 opcodes_2 = 0x0c24548b; 41 opcodes_3 = 0x08245489; 42 opcodes_4 = 0x0c2444c7; 43 opcodes_5 = 0x042444c7; 44 opcodes_6 = 0xc35a; 45 extra_argument = 0; 46 interceptor_function = 0; 47 }; 48 ULONG opcodes_1; // = 0x5208ec83 49 ULONG opcodes_2; // = 0x0c24548b 50 ULONG opcodes_3; // = 0x08245489 51 ULONG opcodes_4; // = 0x0c2444c7 52 ULONG extra_argument; 53 ULONG opcodes_5; // = 0x042444c7 54 ULONG interceptor_function; 55 USHORT opcodes_6; // = 0xc35a 56}; 57#pragma pack(pop) 58 59}; // namespace 60 61namespace sandbox { 62 63bool ResolverThunk::SetInternalThunk(void* storage, size_t storage_bytes, 64 const void* original_function, 65 const void* interceptor) { 66 if (storage_bytes < sizeof(InternalThunk)) 67 return false; 68 69 InternalThunk* thunk = new(storage) InternalThunk; 70 71#pragma warning(push) 72#pragma warning(disable: 4311) 73 // These casts generate warnings because they are 32 bit specific. 74 thunk->interceptor_function = reinterpret_cast<ULONG>(interceptor); 75 thunk->extra_argument = reinterpret_cast<ULONG>(original_function); 76#pragma warning(pop) 77 78 return true; 79} 80 81size_t ResolverThunk::GetInternalThunkSize() const { 82 return sizeof(InternalThunk); 83} 84 85NTSTATUS ResolverThunk::ResolveTarget(const void* module, 86 const char* function_name, 87 void** address) { 88 const void** casted = const_cast<const void**>(address); 89 return ResolverThunk::ResolveInterceptor(module, function_name, casted); 90} 91 92} // namespace sandbox 93