blob: fae2551bd7b247c5e7d35f5021f95ba7a8c531ff [file] [log] [blame]
[email protected]648d3862012-01-24 16:19:361// Copyright (c) 2012 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/*
initial.commit920c0912008-07-27 00:12:166 * Definition of PreamblePatcher
7 */
8
9#ifndef MEMORY_WATCHER_PREAMBLE_PATCHER_H__
10#define MEMORY_WATCHER_PREAMBLE_PATCHER_H__
11
12#include <windows.h>
13
14// compatibility shim
15#include "base/logging.h"
16#define ASSERT(cond, msg) DCHECK(cond)
17#define ASSERT1(cond) DCHECK(cond)
18
19// Maximum size of the preamble stub. We overwrite at least the first 5
20// bytes of the function. Considering the worst case scenario, we need 4
21// bytes + the max instruction size + 5 more bytes for our jump back to
22// the original code. With that in mind, 32 is a good number :)
[email protected]f0a51fb52009-03-05 12:46:3823#define MAX_PREAMBLE_STUB_SIZE (32)
initial.commit920c0912008-07-27 00:12:1624
25namespace sidestep {
26
27// Possible results of patching/unpatching
28enum SideStepError {
29 SIDESTEP_SUCCESS = 0,
30 SIDESTEP_INVALID_PARAMETER,
31 SIDESTEP_INSUFFICIENT_BUFFER,
32 SIDESTEP_JUMP_INSTRUCTION,
33 SIDESTEP_FUNCTION_TOO_SMALL,
34 SIDESTEP_UNSUPPORTED_INSTRUCTION,
35 SIDESTEP_NO_SUCH_MODULE,
36 SIDESTEP_NO_SUCH_FUNCTION,
37 SIDESTEP_ACCESS_DENIED,
38 SIDESTEP_UNEXPECTED,
39};
40
41#define SIDESTEP_TO_HRESULT(error) \
42 MAKE_HRESULT(SEVERITY_ERROR, FACILITY_NULL, error)
43
44// Implements a patching mechanism that overwrites the first few bytes of
45// a function preamble with a jump to our hook function, which is then
46// able to call the original function via a specially-made preamble-stub
47// that imitates the action of the original preamble.
48//
49// NOTE: This patching mechanism should currently only be used for
50// non-production code, e.g. unit tests, because it is not threadsafe.
51// See the TODO in preamble_patcher_with_stub.cc for instructions on what
52// we need to do before using it in production code; it's fairly simple
53// but unnecessary for now since we only intend to use it in unit tests.
[email protected]f0a51fb52009-03-05 12:46:3854//
initial.commit920c0912008-07-27 00:12:1655// To patch a function, use either of the typesafe Patch() methods. You
56// can unpatch a function using Unpatch().
[email protected]f0a51fb52009-03-05 12:46:3857//
initial.commit920c0912008-07-27 00:12:1658// Typical usage goes something like this:
59// @code
60// typedef int (*MyTypesafeFuncPtr)(int x);
61// MyTypesafeFuncPtr original_func_stub;
62// int MyTypesafeFunc(int x) { return x + 1; }
63// int HookMyTypesafeFunc(int x) { return 1 + original_func_stub(x); }
[email protected]f0a51fb52009-03-05 12:46:3864//
initial.commit920c0912008-07-27 00:12:1665// void MyPatchInitializingFunction() {
66// original_func_stub = PreamblePatcher::Patch(
67// MyTypesafeFunc, HookMyTypesafeFunc);
68// if (!original_func_stub) {
69// // ... error handling ...
70// }
[email protected]f0a51fb52009-03-05 12:46:3871//
initial.commit920c0912008-07-27 00:12:1672// // ... continue - you have patched the function successfully ...
73// }
74// @endcode
[email protected]f0a51fb52009-03-05 12:46:3875//
initial.commit920c0912008-07-27 00:12:1676// Note that there are a number of ways that this method of patching can
77// fail. The most common are:
78// - If there is a jump (jxx) instruction in the first 5 bytes of
79// the function being patched, we cannot patch it because in the
80// current implementation we do not know how to rewrite relative
81// jumps after relocating them to the preamble-stub. Note that
82// if you really really need to patch a function like this, it
83// would be possible to add this functionality (but at some cost).
84// - If there is a return (ret) instruction in the first 5 bytes
85// we cannot patch the function because it may not be long enough
86// for the jmp instruction we use to inject our patch.
87// - If there is another thread currently executing within the bytes
88// that are copied to the preamble stub, it will crash in an undefined
89// way.
[email protected]f0a51fb52009-03-05 12:46:3890//
initial.commit920c0912008-07-27 00:12:1691// If you get any other error than the above, you're either pointing the
92// patcher at an invalid instruction (e.g. into the middle of a multi-
93// byte instruction, or not at memory containing executable instructions)
94// or, there may be a bug in the disassembler we use to find
95// instruction boundaries.
96//
97// NOTE: In optimized builds, when you have very trivial functions that
98// the compiler can reason do not have side effects, the compiler may
99// reuse the result of calling the function with a given parameter, which
100// may mean if you patch the function in between your patch will never get
101// invoked. See preamble_patcher_test.cc for an example.
102class PreamblePatcher {
103 public:
104
105 // This is a typesafe version of RawPatch(), identical in all other
106 // ways than it takes a template parameter indicating the type of the
107 // function being patched.
108 //
109 // @param T The type of the function you are patching. Usually
110 // you will establish this type using a typedef, as in the following
111 // example:
112 // @code
113 // typedef BOOL (WINAPI *MessageBoxPtr)(HWND, LPCTSTR, LPCTSTR, UINT);
114 // MessageBoxPtr original = NULL;
115 // PreamblePatcher::Patch(MessageBox, Hook_MessageBox, &original);
116 // @endcode
117 template <class T>
118 static SideStepError Patch(T target_function,
119 T replacement_function,
120 T* original_function_stub) {
121 // NOTE: casting from a function to a pointer is contra the C++
122 // spec. It's not safe on IA64, but is on i386. We use
123 // a C-style cast here to emphasize this is not legal C++.
124 return RawPatch((void*)(target_function),
125 (void*)(replacement_function),
126 (void**)(original_function_stub));
127 }
128
129 // Patches a named function imported from the named module using
130 // preamble patching. Uses RawPatch() to do the actual patching
131 // work.
132 //
133 // @param T The type of the function you are patching. Must
134 // exactly match the function you specify using module_name and
135 // function_name.
136 //
137 // @param module_name The name of the module from which the function
138 // is being imported. Note that the patch will fail if this module
139 // has not already been loaded into the current process.
140 //
141 // @param function_name The name of the function you wish to patch.
142 //
143 // @param replacement_function Your replacement function which
144 // will be called whenever code tries to call the original function.
145 //
146 // @param original_function_stub Pointer to memory that should receive a
147 // pointer that can be used (e.g. in the replacement function) to call the
148 // original function, or NULL to indicate failure.
149 //
150 // @return One of the EnSideStepError error codes; only SIDESTEP_SUCCESS
151 // indicates success.
152 template <class T>
153 static SideStepError Patch(LPCTSTR module_name,
154 LPCSTR function_name,
155 T replacement_function,
156 T* original_function_stub) {
157 ASSERT1(module_name && function_name);
158 if (!module_name || !function_name) {
159 ASSERT(false,
160 "You must specify a module name and function name.");
161 return SIDESTEP_INVALID_PARAMETER;
162 }
163 HMODULE module = ::GetModuleHandle(module_name);
164 ASSERT1(module != NULL);
165 if (!module) {
166 ASSERT(false, "Invalid module name.");
167 return SIDESTEP_NO_SUCH_MODULE;
168 }
169 FARPROC existing_function = ::GetProcAddress(module, function_name);
170 if (!existing_function) {
171 return SIDESTEP_NO_SUCH_FUNCTION;
172 }
173 // NOTE: casting from a function to a pointer is contra the C++
174 // spec. It's not safe on IA64, but is on i386. We use
175 // a C-style cast here to emphasize this is not legal C++.
176 return RawPatch((void*)existing_function, (void*)replacement_function,
177 (void**)(original_function_stub));
178 }
179
180 // Patches a function by overwriting its first few bytes with
181 // a jump to a different function. This is the "worker" function
182 // for each of the typesafe Patch() functions. In most cases,
183 // it is preferable to use the Patch() functions rather than
184 // this one as they do more checking at compile time.
185 //
186 // @param target_function A pointer to the function that should be
187 // patched.
188 //
189 // @param replacement_function A pointer to the function that should
190 // replace the target function. The replacement function must have
191 // exactly the same calling convention and parameters as the original
192 // function.
193 //
194 // @param original_function_stub Pointer to memory that should receive a
195 // pointer that can be used (e.g. in the replacement function) to call the
196 // original function, or NULL to indicate failure.
197 //
198 // @param original_function_stub Pointer to memory that should receive a
199 // pointer that can be used (e.g. in the replacement function) to call the
200 // original function, or NULL to indicate failure.
201 //
202 // @return One of the EnSideStepError error codes; only SIDESTEP_SUCCESS
203 // indicates success.
204 //
205 // @note The preamble-stub (the memory pointed to by
206 // *original_function_stub) is allocated on the heap, and (in
207 // production binaries) never destroyed, resulting in a memory leak. This
208 // will be the case until we implement safe unpatching of a method.
209 // However, it is quite difficult to unpatch a method (because other
210 // threads in the process may be using it) so we are leaving it for now.
211 // See however UnsafeUnpatch, which can be used for binaries where you
212 // know only one thread is running, e.g. unit tests.
213 static SideStepError RawPatch(void* target_function,
214 void* replacement_function,
215 void** original_function_stub);
216
217 // Unpatches target_function and deletes the stub that previously could be
218 // used to call the original version of the function.
219 //
220 // DELETES the stub that is passed to the function.
221 //
222 // @param target_function Pointer to the target function which was
223 // previously patched, i.e. a pointer which value should match the value
224 // of the symbol prior to patching it.
225 //
226 // @param replacement_function Pointer to the function target_function
227 // was patched to.
228 //
229 // @param original_function_stub Pointer to the stub returned when
230 // patching, that could be used to call the original version of the
231 // patched function. This function will also delete the stub, which after
232 // unpatching is useless.
233 //
234 // If your original call was
235 // origptr = Patch(VirtualAlloc, MyVirtualAlloc)
236 // then to undo it you would call
237 // Unpatch(VirtualAlloc, MyVirtualAlloc, origptr);
238 //
239 // @return One of the EnSideStepError error codes; only SIDESTEP_SUCCESS
240 // indicates success.
241 static SideStepError Unpatch(void* target_function,
242 void* replacement_function,
243 void* original_function_stub);
244
245 private:
246
247 // Patches a function by overwriting its first few bytes with
248 // a jump to a different function. This is similar to the RawPatch
249 // function except that it uses the stub allocated by the caller
250 // instead of allocating it.
251 //
252 // We call VirtualProtect to make the
253 // target function writable at least for the duration of the call.
254 //
255 // @param target_function A pointer to the function that should be
256 // patched.
257 //
258 // @param replacement_function A pointer to the function that should
259 // replace the target function. The replacement function must have
260 // exactly the same calling convention and parameters as the original
261 // function.
262 //
[email protected]f0a51fb52009-03-05 12:46:38263 // @param preamble_stub A pointer to a buffer where the preamble stub
initial.commit920c0912008-07-27 00:12:16264 // should be copied. The size of the buffer should be sufficient to
[email protected]f0a51fb52009-03-05 12:46:38265 // hold the preamble bytes.
initial.commit920c0912008-07-27 00:12:16266 //
267 // @param stub_size Size in bytes of the buffer allocated for the
268 // preamble_stub
269 //
270 // @param bytes_needed Pointer to a variable that receives the minimum
271 // number of bytes required for the stub. Can be set to NULL if you're
272 // not interested.
273 //
274 // @return An error code indicating the result of patching.
[email protected]f0a51fb52009-03-05 12:46:38275 static SideStepError RawPatchWithStubAndProtections(void* target_function,
276 void *replacement_function,
277 unsigned char* preamble_stub,
278 unsigned long stub_size,
initial.commit920c0912008-07-27 00:12:16279 unsigned long* bytes_needed);
280
281 // A helper function used by RawPatchWithStubAndProtections -- it does
282 // everything but the VirtualProtect wsork. Defined in
283 // preamble_patcher_with_stub.cc.
[email protected]f0a51fb52009-03-05 12:46:38284 static SideStepError RawPatchWithStub(void* target_function,
285 void *replacement_function,
286 unsigned char* preamble_stub,
287 unsigned long stub_size,
initial.commit920c0912008-07-27 00:12:16288 unsigned long* bytes_needed);
289};
290
291}; // namespace sidestep
292
293#endif // MEMORY_WATCHER_PREAMBLE_PATCHER_H__