Home | History | Annotate | Download | only in memory_watcher
      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 /*
      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 :)
     23 #define MAX_PREAMBLE_STUB_SIZE    (32)
     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.
     54 //
     55 // To patch a function, use either of the typesafe Patch() methods.  You
     56 // can unpatch a function using Unpatch().
     57 //
     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); }
     64 //
     65 // void MyPatchInitializingFunction() {
     66 //   original_func_stub = PreamblePatcher::Patch(
     67 //              MyTypesafeFunc, HookMyTypesafeFunc);
     68 //   if (!original_func_stub) {
     69 //     // ... error handling ...
     70 //   }
     71 //
     72 //   // ... continue - you have patched the function successfully ...
     73 // }
     74 // @endcode
     75 //
     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.
     90 //
     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   //
    263   // @param preamble_stub A pointer to a buffer where the preamble stub
    264   // should be copied. The size of the buffer should be sufficient to
    265   // hold the preamble bytes.
    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.
    275   static SideStepError RawPatchWithStubAndProtections(void* target_function,
    276                                           void *replacement_function,
    277                                           unsigned char* preamble_stub,
    278                                           unsigned long stub_size,
    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.
    284   static SideStepError RawPatchWithStub(void* target_function,
    285                                           void *replacement_function,
    286                                           unsigned char* preamble_stub,
    287                                           unsigned long stub_size,
    288                                           unsigned long* bytes_needed);
    289 };
    290 
    291 };  // namespace sidestep
    292 
    293 #endif  // MEMORY_WATCHER_PREAMBLE_PATCHER_H__
    294