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> Patch(T target_function,T replacement_function,void * preamble_stub,size_t stub_size)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