[email protected] | 648d386 | 2012-01-24 16:19:36 | [diff] [blame] | 1 | // 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.commit | 920c091 | 2008-07-27 00:12:16 | [diff] [blame] | 6 | * 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] | f0a51fb5 | 2009-03-05 12:46:38 | [diff] [blame] | 23 | #define MAX_PREAMBLE_STUB_SIZE (32) |
initial.commit | 920c091 | 2008-07-27 00:12:16 | [diff] [blame] | 24 | |
| 25 | namespace sidestep { |
| 26 | |
| 27 | // Possible results of patching/unpatching |
| 28 | enum 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] | f0a51fb5 | 2009-03-05 12:46:38 | [diff] [blame] | 54 | // |
initial.commit | 920c091 | 2008-07-27 00:12:16 | [diff] [blame] | 55 | // To patch a function, use either of the typesafe Patch() methods. You |
| 56 | // can unpatch a function using Unpatch(). |
[email protected] | f0a51fb5 | 2009-03-05 12:46:38 | [diff] [blame] | 57 | // |
initial.commit | 920c091 | 2008-07-27 00:12:16 | [diff] [blame] | 58 | // 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] | f0a51fb5 | 2009-03-05 12:46:38 | [diff] [blame] | 64 | // |
initial.commit | 920c091 | 2008-07-27 00:12:16 | [diff] [blame] | 65 | // void MyPatchInitializingFunction() { |
| 66 | // original_func_stub = PreamblePatcher::Patch( |
| 67 | // MyTypesafeFunc, HookMyTypesafeFunc); |
| 68 | // if (!original_func_stub) { |
| 69 | // // ... error handling ... |
| 70 | // } |
[email protected] | f0a51fb5 | 2009-03-05 12:46:38 | [diff] [blame] | 71 | // |
initial.commit | 920c091 | 2008-07-27 00:12:16 | [diff] [blame] | 72 | // // ... continue - you have patched the function successfully ... |
| 73 | // } |
| 74 | // @endcode |
[email protected] | f0a51fb5 | 2009-03-05 12:46:38 | [diff] [blame] | 75 | // |
initial.commit | 920c091 | 2008-07-27 00:12:16 | [diff] [blame] | 76 | // 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] | f0a51fb5 | 2009-03-05 12:46:38 | [diff] [blame] | 90 | // |
initial.commit | 920c091 | 2008-07-27 00:12:16 | [diff] [blame] | 91 | // 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. |
| 102 | class 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] | f0a51fb5 | 2009-03-05 12:46:38 | [diff] [blame] | 263 | // @param preamble_stub A pointer to a buffer where the preamble stub |
initial.commit | 920c091 | 2008-07-27 00:12:16 | [diff] [blame] | 264 | // should be copied. The size of the buffer should be sufficient to |
[email protected] | f0a51fb5 | 2009-03-05 12:46:38 | [diff] [blame] | 265 | // hold the preamble bytes. |
initial.commit | 920c091 | 2008-07-27 00:12:16 | [diff] [blame] | 266 | // |
| 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] | f0a51fb5 | 2009-03-05 12:46:38 | [diff] [blame] | 275 | static SideStepError RawPatchWithStubAndProtections(void* target_function, |
| 276 | void *replacement_function, |
| 277 | unsigned char* preamble_stub, |
| 278 | unsigned long stub_size, |
initial.commit | 920c091 | 2008-07-27 00:12:16 | [diff] [blame] | 279 | 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] | f0a51fb5 | 2009-03-05 12:46:38 | [diff] [blame] | 284 | static SideStepError RawPatchWithStub(void* target_function, |
| 285 | void *replacement_function, |
| 286 | unsigned char* preamble_stub, |
| 287 | unsigned long stub_size, |
initial.commit | 920c091 | 2008-07-27 00:12:16 | [diff] [blame] | 288 | unsigned long* bytes_needed); |
| 289 | }; |
| 290 | |
| 291 | }; // namespace sidestep |
| 292 | |
| 293 | #endif // MEMORY_WATCHER_PREAMBLE_PATCHER_H__ |