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)// Implementation of PreamblePatcher 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "sandbox/win/src/sidestep/preamble_patcher.h" 85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "sandbox/win/src/sandbox_nt_util.h" 105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "sandbox/win/src/sidestep/mini_disassembler.h" 115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Definitions of assembly statements we need 135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define ASM_JMP32REL 0xE9 145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define ASM_INT3 0xCC 155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace { 175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Very basic memcpy. We are copying 4 to 12 bytes most of the time, so there 195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// is no attempt to optimize this code or have a general purpose function. 205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// We don't want to call the crt from this code. 215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)inline void* RawMemcpy(void* destination, const void* source, size_t bytes) { 225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const char* from = reinterpret_cast<const char*>(source); 235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) char* to = reinterpret_cast<char*>(destination); 245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (size_t i = 0; i < bytes ; i++) 265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) to[i] = from[i]; 275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return destination; 295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Very basic memset. We are filling 1 to 7 bytes most of the time, so there 325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// is no attempt to optimize this code or have a general purpose function. 335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// We don't want to call the crt from this code. 345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)inline void* RawMemset(void* destination, int value, size_t bytes) { 355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) char* to = reinterpret_cast<char*>(destination); 365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (size_t i = 0; i < bytes ; i++) 385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) to[i] = static_cast<char>(value); 395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return destination; 415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace 445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#define ASSERT(a, b) DCHECK_NT(a) 465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace sidestep { 485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)SideStepError PreamblePatcher::RawPatchWithStub( 505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void* target_function, 515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) void* replacement_function, 525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) unsigned char* preamble_stub, 535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) size_t stub_size, 545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) size_t* bytes_needed) { 555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if ((NULL == target_function) || 565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (NULL == replacement_function) || 575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (NULL == preamble_stub)) { 585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ASSERT(false, (L"Invalid parameters - either pTargetFunction or " 595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) L"pReplacementFunction or pPreambleStub were NULL.")); 605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return SIDESTEP_INVALID_PARAMETER; 615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // TODO(V7:joi) Siggi and I just had a discussion and decided that both 645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // patching and unpatching are actually unsafe. We also discussed a 655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // method of making it safe, which is to freeze all other threads in the 665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // process, check their thread context to see if their eip is currently 675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // inside the block of instructions we need to copy to the stub, and if so 685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // wait a bit and try again, then unfreeze all threads once we've patched. 695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Not implementing this for now since we're only using SideStep for unit 705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // testing, but if we ever use it for production code this is what we 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // should do. 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // NOTE: Stoyan suggests we can write 8 or even 10 bytes atomically using 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // FPU instructions, and on newer processors we could use cmpxchg8b or 755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // cmpxchg16b. So it might be possible to do the patching/unpatching 765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // atomically and avoid having to freeze other threads. Note though, that 775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // doing it atomically does not help if one of the other threads happens 785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // to have its eip in the middle of the bytes you change while you change 795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // them. 805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) unsigned char* target = reinterpret_cast<unsigned char*>(target_function); 815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Let's disassemble the preamble of the target function to see if we can 835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // patch, and to see how much of the preamble we need to take. We need 5 845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // bytes for our jmp instruction, so let's find the minimum number of 855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // instructions to get 5 bytes. 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) MiniDisassembler disassembler; 875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) unsigned int preamble_bytes = 0; 885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) while (preamble_bytes < 5) { 895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) InstructionType instruction_type = 905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) disassembler.Disassemble(target + preamble_bytes, &preamble_bytes); 915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (IT_JUMP == instruction_type) { 925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ASSERT(false, (L"Unable to patch because there is a jump instruction " 935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) L"in the first 5 bytes.")); 945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return SIDESTEP_JUMP_INSTRUCTION; 955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else if (IT_RETURN == instruction_type) { 965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ASSERT(false, (L"Unable to patch because function is too short")); 975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return SIDESTEP_FUNCTION_TOO_SMALL; 985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else if (IT_GENERIC != instruction_type) { 995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ASSERT(false, (L"Disassembler encountered unsupported instruction " 1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) L"(either unused or unknown")); 1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return SIDESTEP_UNSUPPORTED_INSTRUCTION; 1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (NULL != bytes_needed) 1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *bytes_needed = preamble_bytes + 5; 1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Inv: preamble_bytes is the number of bytes (at least 5) that we need to 1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // take from the preamble to have whole instructions that are 5 bytes or more 1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // in size total. The size of the stub required is cbPreamble + size of 1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // jmp (5) 1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (preamble_bytes + 5 > stub_size) { 1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NOTREACHED_NT(); 1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return SIDESTEP_INSUFFICIENT_BUFFER; 1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // First, copy the preamble that we will overwrite. 1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RawMemcpy(reinterpret_cast<void*>(preamble_stub), 1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) reinterpret_cast<void*>(target), preamble_bytes); 1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Now, make a jmp instruction to the rest of the target function (minus the 1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // preamble bytes we moved into the stub) and copy it into our preamble-stub. 1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // find address to jump to, relative to next address after jmp instruction 1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#pragma warning(push) 1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#pragma warning(disable:4244) 1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // This assignment generates a warning because it is 32 bit specific. 1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int relative_offset_to_target_rest 1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) = ((reinterpret_cast<unsigned char*>(target) + preamble_bytes) - 1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) (preamble_stub + preamble_bytes + 5)); 1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#pragma warning(pop) 1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // jmp (Jump near, relative, displacement relative to next instruction) 1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) preamble_stub[preamble_bytes] = ASM_JMP32REL; 1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // copy the address 1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RawMemcpy(reinterpret_cast<void*>(preamble_stub + preamble_bytes + 1), 1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) reinterpret_cast<void*>(&relative_offset_to_target_rest), 4); 1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Inv: preamble_stub points to assembly code that will execute the 1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // original function by first executing the first cbPreamble bytes of the 1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // preamble, then jumping to the rest of the function. 1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Overwrite the first 5 bytes of the target function with a jump to our 1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // replacement function. 1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // (Jump near, relative, displacement relative to next instruction) 1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) target[0] = ASM_JMP32REL; 1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Find offset from instruction after jmp, to the replacement function. 1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#pragma warning(push) 1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#pragma warning(disable:4244) 1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int offset_to_replacement_function = 1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) reinterpret_cast<unsigned char*>(replacement_function) - 1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) reinterpret_cast<unsigned char*>(target) - 5; 1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#pragma warning(pop) 1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // complete the jmp instruction 1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RawMemcpy(reinterpret_cast<void*>(target + 1), 1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) reinterpret_cast<void*>(&offset_to_replacement_function), 4); 1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Set any remaining bytes that were moved to the preamble-stub to INT3 so 1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // as not to cause confusion (otherwise you might see some strange 1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // instructions if you look at the disassembly, or even invalid 1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // instructions). Also, by doing this, we will break into the debugger if 1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // some code calls into this portion of the code. If this happens, it 1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // means that this function cannot be patched using this patcher without 1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // further thought. 1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (preamble_bytes > 5) { 1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) RawMemset(reinterpret_cast<void*>(target + 5), ASM_INT3, 1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) preamble_bytes - 5); 1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Inv: The memory pointed to by target_function now points to a relative 1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // jump instruction that jumps over to the preamble_stub. The preamble 1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // stub contains the first stub_size bytes of the original target 1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // function's preamble code, followed by a relative jump back to the next 1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // instruction after the first cbPreamble bytes. 1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return SIDESTEP_SUCCESS; 1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; // namespace sidestep 1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#undef ASSERT 180