|
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/eat_resolver.h" |
|
6 |
|
7 #include "base/win/pe_image.h" |
|
8 #include "sandbox/win/src/sandbox_nt_util.h" |
|
9 |
|
10 namespace sandbox { |
|
11 |
|
12 NTSTATUS EatResolverThunk::Setup(const void* target_module, |
|
13 const void* interceptor_module, |
|
14 const char* target_name, |
|
15 const char* interceptor_name, |
|
16 const void* interceptor_entry_point, |
|
17 void* thunk_storage, |
|
18 size_t storage_bytes, |
|
19 size_t* storage_used) { |
|
20 NTSTATUS ret = Init(target_module, interceptor_module, target_name, |
|
21 interceptor_name, interceptor_entry_point, |
|
22 thunk_storage, storage_bytes); |
|
23 if (!NT_SUCCESS(ret)) |
|
24 return ret; |
|
25 |
|
26 if (!eat_entry_) |
|
27 return STATUS_INVALID_PARAMETER; |
|
28 |
|
29 size_t thunk_bytes = GetInternalThunkSize(); |
|
30 |
|
31 #if defined(_WIN64) |
|
32 // We have two thunks, in order: the return path and the forward path. |
|
33 if (!SetInternalThunk(thunk_storage, storage_bytes, NULL, target_)) |
|
34 return STATUS_BUFFER_TOO_SMALL; |
|
35 |
|
36 storage_bytes -= thunk_bytes; |
|
37 thunk_storage = reinterpret_cast<char*>(thunk_storage) + thunk_bytes; |
|
38 #endif |
|
39 |
|
40 if (!SetInternalThunk(thunk_storage, storage_bytes, target_, interceptor_)) |
|
41 return STATUS_BUFFER_TOO_SMALL; |
|
42 |
|
43 AutoProtectMemory memory; |
|
44 ret = memory.ChangeProtection(eat_entry_, sizeof(DWORD), PAGE_READWRITE); |
|
45 if (!NT_SUCCESS(ret)) |
|
46 return ret; |
|
47 |
|
48 // Perform the patch. |
|
49 #pragma warning(push) |
|
50 #pragma warning(disable: 4311) |
|
51 // These casts generate warnings because they are 32 bit specific. |
|
52 *eat_entry_ = reinterpret_cast<DWORD>(thunk_storage) - |
|
53 reinterpret_cast<DWORD>(target_module); |
|
54 #pragma warning(pop) |
|
55 |
|
56 if (NULL != storage_used) |
|
57 *storage_used = GetThunkSize(); |
|
58 |
|
59 return ret; |
|
60 } |
|
61 |
|
62 NTSTATUS EatResolverThunk::ResolveTarget(const void* module, |
|
63 const char* function_name, |
|
64 void** address) { |
|
65 DCHECK_NT(address); |
|
66 if (!module) |
|
67 return STATUS_INVALID_PARAMETER; |
|
68 |
|
69 base::win::PEImage pe(module); |
|
70 if (!pe.VerifyMagic()) |
|
71 return STATUS_INVALID_IMAGE_FORMAT; |
|
72 |
|
73 eat_entry_ = pe.GetExportEntry(function_name); |
|
74 |
|
75 if (!eat_entry_) |
|
76 return STATUS_PROCEDURE_NOT_FOUND; |
|
77 |
|
78 *address = pe.RVAToAddr(*eat_entry_); |
|
79 |
|
80 return STATUS_SUCCESS; |
|
81 } |
|
82 |
|
83 size_t EatResolverThunk::GetThunkSize() const { |
|
84 #if defined(_WIN64) |
|
85 return GetInternalThunkSize() * 2; |
|
86 #else |
|
87 return GetInternalThunkSize(); |
|
88 #endif |
|
89 } |
|
90 |
|
91 } // namespace sandbox |