|
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__ |