Home | History | Annotate | Download | only in sidestep
      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 // Definition of PreamblePatcher
      6 
      7 #ifndef SANDBOX_SRC_SIDESTEP_PREAMBLE_PATCHER_H__
      8 #define SANDBOX_SRC_SIDESTEP_PREAMBLE_PATCHER_H__
      9 
     10 #include <stddef.h>
     11 
     12 namespace sidestep {
     13 
     14 // Maximum size of the preamble stub. We overwrite at least the first 5
     15 // bytes of the function. Considering the worst case scenario, we need 4
     16 // bytes + the max instruction size + 5 more bytes for our jump back to
     17 // the original code. With that in mind, 32 is a good number :)
     18 const size_t kMaxPreambleStubSize = 32;
     19 
     20 // Possible results of patching/unpatching
     21 enum SideStepError {
     22   SIDESTEP_SUCCESS = 0,
     23   SIDESTEP_INVALID_PARAMETER,
     24   SIDESTEP_INSUFFICIENT_BUFFER,
     25   SIDESTEP_JUMP_INSTRUCTION,
     26   SIDESTEP_FUNCTION_TOO_SMALL,
     27   SIDESTEP_UNSUPPORTED_INSTRUCTION,
     28   SIDESTEP_NO_SUCH_MODULE,
     29   SIDESTEP_NO_SUCH_FUNCTION,
     30   SIDESTEP_ACCESS_DENIED,
     31   SIDESTEP_UNEXPECTED,
     32 };
     33 
     34 // Implements a patching mechanism that overwrites the first few bytes of
     35 // a function preamble with a jump to our hook function, which is then
     36 // able to call the original function via a specially-made preamble-stub
     37 // that imitates the action of the original preamble.
     38 //
     39 // Note that there are a number of ways that this method of patching can
     40 // fail.  The most common are:
     41 //    - If there is a jump (jxx) instruction in the first 5 bytes of
     42 //    the function being patched, we cannot patch it because in the
     43 //    current implementation we do not know how to rewrite relative
     44 //    jumps after relocating them to the preamble-stub.  Note that
     45 //    if you really really need to patch a function like this, it
     46 //    would be possible to add this functionality (but at some cost).
     47 //    - If there is a return (ret) instruction in the first 5 bytes
     48 //    we cannot patch the function because it may not be long enough
     49 //    for the jmp instruction we use to inject our patch.
     50 //    - If there is another thread currently executing within the bytes
     51 //    that are copied to the preamble stub, it will crash in an undefined
     52 //    way.
     53 //
     54 // If you get any other error than the above, you're either pointing the
     55 // patcher at an invalid instruction (e.g. into the middle of a multi-
     56 // byte instruction, or not at memory containing executable instructions)
     57 // or, there may be a bug in the disassembler we use to find
     58 // instruction boundaries.
     59 class PreamblePatcher {
     60  public:
     61   // Patches target_function to point to replacement_function using a provided
     62   // preamble_stub of stub_size bytes.
     63   // Returns An error code indicating the result of patching.
     64   template <class T>
     65   static SideStepError Patch(T target_function, T replacement_function,
     66                              void* preamble_stub, size_t stub_size) {
     67     return RawPatchWithStub(target_function, replacement_function,
     68                             reinterpret_cast<unsigned char*>(preamble_stub),
     69                             stub_size, NULL);
     70   }
     71 
     72  private:
     73 
     74   // Patches a function by overwriting its first few bytes with
     75   // a jump to a different function.  This is similar to the RawPatch
     76   // function except that it uses the stub allocated by the caller
     77   // instead of allocating it.
     78   //
     79   // To use this function, you first have to call VirtualProtect to make the
     80   // target function writable at least for the duration of the call.
     81   //
     82   // target_function: A pointer to the function that should be
     83   // patched.
     84   //
     85   // replacement_function: A pointer to the function that should
     86   // replace the target function.  The replacement function must have
     87   // exactly the same calling convention and parameters as the original
     88   // function.
     89   //
     90   // preamble_stub: A pointer to a buffer where the preamble stub
     91   // should be copied. The size of the buffer should be sufficient to
     92   // hold the preamble bytes.
     93   //
     94   // stub_size: Size in bytes of the buffer allocated for the
     95   // preamble_stub
     96   //
     97   // bytes_needed: Pointer to a variable that receives the minimum
     98   // number of bytes required for the stub.  Can be set to NULL if you're
     99   // not interested.
    100   //
    101   // Returns An error code indicating the result of patching.
    102   static SideStepError RawPatchWithStub(void* target_function,
    103                                         void *replacement_function,
    104                                         unsigned char* preamble_stub,
    105                                         size_t stub_size,
    106                                         size_t* bytes_needed);
    107 };
    108 
    109 };  // namespace sidestep
    110 
    111 #endif  // SANDBOX_SRC_SIDESTEP_PREAMBLE_PATCHER_H__
    112