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