| OLD | NEW |
| 1 /* Copyright (c) 2007, Google Inc. | 1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. |
| 2 * All rights reserved. | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 * | 3 // found in the LICENSE file. |
| 4 * Redistribution and use in source and binary forms, with or without | |
| 5 * modification, are permitted provided that the following conditions are | |
| 6 * met: | |
| 7 * | |
| 8 * * Redistributions of source code must retain the above copyright | |
| 9 * notice, this list of conditions and the following disclaimer. | |
| 10 * * Redistributions in binary form must reproduce the above | |
| 11 * copyright notice, this list of conditions and the following disclaimer | |
| 12 * in the documentation and/or other materials provided with the | |
| 13 * distribution. | |
| 14 * * Neither the name of Google Inc. nor the names of its | |
| 15 * contributors may be used to endorse or promote products derived from | |
| 16 * this software without specific prior written permission. | |
| 17 * | |
| 18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | |
| 19 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | |
| 20 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR | |
| 21 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | |
| 22 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, | |
| 23 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT | |
| 24 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | |
| 25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | |
| 26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | |
| 27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | |
| 28 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | |
| 29 * | |
| 30 * --- | |
| 31 * | |
| 32 * Implementation of PreamblePatcher | |
| 33 */ | |
| 34 | 4 |
| 35 #include "preamble_patcher.h" | 5 #include "preamble_patcher.h" |
| 36 #include "memory_hook.h" | 6 #include "memory_hook.h" |
| 37 #include "mini_disassembler.h" | 7 #include "mini_disassembler.h" |
| 38 | 8 |
| 39 // compatibility shims | 9 // compatibility shims |
| 40 #include "base/logging.h" | 10 #include "base/logging.h" |
| 41 | 11 |
| 42 // Definitions of assembly statements we need | 12 // Definitions of assembly statements we need |
| 43 #define ASM_JMP32REL 0xE9 | 13 #define ASM_JMP32REL 0xE9 |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 84 ASSERT(false, "Failed to restore protection to target function."); | 54 ASSERT(false, "Failed to restore protection to target function."); |
| 85 // We must not return an error here because the function has actually | 55 // We must not return an error here because the function has actually |
| 86 // been patched, and returning an error would likely cause our client | 56 // been patched, and returning an error would likely cause our client |
| 87 // code not to unpatch it. So we just keep going. | 57 // code not to unpatch it. So we just keep going. |
| 88 } | 58 } |
| 89 | 59 |
| 90 // Flush the instruction cache to make sure the processor doesn't execute the | 60 // Flush the instruction cache to make sure the processor doesn't execute the |
| 91 // old version of the instructions (before our patch). | 61 // old version of the instructions (before our patch). |
| 92 // | 62 // |
| 93 // FlushInstructionCache is actually a no-op at least on single-processor | 63 // FlushInstructionCache is actually a no-op at least on single-processor |
| 94 // XP machines. I'm not sure why this is so, but it is, yet I want to keep th
e | 64 // XP machines. I'm not sure why this is so, but it is, yet I want to keep |
| 95 // call to the API here for correctness in case there is a difference in | 65 // the call to the API here for correctness in case there is a difference in |
| 96 // some variants of Windows/hardware. | 66 // some variants of Windows/hardware. |
| 97 succeeded = ::FlushInstructionCache(::GetCurrentProcess(), | 67 succeeded = ::FlushInstructionCache(::GetCurrentProcess(), |
| 98 target_function, | 68 target_function, |
| 99 MAX_PREAMBLE_STUB_SIZE); | 69 MAX_PREAMBLE_STUB_SIZE); |
| 100 if (!succeeded) { | 70 if (!succeeded) { |
| 101 ASSERT(false, "Failed to flush instruction cache."); | 71 ASSERT(false, "Failed to flush instruction cache."); |
| 102 // We must not return an error here because the function has actually | 72 // We must not return an error here because the function has actually |
| 103 // been patched, and returning an error would likely cause our client | 73 // been patched, and returning an error would likely cause our client |
| 104 // code not to unpatch it. So we just keep going. | 74 // code not to unpatch it. So we just keep going. |
| 105 } | 75 } |
| (...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 149 delete[] preamble_stub; | 119 delete[] preamble_stub; |
| 150 return error_code; | 120 return error_code; |
| 151 } | 121 } |
| 152 | 122 |
| 153 *original_function_stub = reinterpret_cast<void*>(preamble_stub); | 123 *original_function_stub = reinterpret_cast<void*>(preamble_stub); |
| 154 | 124 |
| 155 // NOTE: For hooking malloc/free, we don't want to use streams which | 125 // NOTE: For hooking malloc/free, we don't want to use streams which |
| 156 // allocate. Basically, we've hooked malloc, but not necessarily | 126 // allocate. Basically, we've hooked malloc, but not necessarily |
| 157 // hooked free yet. To do anything which uses the heap could crash | 127 // hooked free yet. To do anything which uses the heap could crash |
| 158 // with a mismatched malloc/free! | 128 // with a mismatched malloc/free! |
| 159 //LOG(INFO) << "PreamblePatcher::RawPatch successfully patched 0x" << | 129 //VLOG(1) << "PreamblePatcher::RawPatch successfully patched 0x" |
| 160 // target_function; | 130 // << target_function; |
| 161 | 131 |
| 162 return SIDESTEP_SUCCESS; | 132 return SIDESTEP_SUCCESS; |
| 163 } | 133 } |
| 164 | 134 |
| 165 SideStepError PreamblePatcher::Unpatch(void* target_function, | 135 SideStepError PreamblePatcher::Unpatch(void* target_function, |
| 166 void* replacement_function, | 136 void* replacement_function, |
| 167 void* original_function_stub) { | 137 void* original_function_stub) { |
| 168 ASSERT1(target_function && original_function_stub); | 138 ASSERT1(target_function && original_function_stub); |
| 169 if (!target_function || !original_function_stub) { | 139 if (!target_function || !original_function_stub) { |
| 170 return SIDESTEP_INVALID_PARAMETER; | 140 return SIDESTEP_INVALID_PARAMETER; |
| 171 } | 141 } |
| 172 | 142 |
| 173 // We disassemble the preamble of the _stub_ to see how many bytes we | 143 // We disassemble the preamble of the _stub_ to see how many bytes we |
| 174 // originally copied to the stub. | 144 // originally copied to the stub. |
| 175 MiniDisassembler disassembler; | 145 MiniDisassembler disassembler; |
| 176 unsigned int preamble_bytes = 0; | 146 unsigned int preamble_bytes = 0; |
| 177 while (preamble_bytes < 5) { | 147 while (preamble_bytes < 5) { |
| 178 InstructionType instruction_type = | 148 InstructionType instruction_type = disassembler.Disassemble( |
| 179 disassembler.Disassemble( | 149 reinterpret_cast<unsigned char*>(original_function_stub) + |
| 180 reinterpret_cast<unsigned char*>(original_function_stub) + preamble_byte
s, | 150 preamble_bytes, preamble_bytes); |
| 181 preamble_bytes); | |
| 182 if (IT_GENERIC != instruction_type) { | 151 if (IT_GENERIC != instruction_type) { |
| 183 ASSERT(false, "Should only have generic instructions in stub!!"); | 152 ASSERT(false, "Should only have generic instructions in stub!!"); |
| 184 return SIDESTEP_UNSUPPORTED_INSTRUCTION; | 153 return SIDESTEP_UNSUPPORTED_INSTRUCTION; |
| 185 } | 154 } |
| 186 } | 155 } |
| 187 | 156 |
| 188 // Before unpatching, target_function should be a JMP to | 157 // Before unpatching, target_function should be a JMP to |
| 189 // replacement_function. If it's not, then either it's an error, or | 158 // replacement_function. If it's not, then either it's an error, or |
| 190 // we're falling into the case where the original instruction was a | 159 // we're falling into the case where the original instruction was a |
| 191 // JMP, and we patched the jumped_to address rather than the JMP | 160 // JMP, and we patched the jumped_to address rather than the JMP |
| (...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 244 // | 213 // |
| 245 // See comment on FlushInstructionCache elsewhere in this file. | 214 // See comment on FlushInstructionCache elsewhere in this file. |
| 246 succeeded = ::FlushInstructionCache(::GetCurrentProcess(), | 215 succeeded = ::FlushInstructionCache(::GetCurrentProcess(), |
| 247 target, | 216 target, |
| 248 MAX_PREAMBLE_STUB_SIZE); | 217 MAX_PREAMBLE_STUB_SIZE); |
| 249 if (!succeeded) { | 218 if (!succeeded) { |
| 250 ASSERT(false, "Failed to flush instruction cache."); | 219 ASSERT(false, "Failed to flush instruction cache."); |
| 251 return SIDESTEP_UNEXPECTED; | 220 return SIDESTEP_UNEXPECTED; |
| 252 } | 221 } |
| 253 | 222 |
| 254 LOG(INFO) << "PreamblePatcher::Unpatch successfully unpatched 0x" << | 223 VLOG(1) << "PreamblePatcher::Unpatch successfully unpatched 0x" |
| 255 target_function; | 224 << target_function; |
| 256 return SIDESTEP_SUCCESS; | 225 return SIDESTEP_SUCCESS; |
| 257 } | 226 } |
| 258 | 227 |
| 259 }; // namespace sidestep | 228 }; // namespace sidestep |
| OLD | NEW |