Home | History | Annotate | Download | only in interception
      1 //===-- interception_linux.cc -----------------------------------*- C++ -*-===//
      2 //
      3 //                     The LLVM Compiler Infrastructure
      4 //
      5 // This file is distributed under the University of Illinois Open Source
      6 // License. See LICENSE.TXT for details.
      7 //
      8 //===----------------------------------------------------------------------===//
      9 //
     10 // This file is a part of AddressSanitizer, an address sanity checker.
     11 //
     12 // Windows-specific interception methods.
     13 //
     14 // This file is implementing several hooking techniques to intercept calls
     15 // to functions. The hooks are dynamically installed by modifying the assembly
     16 // code.
     17 //
     18 // The hooking techniques are making assumptions on the way the code is
     19 // generated and are safe under these assumptions.
     20 //
     21 // On 64-bit architecture, there is no direct 64-bit jump instruction. To allow
     22 // arbitrary branching on the whole memory space, the notion of trampoline
     23 // region is used. A trampoline region is a memory space withing 2G boundary
     24 // where it is safe to add custom assembly code to build 64-bit jumps.
     25 //
     26 // Hooking techniques
     27 // ==================
     28 //
     29 // 1) Detour
     30 //
     31 //    The Detour hooking technique is assuming the presence of an header with
     32 //    padding and an overridable 2-bytes nop instruction (mov edi, edi). The
     33 //    nop instruction can safely be replaced by a 2-bytes jump without any need
     34 //    to save the instruction. A jump to the target is encoded in the function
     35 //    header and the nop instruction is replaced by a short jump to the header.
     36 //
     37 //        head:  5 x nop                 head:  jmp <hook>
     38 //        func:  mov edi, edi    -->     func:  jmp short <head>
     39 //               [...]                   real:  [...]
     40 //
     41 //    This technique is only implemented on 32-bit architecture.
     42 //    Most of the time, Windows API are hookable with the detour technique.
     43 //
     44 // 2) Redirect Jump
     45 //
     46 //    The redirect jump is applicable when the first instruction is a direct
     47 //    jump. The instruction is replaced by jump to the hook.
     48 //
     49 //        func:  jmp <label>     -->     func:  jmp <hook>
     50 //
     51 //    On an 64-bit architecture, a trampoline is inserted.
     52 //
     53 //        func:  jmp <label>     -->     func:  jmp <tramp>
     54 //                                              [...]
     55 //
     56 //                                   [trampoline]
     57 //                                      tramp:  jmp QWORD [addr]
     58 //                                       addr:  .bytes <hook>
     59 //
     60 //    Note: <real> is equilavent to <label>.
     61 //
     62 // 3) HotPatch
     63 //
     64 //    The HotPatch hooking is assuming the presence of an header with padding
     65 //    and a first instruction with at least 2-bytes.
     66 //
     67 //    The reason to enforce the 2-bytes limitation is to provide the minimal
     68 //    space to encode a short jump. HotPatch technique is only rewriting one
     69 //    instruction to avoid breaking a sequence of instructions containing a
     70 //    branching target.
     71 //
     72 //    Assumptions are enforced by MSVC compiler by using the /HOTPATCH flag.
     73 //      see: https://msdn.microsoft.com/en-us/library/ms173507.aspx
     74 //    Default padding length is 5 bytes in 32-bits and 6 bytes in 64-bits.
     75 //
     76 //        head:   5 x nop                head:  jmp <hook>
     77 //        func:   <instr>        -->     func:  jmp short <head>
     78 //                [...]                  body:  [...]
     79 //
     80 //                                   [trampoline]
     81 //                                       real:  <instr>
     82 //                                              jmp <body>
     83 //
     84 //    On an 64-bit architecture:
     85 //
     86 //        head:   6 x nop                head:  jmp QWORD [addr1]
     87 //        func:   <instr>        -->     func:  jmp short <head>
     88 //                [...]                  body:  [...]
     89 //
     90 //                                   [trampoline]
     91 //                                      addr1:  .bytes <hook>
     92 //                                       real:  <instr>
     93 //                                              jmp QWORD [addr2]
     94 //                                      addr2:  .bytes <body>
     95 //
     96 // 4) Trampoline
     97 //
     98 //    The Trampoline hooking technique is the most aggressive one. It is
     99 //    assuming that there is a sequence of instructions that can be safely
    100 //    replaced by a jump (enough room and no incoming branches).
    101 //
    102 //    Unfortunately, these assumptions can't be safely presumed and code may
    103 //    be broken after hooking.
    104 //
    105 //        func:   <instr>        -->     func:  jmp <hook>
    106 //                <instr>
    107 //                [...]                  body:  [...]
    108 //
    109 //                                   [trampoline]
    110 //                                       real:  <instr>
    111 //                                              <instr>
    112 //                                              jmp <body>
    113 //
    114 //    On an 64-bit architecture:
    115 //
    116 //        func:   <instr>        -->     func:  jmp QWORD [addr1]
    117 //                <instr>
    118 //                [...]                  body:  [...]
    119 //
    120 //                                   [trampoline]
    121 //                                      addr1:  .bytes <hook>
    122 //                                       real:  <instr>
    123 //                                              <instr>
    124 //                                              jmp QWORD [addr2]
    125 //                                      addr2:  .bytes <body>
    126 //===----------------------------------------------------------------------===//
    127 
    128 #ifdef _WIN32
    129 
    130 #include "interception.h"
    131 #include "sanitizer_common/sanitizer_platform.h"
    132 #define WIN32_LEAN_AND_MEAN
    133 #include <windows.h>
    134 
    135 namespace __interception {
    136 
    137 static const int kAddressLength = FIRST_32_SECOND_64(4, 8);
    138 static const int kJumpInstructionLength = 5;
    139 static const int kShortJumpInstructionLength = 2;
    140 static const int kIndirectJumpInstructionLength = 6;
    141 static const int kBranchLength =
    142     FIRST_32_SECOND_64(kJumpInstructionLength, kIndirectJumpInstructionLength);
    143 static const int kDirectBranchLength = kBranchLength + kAddressLength;
    144 
    145 static void InterceptionFailed() {
    146   // Do we have a good way to abort with an error message here?
    147   __debugbreak();
    148 }
    149 
    150 static bool DistanceIsWithin2Gig(uptr from, uptr target) {
    151   if (from < target)
    152     return target - from <= (uptr)0x7FFFFFFFU;
    153   else
    154     return from - target <= (uptr)0x80000000U;
    155 }
    156 
    157 static uptr GetMmapGranularity() {
    158   SYSTEM_INFO si;
    159   GetSystemInfo(&si);
    160   return si.dwAllocationGranularity;
    161 }
    162 
    163 static uptr RoundUpTo(uptr size, uptr boundary) {
    164   return (size + boundary - 1) & ~(boundary - 1);
    165 }
    166 
    167 // FIXME: internal_str* and internal_mem* functions should be moved from the
    168 // ASan sources into interception/.
    169 
    170 static void _memset(void *p, int value, size_t sz) {
    171   for (size_t i = 0; i < sz; ++i)
    172     ((char*)p)[i] = (char)value;
    173 }
    174 
    175 static void _memcpy(void *dst, void *src, size_t sz) {
    176   char *dst_c = (char*)dst,
    177        *src_c = (char*)src;
    178   for (size_t i = 0; i < sz; ++i)
    179     dst_c[i] = src_c[i];
    180 }
    181 
    182 static bool ChangeMemoryProtection(
    183     uptr address, uptr size, DWORD *old_protection) {
    184   return ::VirtualProtect((void*)address, size,
    185                           PAGE_EXECUTE_READWRITE,
    186                           old_protection) != FALSE;
    187 }
    188 
    189 static bool RestoreMemoryProtection(
    190     uptr address, uptr size, DWORD old_protection) {
    191   DWORD unused;
    192   return ::VirtualProtect((void*)address, size,
    193                           old_protection,
    194                           &unused) != FALSE;
    195 }
    196 
    197 static bool IsMemoryPadding(uptr address, uptr size) {
    198   u8* function = (u8*)address;
    199   for (size_t i = 0; i < size; ++i)
    200     if (function[i] != 0x90 && function[i] != 0xCC)
    201       return false;
    202   return true;
    203 }
    204 
    205 static const u8 kHintNop10Bytes[] = {
    206   0x66, 0x66, 0x0F, 0x1F, 0x84,
    207   0x00, 0x00, 0x00, 0x00, 0x00
    208 };
    209 
    210 template<class T>
    211 static bool FunctionHasPrefix(uptr address, const T &pattern) {
    212   u8* function = (u8*)address - sizeof(pattern);
    213   for (size_t i = 0; i < sizeof(pattern); ++i)
    214     if (function[i] != pattern[i])
    215       return false;
    216   return true;
    217 }
    218 
    219 static bool FunctionHasPadding(uptr address, uptr size) {
    220   if (IsMemoryPadding(address - size, size))
    221     return true;
    222   if (size <= sizeof(kHintNop10Bytes) &&
    223       FunctionHasPrefix(address, kHintNop10Bytes))
    224     return true;
    225   return false;
    226 }
    227 
    228 static void WritePadding(uptr from, uptr size) {
    229   _memset((void*)from, 0xCC, (size_t)size);
    230 }
    231 
    232 static void CopyInstructions(uptr from, uptr to, uptr size) {
    233   _memcpy((void*)from, (void*)to, (size_t)size);
    234 }
    235 
    236 static void WriteJumpInstruction(uptr from, uptr target) {
    237   if (!DistanceIsWithin2Gig(from + kJumpInstructionLength, target))
    238     InterceptionFailed();
    239   ptrdiff_t offset = target - from - kJumpInstructionLength;
    240   *(u8*)from = 0xE9;
    241   *(u32*)(from + 1) = offset;
    242 }
    243 
    244 static void WriteShortJumpInstruction(uptr from, uptr target) {
    245   sptr offset = target - from - kShortJumpInstructionLength;
    246   if (offset < -128 || offset > 127)
    247     InterceptionFailed();
    248   *(u8*)from = 0xEB;
    249   *(u8*)(from + 1) = (u8)offset;
    250 }
    251 
    252 #if SANITIZER_WINDOWS64
    253 static void WriteIndirectJumpInstruction(uptr from, uptr indirect_target) {
    254   // jmp [rip + <offset>] = FF 25 <offset> where <offset> is a relative
    255   // offset.
    256   // The offset is the distance from then end of the jump instruction to the
    257   // memory location containing the targeted address. The displacement is still
    258   // 32-bit in x64, so indirect_target must be located within +/- 2GB range.
    259   int offset = indirect_target - from - kIndirectJumpInstructionLength;
    260   if (!DistanceIsWithin2Gig(from + kIndirectJumpInstructionLength,
    261                             indirect_target)) {
    262     InterceptionFailed();
    263   }
    264   *(u16*)from = 0x25FF;
    265   *(u32*)(from + 2) = offset;
    266 }
    267 #endif
    268 
    269 static void WriteBranch(
    270     uptr from, uptr indirect_target, uptr target) {
    271 #if SANITIZER_WINDOWS64
    272   WriteIndirectJumpInstruction(from, indirect_target);
    273   *(u64*)indirect_target = target;
    274 #else
    275   (void)indirect_target;
    276   WriteJumpInstruction(from, target);
    277 #endif
    278 }
    279 
    280 static void WriteDirectBranch(uptr from, uptr target) {
    281 #if SANITIZER_WINDOWS64
    282   // Emit an indirect jump through immediately following bytes:
    283   //   jmp [rip + kBranchLength]
    284   //   .quad <target>
    285   WriteBranch(from, from + kBranchLength, target);
    286 #else
    287   WriteJumpInstruction(from, target);
    288 #endif
    289 }
    290 
    291 struct TrampolineMemoryRegion {
    292   uptr content;
    293   uptr allocated_size;
    294   uptr max_size;
    295 };
    296 
    297 static const uptr kTrampolineScanLimitRange = 1 << 30;  // 1 gig
    298 static const int kMaxTrampolineRegion = 1024;
    299 static TrampolineMemoryRegion TrampolineRegions[kMaxTrampolineRegion];
    300 
    301 static void *AllocateTrampolineRegion(uptr image_address, size_t granularity) {
    302 #if SANITIZER_WINDOWS64
    303   uptr address = image_address;
    304   uptr scanned = 0;
    305   while (scanned < kTrampolineScanLimitRange) {
    306     MEMORY_BASIC_INFORMATION info;
    307     if (!::VirtualQuery((void*)address, &info, sizeof(info)))
    308       return nullptr;
    309 
    310     // Check whether a region can be allocated at |address|.
    311     if (info.State == MEM_FREE && info.RegionSize >= granularity) {
    312       void *page = ::VirtualAlloc((void*)RoundUpTo(address, granularity),
    313                                   granularity,
    314                                   MEM_RESERVE | MEM_COMMIT,
    315                                   PAGE_EXECUTE_READWRITE);
    316       return page;
    317     }
    318 
    319     // Move to the next region.
    320     address = (uptr)info.BaseAddress + info.RegionSize;
    321     scanned += info.RegionSize;
    322   }
    323   return nullptr;
    324 #else
    325   return ::VirtualAlloc(nullptr,
    326                         granularity,
    327                         MEM_RESERVE | MEM_COMMIT,
    328                         PAGE_EXECUTE_READWRITE);
    329 #endif
    330 }
    331 
    332 // Used by unittests to release mapped memory space.
    333 void TestOnlyReleaseTrampolineRegions() {
    334   for (size_t bucket = 0; bucket < kMaxTrampolineRegion; ++bucket) {
    335     TrampolineMemoryRegion *current = &TrampolineRegions[bucket];
    336     if (current->content == 0)
    337       return;
    338     ::VirtualFree((void*)current->content, 0, MEM_RELEASE);
    339     current->content = 0;
    340   }
    341 }
    342 
    343 static uptr AllocateMemoryForTrampoline(uptr image_address, size_t size) {
    344   // Find a region within 2G with enough space to allocate |size| bytes.
    345   TrampolineMemoryRegion *region = nullptr;
    346   for (size_t bucket = 0; bucket < kMaxTrampolineRegion; ++bucket) {
    347     TrampolineMemoryRegion* current = &TrampolineRegions[bucket];
    348     if (current->content == 0) {
    349       // No valid region found, allocate a new region.
    350       size_t bucket_size = GetMmapGranularity();
    351       void *content = AllocateTrampolineRegion(image_address, bucket_size);
    352       if (content == nullptr)
    353         return 0U;
    354 
    355       current->content = (uptr)content;
    356       current->allocated_size = 0;
    357       current->max_size = bucket_size;
    358       region = current;
    359       break;
    360     } else if (current->max_size - current->allocated_size > size) {
    361 #if SANITIZER_WINDOWS64
    362         // In 64-bits, the memory space must be allocated within 2G boundary.
    363         uptr next_address = current->content + current->allocated_size;
    364         if (next_address < image_address ||
    365             next_address - image_address >= 0x7FFF0000)
    366           continue;
    367 #endif
    368       // The space can be allocated in the current region.
    369       region = current;
    370       break;
    371     }
    372   }
    373 
    374   // Failed to find a region.
    375   if (region == nullptr)
    376     return 0U;
    377 
    378   // Allocate the space in the current region.
    379   uptr allocated_space = region->content + region->allocated_size;
    380   region->allocated_size += size;
    381   WritePadding(allocated_space, size);
    382 
    383   return allocated_space;
    384 }
    385 
    386 // Returns 0 on error.
    387 static size_t GetInstructionSize(uptr address) {
    388   switch (*(u8*)address) {
    389     case 0x90:  // 90 : nop
    390       return 1;
    391 
    392     case 0x50:  // push eax / rax
    393     case 0x51:  // push ecx / rcx
    394     case 0x52:  // push edx / rdx
    395     case 0x53:  // push ebx / rbx
    396     case 0x54:  // push esp / rsp
    397     case 0x55:  // push ebp / rbp
    398     case 0x56:  // push esi / rsi
    399     case 0x57:  // push edi / rdi
    400     case 0x5D:  // pop ebp / rbp
    401       return 1;
    402 
    403     case 0x6A:  // 6A XX = push XX
    404       return 2;
    405 
    406     case 0xb8:  // b8 XX XX XX XX : mov eax, XX XX XX XX
    407     case 0xB9:  // b9 XX XX XX XX : mov ecx, XX XX XX XX
    408     case 0xA1:  // A1 XX XX XX XX : mov eax, dword ptr ds:[XXXXXXXX]
    409       return 5;
    410 
    411     // Cannot overwrite control-instruction. Return 0 to indicate failure.
    412     case 0xE9:  // E9 XX XX XX XX : jmp <label>
    413     case 0xE8:  // E8 XX XX XX XX : call <func>
    414     case 0xC3:  // C3 : ret
    415     case 0xEB:  // EB XX : jmp XX (short jump)
    416     case 0x70:  // 7Y YY : jy XX (short conditional jump)
    417     case 0x71:
    418     case 0x72:
    419     case 0x73:
    420     case 0x74:
    421     case 0x75:
    422     case 0x76:
    423     case 0x77:
    424     case 0x78:
    425     case 0x79:
    426     case 0x7A:
    427     case 0x7B:
    428     case 0x7C:
    429     case 0x7D:
    430     case 0x7E:
    431     case 0x7F:
    432       return 0;
    433   }
    434 
    435   switch (*(u16*)(address)) {
    436     case 0xFF8B:  // 8B FF : mov edi, edi
    437     case 0xEC8B:  // 8B EC : mov ebp, esp
    438     case 0xc889:  // 89 C8 : mov eax, ecx
    439     case 0xC18B:  // 8B C1 : mov eax, ecx
    440     case 0xC033:  // 33 C0 : xor eax, eax
    441     case 0xC933:  // 33 C9 : xor ecx, ecx
    442     case 0xD233:  // 33 D2 : xor edx, edx
    443       return 2;
    444 
    445     // Cannot overwrite control-instruction. Return 0 to indicate failure.
    446     case 0x25FF:  // FF 25 XX XX XX XX : jmp [XXXXXXXX]
    447       return 0;
    448   }
    449 
    450 #if SANITIZER_WINDOWS64
    451   switch (*(u16*)address) {
    452     case 0x5040:  // push rax
    453     case 0x5140:  // push rcx
    454     case 0x5240:  // push rdx
    455     case 0x5340:  // push rbx
    456     case 0x5440:  // push rsp
    457     case 0x5540:  // push rbp
    458     case 0x5640:  // push rsi
    459     case 0x5740:  // push rdi
    460     case 0x5441:  // push r12
    461     case 0x5541:  // push r13
    462     case 0x5641:  // push r14
    463     case 0x5741:  // push r15
    464     case 0x9066:  // Two-byte NOP
    465       return 2;
    466   }
    467 
    468   switch (0x00FFFFFF & *(u32*)address) {
    469     case 0xe58948:    // 48 8b c4 : mov rbp, rsp
    470     case 0xc18b48:    // 48 8b c1 : mov rax, rcx
    471     case 0xc48b48:    // 48 8b c4 : mov rax, rsp
    472     case 0xd9f748:    // 48 f7 d9 : neg rcx
    473     case 0xd12b48:    // 48 2b d1 : sub rdx, rcx
    474     case 0x07c1f6:    // f6 c1 07 : test cl, 0x7
    475     case 0xc0854d:    // 4d 85 c0 : test r8, r8
    476     case 0xc2b60f:    // 0f b6 c2 : movzx eax, dl
    477     case 0xc03345:    // 45 33 c0 : xor r8d, r8d
    478     case 0xd98b4c:    // 4c 8b d9 : mov r11, rcx
    479     case 0xd28b4c:    // 4c 8b d2 : mov r10, rdx
    480     case 0xd2b60f:    // 0f b6 d2 : movzx edx, dl
    481     case 0xca2b48:    // 48 2b ca : sub rcx, rdx
    482     case 0x10b70f:    // 0f b7 10 : movzx edx, WORD PTR [rax]
    483     case 0xc00b4d:    // 3d 0b c0 : or r8, r8
    484     case 0xd18b48:    // 48 8b d1 : mov rdx, rcx
    485     case 0xdc8b4c:    // 4c 8b dc : mov r11,rsp
    486     case 0xd18b4c:    // 4c 8b d1 : mov r10, rcx
    487       return 3;
    488 
    489     case 0xec8348:    // 48 83 ec XX : sub rsp, XX
    490     case 0xf88349:    // 49 83 f8 XX : cmp r8, XX
    491     case 0x588948:    // 48 89 58 XX : mov QWORD PTR[rax + XX], rbx
    492       return 4;
    493 
    494     case 0x058b48:    // 48 8b 05 XX XX XX XX :
    495                       //   mov rax, QWORD PTR [rip + XXXXXXXX]
    496     case 0x25ff48:    // 48 ff 25 XX XX XX XX :
    497                       //   rex.W jmp QWORD PTR [rip + XXXXXXXX]
    498       return 7;
    499   }
    500 
    501   switch (*(u32*)(address)) {
    502     case 0x24448b48:  // 48 8b 44 24 XX : mov rax, qword ptr [rsp + XX]
    503     case 0x245c8948:  // 48 89 5c 24 XX : mov QWORD PTR [rsp + XX], rbx
    504     case 0x24748948:  // 48 89 74 24 XX : mov QWORD PTR [rsp + XX], rsi
    505       return 5;
    506   }
    507 
    508 #else
    509 
    510   switch (*(u16*)address) {
    511     case 0x458B:  // 8B 45 XX : mov eax, dword ptr [ebp + XX]
    512     case 0x5D8B:  // 8B 5D XX : mov ebx, dword ptr [ebp + XX]
    513     case 0x7D8B:  // 8B 7D XX : mov edi, dword ptr [ebp + XX]
    514     case 0xEC83:  // 83 EC XX : sub esp, XX
    515     case 0x75FF:  // FF 75 XX : push dword ptr [ebp + XX]
    516       return 3;
    517     case 0xC1F7:  // F7 C1 XX YY ZZ WW : test ecx, WWZZYYXX
    518     case 0x25FF:  // FF 25 XX YY ZZ WW : jmp dword ptr ds:[WWZZYYXX]
    519       return 6;
    520     case 0x3D83:  // 83 3D XX YY ZZ WW TT : cmp TT, WWZZYYXX
    521       return 7;
    522     case 0x7D83:  // 83 7D XX YY : cmp dword ptr [ebp + XX], YY
    523       return 4;
    524   }
    525 
    526   switch (0x00FFFFFF & *(u32*)address) {
    527     case 0x24448A:  // 8A 44 24 XX : mov eal, dword ptr [esp + XX]
    528     case 0x24448B:  // 8B 44 24 XX : mov eax, dword ptr [esp + XX]
    529     case 0x244C8B:  // 8B 4C 24 XX : mov ecx, dword ptr [esp + XX]
    530     case 0x24548B:  // 8B 54 24 XX : mov edx, dword ptr [esp + XX]
    531     case 0x24748B:  // 8B 74 24 XX : mov esi, dword ptr [esp + XX]
    532     case 0x247C8B:  // 8B 7C 24 XX : mov edi, dword ptr [esp + XX]
    533       return 4;
    534   }
    535 
    536   switch (*(u32*)address) {
    537     case 0x2444B60F:  // 0F B6 44 24 XX : movzx eax, byte ptr [esp + XX]
    538       return 5;
    539   }
    540 #endif
    541 
    542   // Unknown instruction!
    543   // FIXME: Unknown instruction failures might happen when we add a new
    544   // interceptor or a new compiler version. In either case, they should result
    545   // in visible and readable error messages. However, merely calling abort()
    546   // leads to an infinite recursion in CheckFailed.
    547   InterceptionFailed();
    548   return 0;
    549 }
    550 
    551 // Returns 0 on error.
    552 static size_t RoundUpToInstrBoundary(size_t size, uptr address) {
    553   size_t cursor = 0;
    554   while (cursor < size) {
    555     size_t instruction_size = GetInstructionSize(address + cursor);
    556     if (!instruction_size)
    557       return 0;
    558     cursor += instruction_size;
    559   }
    560   return cursor;
    561 }
    562 
    563 #if !SANITIZER_WINDOWS64
    564 bool OverrideFunctionWithDetour(
    565     uptr old_func, uptr new_func, uptr *orig_old_func) {
    566   const int kDetourHeaderLen = 5;
    567   const u16 kDetourInstruction = 0xFF8B;
    568 
    569   uptr header = (uptr)old_func - kDetourHeaderLen;
    570   uptr patch_length = kDetourHeaderLen + kShortJumpInstructionLength;
    571 
    572   // Validate that the function is hookable.
    573   if (*(u16*)old_func != kDetourInstruction ||
    574       !IsMemoryPadding(header, kDetourHeaderLen))
    575     return false;
    576 
    577   // Change memory protection to writable.
    578   DWORD protection = 0;
    579   if (!ChangeMemoryProtection(header, patch_length, &protection))
    580     return false;
    581 
    582   // Write a relative jump to the redirected function.
    583   WriteJumpInstruction(header, new_func);
    584 
    585   // Write the short jump to the function prefix.
    586   WriteShortJumpInstruction(old_func, header);
    587 
    588   // Restore previous memory protection.
    589   if (!RestoreMemoryProtection(header, patch_length, protection))
    590     return false;
    591 
    592   if (orig_old_func)
    593     *orig_old_func = old_func + kShortJumpInstructionLength;
    594 
    595   return true;
    596 }
    597 #endif
    598 
    599 bool OverrideFunctionWithRedirectJump(
    600     uptr old_func, uptr new_func, uptr *orig_old_func) {
    601   // Check whether the first instruction is a relative jump.
    602   if (*(u8*)old_func != 0xE9)
    603     return false;
    604 
    605   if (orig_old_func) {
    606     uptr relative_offset = *(u32*)(old_func + 1);
    607     uptr absolute_target = old_func + relative_offset + kJumpInstructionLength;
    608     *orig_old_func = absolute_target;
    609   }
    610 
    611 #if SANITIZER_WINDOWS64
    612   // If needed, get memory space for a trampoline jump.
    613   uptr trampoline = AllocateMemoryForTrampoline(old_func, kDirectBranchLength);
    614   if (!trampoline)
    615     return false;
    616   WriteDirectBranch(trampoline, new_func);
    617 #endif
    618 
    619   // Change memory protection to writable.
    620   DWORD protection = 0;
    621   if (!ChangeMemoryProtection(old_func, kJumpInstructionLength, &protection))
    622     return false;
    623 
    624   // Write a relative jump to the redirected function.
    625   WriteJumpInstruction(old_func, FIRST_32_SECOND_64(new_func, trampoline));
    626 
    627   // Restore previous memory protection.
    628   if (!RestoreMemoryProtection(old_func, kJumpInstructionLength, protection))
    629     return false;
    630 
    631   return true;
    632 }
    633 
    634 bool OverrideFunctionWithHotPatch(
    635     uptr old_func, uptr new_func, uptr *orig_old_func) {
    636   const int kHotPatchHeaderLen = kBranchLength;
    637 
    638   uptr header = (uptr)old_func - kHotPatchHeaderLen;
    639   uptr patch_length = kHotPatchHeaderLen + kShortJumpInstructionLength;
    640 
    641   // Validate that the function is hot patchable.
    642   size_t instruction_size = GetInstructionSize(old_func);
    643   if (instruction_size < kShortJumpInstructionLength ||
    644       !FunctionHasPadding(old_func, kHotPatchHeaderLen))
    645     return false;
    646 
    647   if (orig_old_func) {
    648     // Put the needed instructions into the trampoline bytes.
    649     uptr trampoline_length = instruction_size + kDirectBranchLength;
    650     uptr trampoline = AllocateMemoryForTrampoline(old_func, trampoline_length);
    651     if (!trampoline)
    652       return false;
    653     CopyInstructions(trampoline, old_func, instruction_size);
    654     WriteDirectBranch(trampoline + instruction_size,
    655                       old_func + instruction_size);
    656     *orig_old_func = trampoline;
    657   }
    658 
    659   // If needed, get memory space for indirect address.
    660   uptr indirect_address = 0;
    661 #if SANITIZER_WINDOWS64
    662   indirect_address = AllocateMemoryForTrampoline(old_func, kAddressLength);
    663   if (!indirect_address)
    664     return false;
    665 #endif
    666 
    667   // Change memory protection to writable.
    668   DWORD protection = 0;
    669   if (!ChangeMemoryProtection(header, patch_length, &protection))
    670     return false;
    671 
    672   // Write jumps to the redirected function.
    673   WriteBranch(header, indirect_address, new_func);
    674   WriteShortJumpInstruction(old_func, header);
    675 
    676   // Restore previous memory protection.
    677   if (!RestoreMemoryProtection(header, patch_length, protection))
    678     return false;
    679 
    680   return true;
    681 }
    682 
    683 bool OverrideFunctionWithTrampoline(
    684     uptr old_func, uptr new_func, uptr *orig_old_func) {
    685 
    686   size_t instructions_length = kBranchLength;
    687   size_t padding_length = 0;
    688   uptr indirect_address = 0;
    689 
    690   if (orig_old_func) {
    691     // Find out the number of bytes of the instructions we need to copy
    692     // to the trampoline.
    693     instructions_length = RoundUpToInstrBoundary(kBranchLength, old_func);
    694     if (!instructions_length)
    695       return false;
    696 
    697     // Put the needed instructions into the trampoline bytes.
    698     uptr trampoline_length = instructions_length + kDirectBranchLength;
    699     uptr trampoline = AllocateMemoryForTrampoline(old_func, trampoline_length);
    700     if (!trampoline)
    701       return false;
    702     CopyInstructions(trampoline, old_func, instructions_length);
    703     WriteDirectBranch(trampoline + instructions_length,
    704                       old_func + instructions_length);
    705     *orig_old_func = trampoline;
    706   }
    707 
    708 #if SANITIZER_WINDOWS64
    709   // Check if the targeted address can be encoded in the function padding.
    710   // Otherwise, allocate it in the trampoline region.
    711   if (IsMemoryPadding(old_func - kAddressLength, kAddressLength)) {
    712     indirect_address = old_func - kAddressLength;
    713     padding_length = kAddressLength;
    714   } else {
    715     indirect_address = AllocateMemoryForTrampoline(old_func, kAddressLength);
    716     if (!indirect_address)
    717       return false;
    718   }
    719 #endif
    720 
    721   // Change memory protection to writable.
    722   uptr patch_address = old_func - padding_length;
    723   uptr patch_length = instructions_length + padding_length;
    724   DWORD protection = 0;
    725   if (!ChangeMemoryProtection(patch_address, patch_length, &protection))
    726     return false;
    727 
    728   // Patch the original function.
    729   WriteBranch(old_func, indirect_address, new_func);
    730 
    731   // Restore previous memory protection.
    732   if (!RestoreMemoryProtection(patch_address, patch_length, protection))
    733     return false;
    734 
    735   return true;
    736 }
    737 
    738 bool OverrideFunction(
    739     uptr old_func, uptr new_func, uptr *orig_old_func) {
    740 #if !SANITIZER_WINDOWS64
    741   if (OverrideFunctionWithDetour(old_func, new_func, orig_old_func))
    742     return true;
    743 #endif
    744   if (OverrideFunctionWithRedirectJump(old_func, new_func, orig_old_func))
    745     return true;
    746   if (OverrideFunctionWithHotPatch(old_func, new_func, orig_old_func))
    747     return true;
    748   if (OverrideFunctionWithTrampoline(old_func, new_func, orig_old_func))
    749     return true;
    750   return false;
    751 }
    752 
    753 static void **InterestingDLLsAvailable() {
    754   static const char *InterestingDLLs[] = {
    755       "kernel32.dll",
    756       "msvcr110.dll",      // VS2012
    757       "msvcr120.dll",      // VS2013
    758       "vcruntime140.dll",  // VS2015
    759       "ucrtbase.dll",      // Universal CRT
    760       // NTDLL should go last as it exports some functions that we should
    761       // override in the CRT [presumably only used internally].
    762       "ntdll.dll", NULL};
    763   static void *result[ARRAY_SIZE(InterestingDLLs)] = { 0 };
    764   if (!result[0]) {
    765     for (size_t i = 0, j = 0; InterestingDLLs[i]; ++i) {
    766       if (HMODULE h = GetModuleHandleA(InterestingDLLs[i]))
    767         result[j++] = (void *)h;
    768     }
    769   }
    770   return &result[0];
    771 }
    772 
    773 namespace {
    774 // Utility for reading loaded PE images.
    775 template <typename T> class RVAPtr {
    776  public:
    777   RVAPtr(void *module, uptr rva)
    778       : ptr_(reinterpret_cast<T *>(reinterpret_cast<char *>(module) + rva)) {}
    779   operator T *() { return ptr_; }
    780   T *operator->() { return ptr_; }
    781   T *operator++() { return ++ptr_; }
    782 
    783  private:
    784   T *ptr_;
    785 };
    786 } // namespace
    787 
    788 // Internal implementation of GetProcAddress. At least since Windows 8,
    789 // GetProcAddress appears to initialize DLLs before returning function pointers
    790 // into them. This is problematic for the sanitizers, because they typically
    791 // want to intercept malloc *before* MSVCRT initializes. Our internal
    792 // implementation walks the export list manually without doing initialization.
    793 uptr InternalGetProcAddress(void *module, const char *func_name) {
    794   // Check that the module header is full and present.
    795   RVAPtr<IMAGE_DOS_HEADER> dos_stub(module, 0);
    796   RVAPtr<IMAGE_NT_HEADERS> headers(module, dos_stub->e_lfanew);
    797   if (!module || dos_stub->e_magic != IMAGE_DOS_SIGNATURE || // "MZ"
    798       headers->Signature != IMAGE_NT_SIGNATURE ||           // "PE\0\0"
    799       headers->FileHeader.SizeOfOptionalHeader <
    800           sizeof(IMAGE_OPTIONAL_HEADER)) {
    801     return 0;
    802   }
    803 
    804   IMAGE_DATA_DIRECTORY *export_directory =
    805       &headers->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT];
    806   RVAPtr<IMAGE_EXPORT_DIRECTORY> exports(module,
    807                                          export_directory->VirtualAddress);
    808   RVAPtr<DWORD> functions(module, exports->AddressOfFunctions);
    809   RVAPtr<DWORD> names(module, exports->AddressOfNames);
    810   RVAPtr<WORD> ordinals(module, exports->AddressOfNameOrdinals);
    811 
    812   for (DWORD i = 0; i < exports->NumberOfNames; i++) {
    813     RVAPtr<char> name(module, names[i]);
    814     if (!strcmp(func_name, name)) {
    815       DWORD index = ordinals[i];
    816       RVAPtr<char> func(module, functions[index]);
    817       return (uptr)(char *)func;
    818     }
    819   }
    820 
    821   return 0;
    822 }
    823 
    824 static bool GetFunctionAddressInDLLs(const char *func_name, uptr *func_addr) {
    825   *func_addr = 0;
    826   void **DLLs = InterestingDLLsAvailable();
    827   for (size_t i = 0; *func_addr == 0 && DLLs[i]; ++i)
    828     *func_addr = InternalGetProcAddress(DLLs[i], func_name);
    829   return (*func_addr != 0);
    830 }
    831 
    832 bool OverrideFunction(const char *name, uptr new_func, uptr *orig_old_func) {
    833   uptr orig_func;
    834   if (!GetFunctionAddressInDLLs(name, &orig_func))
    835     return false;
    836   return OverrideFunction(orig_func, new_func, orig_old_func);
    837 }
    838 
    839 bool OverrideImportedFunction(const char *module_to_patch,
    840                               const char *imported_module,
    841                               const char *function_name, uptr new_function,
    842                               uptr *orig_old_func) {
    843   HMODULE module = GetModuleHandleA(module_to_patch);
    844   if (!module)
    845     return false;
    846 
    847   // Check that the module header is full and present.
    848   RVAPtr<IMAGE_DOS_HEADER> dos_stub(module, 0);
    849   RVAPtr<IMAGE_NT_HEADERS> headers(module, dos_stub->e_lfanew);
    850   if (!module || dos_stub->e_magic != IMAGE_DOS_SIGNATURE || // "MZ"
    851       headers->Signature != IMAGE_NT_SIGNATURE ||            // "PE\0\0"
    852       headers->FileHeader.SizeOfOptionalHeader <
    853           sizeof(IMAGE_OPTIONAL_HEADER)) {
    854     return false;
    855   }
    856 
    857   IMAGE_DATA_DIRECTORY *import_directory =
    858       &headers->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT];
    859 
    860   // Iterate the list of imported DLLs. FirstThunk will be null for the last
    861   // entry.
    862   RVAPtr<IMAGE_IMPORT_DESCRIPTOR> imports(module,
    863                                           import_directory->VirtualAddress);
    864   for (; imports->FirstThunk != 0; ++imports) {
    865     RVAPtr<const char> modname(module, imports->Name);
    866     if (_stricmp(&*modname, imported_module) == 0)
    867       break;
    868   }
    869   if (imports->FirstThunk == 0)
    870     return false;
    871 
    872   // We have two parallel arrays: the import address table (IAT) and the table
    873   // of names. They start out containing the same data, but the loader rewrites
    874   // the IAT to hold imported addresses and leaves the name table in
    875   // OriginalFirstThunk alone.
    876   RVAPtr<IMAGE_THUNK_DATA> name_table(module, imports->OriginalFirstThunk);
    877   RVAPtr<IMAGE_THUNK_DATA> iat(module, imports->FirstThunk);
    878   for (; name_table->u1.Ordinal != 0; ++name_table, ++iat) {
    879     if (!IMAGE_SNAP_BY_ORDINAL(name_table->u1.Ordinal)) {
    880       RVAPtr<IMAGE_IMPORT_BY_NAME> import_by_name(
    881           module, name_table->u1.ForwarderString);
    882       const char *funcname = &import_by_name->Name[0];
    883       if (strcmp(funcname, function_name) == 0)
    884         break;
    885     }
    886   }
    887   if (name_table->u1.Ordinal == 0)
    888     return false;
    889 
    890   // Now we have the correct IAT entry. Do the swap. We have to make the page
    891   // read/write first.
    892   if (orig_old_func)
    893     *orig_old_func = iat->u1.AddressOfData;
    894   DWORD old_prot, unused_prot;
    895   if (!VirtualProtect(&iat->u1.AddressOfData, 4, PAGE_EXECUTE_READWRITE,
    896                       &old_prot))
    897     return false;
    898   iat->u1.AddressOfData = new_function;
    899   if (!VirtualProtect(&iat->u1.AddressOfData, 4, old_prot, &unused_prot))
    900     return false;  // Not clear if this failure bothers us.
    901   return true;
    902 }
    903 
    904 }  // namespace __interception
    905 
    906 #endif  // _WIN32
    907