diff options
Diffstat (limited to 'sandbox/src/sidestep/preamble_patcher_with_stub.cpp')
-rw-r--r-- | sandbox/src/sidestep/preamble_patcher_with_stub.cpp | 179 |
1 files changed, 0 insertions, 179 deletions
diff --git a/sandbox/src/sidestep/preamble_patcher_with_stub.cpp b/sandbox/src/sidestep/preamble_patcher_with_stub.cpp deleted file mode 100644 index 4bdd79c2..0000000 --- a/sandbox/src/sidestep/preamble_patcher_with_stub.cpp +++ /dev/null @@ -1,179 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -// Implementation of PreamblePatcher - -#include "sandbox/src/sidestep/preamble_patcher.h" - -#include "sandbox/src/sandbox_nt_util.h" -#include "sandbox/src/sidestep/mini_disassembler.h" - -// Definitions of assembly statements we need -#define ASM_JMP32REL 0xE9 -#define ASM_INT3 0xCC - -namespace { - -// Very basic memcpy. We are copying 4 to 12 bytes most of the time, so there -// is no attempt to optimize this code or have a general purpose function. -// We don't want to call the crt from this code. -inline void* RawMemcpy(void* destination, const void* source, size_t bytes) { - const char* from = reinterpret_cast<const char*>(source); - char* to = reinterpret_cast<char*>(destination); - - for (size_t i = 0; i < bytes ; i++) - to[i] = from[i]; - - return destination; -} - -// Very basic memset. We are filling 1 to 7 bytes most of the time, so there -// is no attempt to optimize this code or have a general purpose function. -// We don't want to call the crt from this code. -inline void* RawMemset(void* destination, int value, size_t bytes) { - char* to = reinterpret_cast<char*>(destination); - - for (size_t i = 0; i < bytes ; i++) - to[i] = static_cast<char>(value); - - return destination; -} - -} // namespace - -#define ASSERT(a, b) DCHECK_NT(a) - -namespace sidestep { - -SideStepError PreamblePatcher::RawPatchWithStub( - void* target_function, - void* replacement_function, - unsigned char* preamble_stub, - size_t stub_size, - size_t* bytes_needed) { - if ((NULL == target_function) || - (NULL == replacement_function) || - (NULL == preamble_stub)) { - ASSERT(false, (L"Invalid parameters - either pTargetFunction or " - L"pReplacementFunction or pPreambleStub were NULL.")); - return SIDESTEP_INVALID_PARAMETER; - } - - // TODO(V7:joi) Siggi and I just had a discussion and decided that both - // patching and unpatching are actually unsafe. We also discussed a - // method of making it safe, which is to freeze all other threads in the - // process, check their thread context to see if their eip is currently - // inside the block of instructions we need to copy to the stub, and if so - // wait a bit and try again, then unfreeze all threads once we've patched. - // Not implementing this for now since we're only using SideStep for unit - // testing, but if we ever use it for production code this is what we - // should do. - // - // NOTE: Stoyan suggests we can write 8 or even 10 bytes atomically using - // FPU instructions, and on newer processors we could use cmpxchg8b or - // cmpxchg16b. So it might be possible to do the patching/unpatching - // atomically and avoid having to freeze other threads. Note though, that - // doing it atomically does not help if one of the other threads happens - // to have its eip in the middle of the bytes you change while you change - // them. - unsigned char* target = reinterpret_cast<unsigned char*>(target_function); - - // Let's disassemble the preamble of the target function to see if we can - // patch, and to see how much of the preamble we need to take. We need 5 - // bytes for our jmp instruction, so let's find the minimum number of - // instructions to get 5 bytes. - MiniDisassembler disassembler; - unsigned int preamble_bytes = 0; - while (preamble_bytes < 5) { - InstructionType instruction_type = - disassembler.Disassemble(target + preamble_bytes, &preamble_bytes); - if (IT_JUMP == instruction_type) { - ASSERT(false, (L"Unable to patch because there is a jump instruction " - L"in the first 5 bytes.")); - return SIDESTEP_JUMP_INSTRUCTION; - } else if (IT_RETURN == instruction_type) { - ASSERT(false, (L"Unable to patch because function is too short")); - return SIDESTEP_FUNCTION_TOO_SMALL; - } else if (IT_GENERIC != instruction_type) { - ASSERT(false, (L"Disassembler encountered unsupported instruction " - L"(either unused or unknown")); - return SIDESTEP_UNSUPPORTED_INSTRUCTION; - } - } - - if (NULL != bytes_needed) - *bytes_needed = preamble_bytes + 5; - - // Inv: preamble_bytes is the number of bytes (at least 5) that we need to - // take from the preamble to have whole instructions that are 5 bytes or more - // in size total. The size of the stub required is cbPreamble + size of - // jmp (5) - if (preamble_bytes + 5 > stub_size) { - NOTREACHED_NT(); - return SIDESTEP_INSUFFICIENT_BUFFER; - } - - // First, copy the preamble that we will overwrite. - RawMemcpy(reinterpret_cast<void*>(preamble_stub), - reinterpret_cast<void*>(target), preamble_bytes); - - // Now, make a jmp instruction to the rest of the target function (minus the - // preamble bytes we moved into the stub) and copy it into our preamble-stub. - // find address to jump to, relative to next address after jmp instruction -#pragma warning(push) -#pragma warning(disable:4244) - // This assignment generates a warning because it is 32 bit specific. - int relative_offset_to_target_rest - = ((reinterpret_cast<unsigned char*>(target) + preamble_bytes) - - (preamble_stub + preamble_bytes + 5)); -#pragma warning(pop) - // jmp (Jump near, relative, displacement relative to next instruction) - preamble_stub[preamble_bytes] = ASM_JMP32REL; - // copy the address - RawMemcpy(reinterpret_cast<void*>(preamble_stub + preamble_bytes + 1), - reinterpret_cast<void*>(&relative_offset_to_target_rest), 4); - - // Inv: preamble_stub points to assembly code that will execute the - // original function by first executing the first cbPreamble bytes of the - // preamble, then jumping to the rest of the function. - - // Overwrite the first 5 bytes of the target function with a jump to our - // replacement function. - // (Jump near, relative, displacement relative to next instruction) - target[0] = ASM_JMP32REL; - - // Find offset from instruction after jmp, to the replacement function. -#pragma warning(push) -#pragma warning(disable:4244) - int offset_to_replacement_function = - reinterpret_cast<unsigned char*>(replacement_function) - - reinterpret_cast<unsigned char*>(target) - 5; -#pragma warning(pop) - // complete the jmp instruction - RawMemcpy(reinterpret_cast<void*>(target + 1), - reinterpret_cast<void*>(&offset_to_replacement_function), 4); - // Set any remaining bytes that were moved to the preamble-stub to INT3 so - // as not to cause confusion (otherwise you might see some strange - // instructions if you look at the disassembly, or even invalid - // instructions). Also, by doing this, we will break into the debugger if - // some code calls into this portion of the code. If this happens, it - // means that this function cannot be patched using this patcher without - // further thought. - if (preamble_bytes > 5) { - RawMemset(reinterpret_cast<void*>(target + 5), ASM_INT3, - preamble_bytes - 5); - } - - // Inv: The memory pointed to by target_function now points to a relative - // jump instruction that jumps over to the preamble_stub. The preamble - // stub contains the first stub_size bytes of the original target - // function's preamble code, followed by a relative jump back to the next - // instruction after the first cbPreamble bytes. - - return SIDESTEP_SUCCESS; -} - -}; // namespace sidestep - -#undef ASSERT |