15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Definition of PreamblePatcher
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#ifndef SANDBOX_SRC_SIDESTEP_PREAMBLE_PATCHER_H__
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define SANDBOX_SRC_SIDESTEP_PREAMBLE_PATCHER_H__
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
10868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include <stddef.h>
11868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace sidestep {
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Maximum size of the preamble stub. We overwrite at least the first 5
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// bytes of the function. Considering the worst case scenario, we need 4
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// bytes + the max instruction size + 5 more bytes for our jump back to
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// the original code. With that in mind, 32 is a good number :)
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const size_t kMaxPreambleStubSize = 32;
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Possible results of patching/unpatching
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)enum SideStepError {
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SIDESTEP_SUCCESS = 0,
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SIDESTEP_INVALID_PARAMETER,
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SIDESTEP_INSUFFICIENT_BUFFER,
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SIDESTEP_JUMP_INSTRUCTION,
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SIDESTEP_FUNCTION_TOO_SMALL,
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SIDESTEP_UNSUPPORTED_INSTRUCTION,
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SIDESTEP_NO_SUCH_MODULE,
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SIDESTEP_NO_SUCH_FUNCTION,
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SIDESTEP_ACCESS_DENIED,
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SIDESTEP_UNEXPECTED,
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Implements a patching mechanism that overwrites the first few bytes of
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// a function preamble with a jump to our hook function, which is then
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// able to call the original function via a specially-made preamble-stub
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// that imitates the action of the original preamble.
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Note that there are a number of ways that this method of patching can
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// fail.  The most common are:
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//    - If there is a jump (jxx) instruction in the first 5 bytes of
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//    the function being patched, we cannot patch it because in the
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//    current implementation we do not know how to rewrite relative
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//    jumps after relocating them to the preamble-stub.  Note that
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//    if you really really need to patch a function like this, it
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//    would be possible to add this functionality (but at some cost).
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//    - If there is a return (ret) instruction in the first 5 bytes
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//    we cannot patch the function because it may not be long enough
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//    for the jmp instruction we use to inject our patch.
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//    - If there is another thread currently executing within the bytes
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//    that are copied to the preamble stub, it will crash in an undefined
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//    way.
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// If you get any other error than the above, you're either pointing the
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// patcher at an invalid instruction (e.g. into the middle of a multi-
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// byte instruction, or not at memory containing executable instructions)
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// or, there may be a bug in the disassembler we use to find
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// instruction boundaries.
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class PreamblePatcher {
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Patches target_function to point to replacement_function using a provided
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // preamble_stub of stub_size bytes.
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Returns An error code indicating the result of patching.
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  template <class T>
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static SideStepError Patch(T target_function, T replacement_function,
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                             void* preamble_stub, size_t stub_size) {
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return RawPatchWithStub(target_function, replacement_function,
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            reinterpret_cast<unsigned char*>(preamble_stub),
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            stub_size, NULL);
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Patches a function by overwriting its first few bytes with
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // a jump to a different function.  This is similar to the RawPatch
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // function except that it uses the stub allocated by the caller
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // instead of allocating it.
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // To use this function, you first have to call VirtualProtect to make the
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // target function writable at least for the duration of the call.
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // target_function: A pointer to the function that should be
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // patched.
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // replacement_function: A pointer to the function that should
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // replace the target function.  The replacement function must have
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // exactly the same calling convention and parameters as the original
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // function.
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // preamble_stub: A pointer to a buffer where the preamble stub
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // should be copied. The size of the buffer should be sufficient to
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // hold the preamble bytes.
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // stub_size: Size in bytes of the buffer allocated for the
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // preamble_stub
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // bytes_needed: Pointer to a variable that receives the minimum
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // number of bytes required for the stub.  Can be set to NULL if you're
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // not interested.
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  //
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Returns An error code indicating the result of patching.
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  static SideStepError RawPatchWithStub(void* target_function,
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                        void *replacement_function,
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                        unsigned char* preamble_stub,
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                        size_t stub_size,
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                        size_t* bytes_needed);
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};  // namespace sidestep
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif  // SANDBOX_SRC_SIDESTEP_PREAMBLE_PATCHER_H__
112