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 12namespace 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 :) 18const size_t kMaxPreambleStubSize = 32; 19 20// Possible results of patching/unpatching 21enum 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. 59class 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