1 //===-- interception_win_test.cpp -----------------------------------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // This file is a part of ThreadSanitizer/AddressSanitizer runtime.
10 // Tests for interception_win.h.
11 //
12 //===----------------------------------------------------------------------===//
13 #include "interception/interception.h"
14 
15 #include "gtest/gtest.h"
16 
17 // Too slow for debug build
18 #if !SANITIZER_DEBUG
19 #if SANITIZER_WINDOWS
20 
21 #define WIN32_LEAN_AND_MEAN
22 #include <windows.h>
23 
24 namespace __interception {
25 namespace {
26 
27 enum FunctionPrefixKind {
28   FunctionPrefixNone,
29   FunctionPrefixPadding,
30   FunctionPrefixHotPatch,
31   FunctionPrefixDetour,
32 };
33 
34 typedef bool (*TestOverrideFunction)(uptr, uptr, uptr*);
35 typedef int (*IdentityFunction)(int);
36 
37 #if SANITIZER_WINDOWS64
38 
39 const u8 kIdentityCodeWithPrologue[] = {
40     0x55,                   // push        rbp
41     0x48, 0x89, 0xE5,       // mov         rbp,rsp
42     0x8B, 0xC1,             // mov         eax,ecx
43     0x5D,                   // pop         rbp
44     0xC3,                   // ret
45 };
46 
47 const u8 kIdentityCodeWithPushPop[] = {
48     0x55,                   // push        rbp
49     0x48, 0x89, 0xE5,       // mov         rbp,rsp
50     0x53,                   // push        rbx
51     0x50,                   // push        rax
52     0x58,                   // pop         rax
53     0x8B, 0xC1,             // mov         rax,rcx
54     0x5B,                   // pop         rbx
55     0x5D,                   // pop         rbp
56     0xC3,                   // ret
57 };
58 
59 const u8 kIdentityTwiceOffset = 16;
60 const u8 kIdentityTwice[] = {
61     0x55,                   // push        rbp
62     0x48, 0x89, 0xE5,       // mov         rbp,rsp
63     0x8B, 0xC1,             // mov         eax,ecx
64     0x5D,                   // pop         rbp
65     0xC3,                   // ret
66     0x90, 0x90, 0x90, 0x90,
67     0x90, 0x90, 0x90, 0x90,
68     0x55,                   // push        rbp
69     0x48, 0x89, 0xE5,       // mov         rbp,rsp
70     0x8B, 0xC1,             // mov         eax,ecx
71     0x5D,                   // pop         rbp
72     0xC3,                   // ret
73 };
74 
75 const u8 kIdentityCodeWithMov[] = {
76     0x89, 0xC8,             // mov         eax, ecx
77     0xC3,                   // ret
78 };
79 
80 const u8 kIdentityCodeWithJump[] = {
81     0xE9, 0x04, 0x00, 0x00,
82     0x00,                   // jmp + 4
83     0xCC, 0xCC, 0xCC, 0xCC,
84     0x89, 0xC8,             // mov         eax, ecx
85     0xC3,                   // ret
86 };
87 
88 #else
89 
90 const u8 kIdentityCodeWithPrologue[] = {
91     0x55,                   // push        ebp
92     0x8B, 0xEC,             // mov         ebp,esp
93     0x8B, 0x45, 0x08,       // mov         eax,dword ptr [ebp + 8]
94     0x5D,                   // pop         ebp
95     0xC3,                   // ret
96 };
97 
98 const u8 kIdentityCodeWithPushPop[] = {
99     0x55,                   // push        ebp
100     0x8B, 0xEC,             // mov         ebp,esp
101     0x53,                   // push        ebx
102     0x50,                   // push        eax
103     0x58,                   // pop         eax
104     0x8B, 0x45, 0x08,       // mov         eax,dword ptr [ebp + 8]
105     0x5B,                   // pop         ebx
106     0x5D,                   // pop         ebp
107     0xC3,                   // ret
108 };
109 
110 const u8 kIdentityTwiceOffset = 8;
111 const u8 kIdentityTwice[] = {
112     0x55,                   // push        ebp
113     0x8B, 0xEC,             // mov         ebp,esp
114     0x8B, 0x45, 0x08,       // mov         eax,dword ptr [ebp + 8]
115     0x5D,                   // pop         ebp
116     0xC3,                   // ret
117     0x55,                   // push        ebp
118     0x8B, 0xEC,             // mov         ebp,esp
119     0x8B, 0x45, 0x08,       // mov         eax,dword ptr [ebp + 8]
120     0x5D,                   // pop         ebp
121     0xC3,                   // ret
122 };
123 
124 const u8 kIdentityCodeWithMov[] = {
125     0x8B, 0x44, 0x24, 0x04, // mov         eax,dword ptr [esp + 4]
126     0xC3,                   // ret
127 };
128 
129 const u8 kIdentityCodeWithJump[] = {
130     0xE9, 0x04, 0x00, 0x00,
131     0x00,                   // jmp + 4
132     0xCC, 0xCC, 0xCC, 0xCC,
133     0x8B, 0x44, 0x24, 0x04, // mov         eax,dword ptr [esp + 4]
134     0xC3,                   // ret
135 };
136 
137 #endif
138 
139 const u8 kPatchableCode1[] = {
140     0xB8, 0x4B, 0x00, 0x00, 0x00,   // mov eax,4B
141     0x33, 0xC9,                     // xor ecx,ecx
142     0xC3,                           // ret
143 };
144 
145 const u8 kPatchableCode2[] = {
146     0x55,                           // push ebp
147     0x8B, 0xEC,                     // mov ebp,esp
148     0x33, 0xC0,                     // xor eax,eax
149     0x5D,                           // pop ebp
150     0xC3,                           // ret
151 };
152 
153 const u8 kPatchableCode3[] = {
154     0x55,                           // push ebp
155     0x8B, 0xEC,                     // mov ebp,esp
156     0x6A, 0x00,                     // push 0
157     0xE8, 0x3D, 0xFF, 0xFF, 0xFF,   // call <func>
158 };
159 
160 const u8 kPatchableCode4[] = {
161     0xE9, 0xCC, 0xCC, 0xCC, 0xCC,   // jmp <label>
162     0x90, 0x90, 0x90, 0x90,
163 };
164 
165 const u8 kPatchableCode5[] = {
166     0x55,                                      // push    ebp
167     0x8b, 0xec,                                // mov     ebp,esp
168     0x8d, 0xa4, 0x24, 0x30, 0xfd, 0xff, 0xff,  // lea     esp,[esp-2D0h]
169     0x54,                                      // push    esp
170 };
171 
172 #if SANITIZER_WINDOWS64
173 u8 kLoadGlobalCode[] = {
174   0x8B, 0x05, 0x00, 0x00, 0x00, 0x00, // mov    eax [rip + global]
175   0xC3,                               // ret
176 };
177 #endif
178 
179 const u8 kUnpatchableCode1[] = {
180     0xC3,                           // ret
181 };
182 
183 const u8 kUnpatchableCode2[] = {
184     0x33, 0xC9,                     // xor ecx,ecx
185     0xC3,                           // ret
186 };
187 
188 const u8 kUnpatchableCode3[] = {
189     0x75, 0xCC,                     // jne <label>
190     0x33, 0xC9,                     // xor ecx,ecx
191     0xC3,                           // ret
192 };
193 
194 const u8 kUnpatchableCode4[] = {
195     0x74, 0xCC,                     // jne <label>
196     0x33, 0xC9,                     // xor ecx,ecx
197     0xC3,                           // ret
198 };
199 
200 const u8 kUnpatchableCode5[] = {
201     0xEB, 0x02,                     // jmp <label>
202     0x33, 0xC9,                     // xor ecx,ecx
203     0xC3,                           // ret
204 };
205 
206 const u8 kUnpatchableCode6[] = {
207     0xE8, 0xCC, 0xCC, 0xCC, 0xCC,   // call <func>
208     0x90, 0x90, 0x90, 0x90,
209 };
210 
211 const u8 kPatchableCode6[] = {
212     0x48, 0x89, 0x54, 0x24, 0xBB, // mov QWORD PTR [rsp + 0xBB], rdx
213     0x33, 0xC9,                   // xor ecx,ecx
214     0xC3,                         // ret
215 };
216 
217 const u8 kPatchableCode7[] = {
218     0x4c, 0x89, 0x4c, 0x24, 0xBB,  // mov QWORD PTR [rsp + 0xBB], r9
219     0x33, 0xC9,                   // xor ecx,ecx
220     0xC3,                         // ret
221 };
222 
223 const u8 kPatchableCode8[] = {
224     0x4c, 0x89, 0x44, 0x24, 0xBB, // mov QWORD PTR [rsp + 0xBB], r8
225     0x33, 0xC9,                   // xor ecx,ecx
226     0xC3,                         // ret
227 };
228 
229 // A buffer holding the dynamically generated code under test.
230 u8* ActiveCode;
231 const size_t ActiveCodeLength = 4096;
232 
233 int InterceptorFunction(int x);
234 
235 /// Allocate code memory more than 2GB away from Base.
AllocateCode2GBAway(u8 * Base)236 u8 *AllocateCode2GBAway(u8 *Base) {
237   // Find a 64K aligned location after Base plus 2GB.
238   size_t TwoGB = 0x80000000;
239   size_t AllocGranularity = 0x10000;
240   Base = (u8 *)((((uptr)Base + TwoGB + AllocGranularity)) & ~(AllocGranularity - 1));
241 
242   // Check if that location is free, and if not, loop over regions until we find
243   // one that is.
244   MEMORY_BASIC_INFORMATION mbi = {};
245   while (sizeof(mbi) == VirtualQuery(Base, &mbi, sizeof(mbi))) {
246     if (mbi.State & MEM_FREE) break;
247     Base += mbi.RegionSize;
248   }
249 
250   // Allocate one RWX page at the free location.
251   return (u8 *)::VirtualAlloc(Base, ActiveCodeLength, MEM_COMMIT | MEM_RESERVE,
252                               PAGE_EXECUTE_READWRITE);
253 }
254 
255 template<class T>
LoadActiveCode(const T & code,uptr * entry_point,FunctionPrefixKind prefix_kind=FunctionPrefixNone)256 static void LoadActiveCode(
257     const T &code,
258     uptr *entry_point,
259     FunctionPrefixKind prefix_kind = FunctionPrefixNone) {
260   if (ActiveCode == nullptr) {
261     ActiveCode = AllocateCode2GBAway((u8*)&InterceptorFunction);
262     ASSERT_NE(ActiveCode, nullptr) << "failed to allocate RWX memory 2GB away";
263   }
264 
265   size_t position = 0;
266 
267   // Add padding to avoid memory violation when scanning the prefix.
268   for (int i = 0; i < 16; ++i)
269     ActiveCode[position++] = 0xC3;  // Instruction 'ret'.
270 
271   // Add function padding.
272   size_t padding = 0;
273   if (prefix_kind == FunctionPrefixPadding)
274     padding = 16;
275   else if (prefix_kind == FunctionPrefixDetour ||
276            prefix_kind == FunctionPrefixHotPatch)
277     padding = FIRST_32_SECOND_64(5, 6);
278   // Insert |padding| instructions 'nop'.
279   for (size_t i = 0; i < padding; ++i)
280     ActiveCode[position++] = 0x90;
281 
282   // Keep track of the entry point.
283   *entry_point = (uptr)&ActiveCode[position];
284 
285   // Add the detour instruction (i.e. mov edi, edi)
286   if (prefix_kind == FunctionPrefixDetour) {
287 #if SANITIZER_WINDOWS64
288     // Note that "mov edi,edi" is NOP in 32-bit only, in 64-bit it clears
289     // higher bits of RDI.
290     // Use 66,90H as NOP for Windows64.
291     ActiveCode[position++] = 0x66;
292     ActiveCode[position++] = 0x90;
293 #else
294     // mov edi,edi.
295     ActiveCode[position++] = 0x8B;
296     ActiveCode[position++] = 0xFF;
297 #endif
298 
299   }
300 
301   // Copy the function body.
302   for (size_t i = 0; i < sizeof(T); ++i)
303     ActiveCode[position++] = code[i];
304 }
305 
306 int InterceptorFunctionCalled;
307 IdentityFunction InterceptedRealFunction;
308 
InterceptorFunction(int x)309 int InterceptorFunction(int x) {
310   ++InterceptorFunctionCalled;
311   return InterceptedRealFunction(x);
312 }
313 
314 }  // namespace
315 
316 // Tests for interception_win.h
TEST(Interception,InternalGetProcAddress)317 TEST(Interception, InternalGetProcAddress) {
318   HMODULE ntdll_handle = ::GetModuleHandle("ntdll");
319   ASSERT_NE(nullptr, ntdll_handle);
320   uptr DbgPrint_expected = (uptr)::GetProcAddress(ntdll_handle, "DbgPrint");
321   uptr isdigit_expected = (uptr)::GetProcAddress(ntdll_handle, "isdigit");
322   uptr DbgPrint_adddress = InternalGetProcAddress(ntdll_handle, "DbgPrint");
323   uptr isdigit_address = InternalGetProcAddress(ntdll_handle, "isdigit");
324 
325   EXPECT_EQ(DbgPrint_expected, DbgPrint_adddress);
326   EXPECT_EQ(isdigit_expected, isdigit_address);
327   EXPECT_NE(DbgPrint_adddress, isdigit_address);
328 }
329 
330 template<class T>
TestIdentityFunctionPatching(const T & code,TestOverrideFunction override,FunctionPrefixKind prefix_kind=FunctionPrefixNone)331 static void TestIdentityFunctionPatching(
332     const T &code,
333     TestOverrideFunction override,
334     FunctionPrefixKind prefix_kind = FunctionPrefixNone) {
335   uptr identity_address;
336   LoadActiveCode(code, &identity_address, prefix_kind);
337   IdentityFunction identity = (IdentityFunction)identity_address;
338 
339   // Validate behavior before dynamic patching.
340   InterceptorFunctionCalled = 0;
341   EXPECT_EQ(0, identity(0));
342   EXPECT_EQ(42, identity(42));
343   EXPECT_EQ(0, InterceptorFunctionCalled);
344 
345   // Patch the function.
346   uptr real_identity_address = 0;
347   bool success = override(identity_address,
348                          (uptr)&InterceptorFunction,
349                          &real_identity_address);
350   EXPECT_TRUE(success);
351   EXPECT_NE(0U, real_identity_address);
352   IdentityFunction real_identity = (IdentityFunction)real_identity_address;
353   InterceptedRealFunction = real_identity;
354 
355   // Don't run tests if hooking failed or the real function is not valid.
356   if (!success || !real_identity_address)
357     return;
358 
359   // Calling the redirected function.
360   InterceptorFunctionCalled = 0;
361   EXPECT_EQ(0, identity(0));
362   EXPECT_EQ(42, identity(42));
363   EXPECT_EQ(2, InterceptorFunctionCalled);
364 
365   // Calling the real function.
366   InterceptorFunctionCalled = 0;
367   EXPECT_EQ(0, real_identity(0));
368   EXPECT_EQ(42, real_identity(42));
369   EXPECT_EQ(0, InterceptorFunctionCalled);
370 
371   TestOnlyReleaseTrampolineRegions();
372 }
373 
374 #if !SANITIZER_WINDOWS64
TEST(Interception,OverrideFunctionWithDetour)375 TEST(Interception, OverrideFunctionWithDetour) {
376   TestOverrideFunction override = OverrideFunctionWithDetour;
377   FunctionPrefixKind prefix = FunctionPrefixDetour;
378   TestIdentityFunctionPatching(kIdentityCodeWithPrologue, override, prefix);
379   TestIdentityFunctionPatching(kIdentityCodeWithPushPop, override, prefix);
380   TestIdentityFunctionPatching(kIdentityCodeWithMov, override, prefix);
381   TestIdentityFunctionPatching(kIdentityCodeWithJump, override, prefix);
382 }
383 #endif  // !SANITIZER_WINDOWS64
384 
TEST(Interception,OverrideFunctionWithRedirectJump)385 TEST(Interception, OverrideFunctionWithRedirectJump) {
386   TestOverrideFunction override = OverrideFunctionWithRedirectJump;
387   TestIdentityFunctionPatching(kIdentityCodeWithJump, override);
388 }
389 
TEST(Interception,OverrideFunctionWithHotPatch)390 TEST(Interception, OverrideFunctionWithHotPatch) {
391   TestOverrideFunction override = OverrideFunctionWithHotPatch;
392   FunctionPrefixKind prefix = FunctionPrefixHotPatch;
393   TestIdentityFunctionPatching(kIdentityCodeWithMov, override, prefix);
394 }
395 
TEST(Interception,OverrideFunctionWithTrampoline)396 TEST(Interception, OverrideFunctionWithTrampoline) {
397   TestOverrideFunction override = OverrideFunctionWithTrampoline;
398   FunctionPrefixKind prefix = FunctionPrefixNone;
399   TestIdentityFunctionPatching(kIdentityCodeWithPrologue, override, prefix);
400   TestIdentityFunctionPatching(kIdentityCodeWithPushPop, override, prefix);
401 
402   prefix = FunctionPrefixPadding;
403   TestIdentityFunctionPatching(kIdentityCodeWithPrologue, override, prefix);
404   TestIdentityFunctionPatching(kIdentityCodeWithPushPop, override, prefix);
405 }
406 
TEST(Interception,OverrideFunction)407 TEST(Interception, OverrideFunction) {
408   TestOverrideFunction override = OverrideFunction;
409   FunctionPrefixKind prefix = FunctionPrefixNone;
410   TestIdentityFunctionPatching(kIdentityCodeWithPrologue, override, prefix);
411   TestIdentityFunctionPatching(kIdentityCodeWithPushPop, override, prefix);
412   TestIdentityFunctionPatching(kIdentityCodeWithJump, override, prefix);
413 
414   prefix = FunctionPrefixPadding;
415   TestIdentityFunctionPatching(kIdentityCodeWithPrologue, override, prefix);
416   TestIdentityFunctionPatching(kIdentityCodeWithPushPop, override, prefix);
417   TestIdentityFunctionPatching(kIdentityCodeWithMov, override, prefix);
418   TestIdentityFunctionPatching(kIdentityCodeWithJump, override, prefix);
419 
420   prefix = FunctionPrefixHotPatch;
421   TestIdentityFunctionPatching(kIdentityCodeWithPrologue, override, prefix);
422   TestIdentityFunctionPatching(kIdentityCodeWithPushPop, override, prefix);
423   TestIdentityFunctionPatching(kIdentityCodeWithMov, override, prefix);
424   TestIdentityFunctionPatching(kIdentityCodeWithJump, override, prefix);
425 
426   prefix = FunctionPrefixDetour;
427   TestIdentityFunctionPatching(kIdentityCodeWithPrologue, override, prefix);
428   TestIdentityFunctionPatching(kIdentityCodeWithPushPop, override, prefix);
429   TestIdentityFunctionPatching(kIdentityCodeWithMov, override, prefix);
430   TestIdentityFunctionPatching(kIdentityCodeWithJump, override, prefix);
431 }
432 
433 template<class T>
TestIdentityFunctionMultiplePatching(const T & code,TestOverrideFunction override,FunctionPrefixKind prefix_kind=FunctionPrefixNone)434 static void TestIdentityFunctionMultiplePatching(
435     const T &code,
436     TestOverrideFunction override,
437     FunctionPrefixKind prefix_kind = FunctionPrefixNone) {
438   uptr identity_address;
439   LoadActiveCode(code, &identity_address, prefix_kind);
440 
441   // Patch the function.
442   uptr real_identity_address = 0;
443   bool success = override(identity_address,
444                           (uptr)&InterceptorFunction,
445                           &real_identity_address);
446   EXPECT_TRUE(success);
447   EXPECT_NE(0U, real_identity_address);
448 
449   // Re-patching the function should not work.
450   success = override(identity_address,
451                      (uptr)&InterceptorFunction,
452                      &real_identity_address);
453   EXPECT_FALSE(success);
454 
455   TestOnlyReleaseTrampolineRegions();
456 }
457 
TEST(Interception,OverrideFunctionMultiplePatchingIsFailing)458 TEST(Interception, OverrideFunctionMultiplePatchingIsFailing) {
459 #if !SANITIZER_WINDOWS64
460   TestIdentityFunctionMultiplePatching(kIdentityCodeWithPrologue,
461                                        OverrideFunctionWithDetour,
462                                        FunctionPrefixDetour);
463 #endif
464 
465   TestIdentityFunctionMultiplePatching(kIdentityCodeWithMov,
466                                        OverrideFunctionWithHotPatch,
467                                        FunctionPrefixHotPatch);
468 
469   TestIdentityFunctionMultiplePatching(kIdentityCodeWithPushPop,
470                                        OverrideFunctionWithTrampoline,
471                                        FunctionPrefixPadding);
472 }
473 
TEST(Interception,OverrideFunctionTwice)474 TEST(Interception, OverrideFunctionTwice) {
475   uptr identity_address1;
476   LoadActiveCode(kIdentityTwice, &identity_address1);
477   uptr identity_address2 = identity_address1 + kIdentityTwiceOffset;
478   IdentityFunction identity1 = (IdentityFunction)identity_address1;
479   IdentityFunction identity2 = (IdentityFunction)identity_address2;
480 
481   // Patch the two functions.
482   uptr real_identity_address = 0;
483   EXPECT_TRUE(OverrideFunction(identity_address1,
484                                (uptr)&InterceptorFunction,
485                                &real_identity_address));
486   EXPECT_TRUE(OverrideFunction(identity_address2,
487                                (uptr)&InterceptorFunction,
488                                &real_identity_address));
489   IdentityFunction real_identity = (IdentityFunction)real_identity_address;
490   InterceptedRealFunction = real_identity;
491 
492   // Calling the redirected function.
493   InterceptorFunctionCalled = 0;
494   EXPECT_EQ(42, identity1(42));
495   EXPECT_EQ(42, identity2(42));
496   EXPECT_EQ(2, InterceptorFunctionCalled);
497 
498   TestOnlyReleaseTrampolineRegions();
499 }
500 
501 template<class T>
TestFunctionPatching(const T & code,TestOverrideFunction override,FunctionPrefixKind prefix_kind=FunctionPrefixNone)502 static bool TestFunctionPatching(
503     const T &code,
504     TestOverrideFunction override,
505     FunctionPrefixKind prefix_kind = FunctionPrefixNone) {
506   uptr address;
507   LoadActiveCode(code, &address, prefix_kind);
508   uptr unused_real_address = 0;
509   bool result = override(
510       address, (uptr)&InterceptorFunction, &unused_real_address);
511 
512   TestOnlyReleaseTrampolineRegions();
513   return result;
514 }
515 
TEST(Interception,PatchableFunction)516 TEST(Interception, PatchableFunction) {
517   TestOverrideFunction override = OverrideFunction;
518   // Test without function padding.
519   EXPECT_TRUE(TestFunctionPatching(kPatchableCode1, override));
520   EXPECT_TRUE(TestFunctionPatching(kPatchableCode2, override));
521 #if SANITIZER_WINDOWS64
522   EXPECT_FALSE(TestFunctionPatching(kPatchableCode3, override));
523 #else
524   EXPECT_TRUE(TestFunctionPatching(kPatchableCode3, override));
525 #endif
526   EXPECT_TRUE(TestFunctionPatching(kPatchableCode4, override));
527   EXPECT_TRUE(TestFunctionPatching(kPatchableCode5, override));
528 #if SANITIZER_WINDOWS64
529   EXPECT_TRUE(TestFunctionPatching(kLoadGlobalCode, override));
530 #endif
531 
532   EXPECT_FALSE(TestFunctionPatching(kUnpatchableCode1, override));
533   EXPECT_FALSE(TestFunctionPatching(kUnpatchableCode2, override));
534   EXPECT_FALSE(TestFunctionPatching(kUnpatchableCode3, override));
535   EXPECT_FALSE(TestFunctionPatching(kUnpatchableCode4, override));
536   EXPECT_FALSE(TestFunctionPatching(kUnpatchableCode5, override));
537   EXPECT_FALSE(TestFunctionPatching(kUnpatchableCode6, override));
538 }
539 
540 #if !SANITIZER_WINDOWS64
TEST(Interception,PatchableFunctionWithDetour)541 TEST(Interception, PatchableFunctionWithDetour) {
542   TestOverrideFunction override = OverrideFunctionWithDetour;
543   // Without the prefix, no function can be detoured.
544   EXPECT_FALSE(TestFunctionPatching(kPatchableCode1, override));
545   EXPECT_FALSE(TestFunctionPatching(kPatchableCode2, override));
546   EXPECT_FALSE(TestFunctionPatching(kPatchableCode3, override));
547   EXPECT_FALSE(TestFunctionPatching(kPatchableCode4, override));
548   EXPECT_FALSE(TestFunctionPatching(kUnpatchableCode1, override));
549   EXPECT_FALSE(TestFunctionPatching(kUnpatchableCode2, override));
550   EXPECT_FALSE(TestFunctionPatching(kUnpatchableCode3, override));
551   EXPECT_FALSE(TestFunctionPatching(kUnpatchableCode4, override));
552   EXPECT_FALSE(TestFunctionPatching(kUnpatchableCode5, override));
553   EXPECT_FALSE(TestFunctionPatching(kUnpatchableCode6, override));
554 
555   // With the prefix, all functions can be detoured.
556   FunctionPrefixKind prefix = FunctionPrefixDetour;
557   EXPECT_TRUE(TestFunctionPatching(kPatchableCode1, override, prefix));
558   EXPECT_TRUE(TestFunctionPatching(kPatchableCode2, override, prefix));
559   EXPECT_TRUE(TestFunctionPatching(kPatchableCode3, override, prefix));
560   EXPECT_TRUE(TestFunctionPatching(kPatchableCode4, override, prefix));
561   EXPECT_TRUE(TestFunctionPatching(kUnpatchableCode1, override, prefix));
562   EXPECT_TRUE(TestFunctionPatching(kUnpatchableCode2, override, prefix));
563   EXPECT_TRUE(TestFunctionPatching(kUnpatchableCode3, override, prefix));
564   EXPECT_TRUE(TestFunctionPatching(kUnpatchableCode4, override, prefix));
565   EXPECT_TRUE(TestFunctionPatching(kUnpatchableCode5, override, prefix));
566   EXPECT_TRUE(TestFunctionPatching(kUnpatchableCode6, override, prefix));
567 }
568 #endif  // !SANITIZER_WINDOWS64
569 
TEST(Interception,PatchableFunctionWithRedirectJump)570 TEST(Interception, PatchableFunctionWithRedirectJump) {
571   TestOverrideFunction override = OverrideFunctionWithRedirectJump;
572   EXPECT_FALSE(TestFunctionPatching(kPatchableCode1, override));
573   EXPECT_FALSE(TestFunctionPatching(kPatchableCode2, override));
574   EXPECT_FALSE(TestFunctionPatching(kPatchableCode3, override));
575   EXPECT_TRUE(TestFunctionPatching(kPatchableCode4, override));
576   EXPECT_FALSE(TestFunctionPatching(kUnpatchableCode1, override));
577   EXPECT_FALSE(TestFunctionPatching(kUnpatchableCode2, override));
578   EXPECT_FALSE(TestFunctionPatching(kUnpatchableCode3, override));
579   EXPECT_FALSE(TestFunctionPatching(kUnpatchableCode4, override));
580   EXPECT_FALSE(TestFunctionPatching(kUnpatchableCode5, override));
581   EXPECT_FALSE(TestFunctionPatching(kUnpatchableCode6, override));
582 }
583 
TEST(Interception,PatchableFunctionWithHotPatch)584 TEST(Interception, PatchableFunctionWithHotPatch) {
585   TestOverrideFunction override = OverrideFunctionWithHotPatch;
586   FunctionPrefixKind prefix = FunctionPrefixHotPatch;
587 
588   EXPECT_TRUE(TestFunctionPatching(kPatchableCode1, override, prefix));
589   EXPECT_FALSE(TestFunctionPatching(kPatchableCode2, override, prefix));
590   EXPECT_FALSE(TestFunctionPatching(kPatchableCode3, override, prefix));
591   EXPECT_FALSE(TestFunctionPatching(kPatchableCode4, override, prefix));
592 #if SANITIZER_WINDOWS64
593   EXPECT_TRUE(TestFunctionPatching(kPatchableCode6, override, prefix));
594   EXPECT_TRUE(TestFunctionPatching(kPatchableCode7, override, prefix));
595   EXPECT_TRUE(TestFunctionPatching(kPatchableCode8, override, prefix));
596 #endif
597   EXPECT_FALSE(TestFunctionPatching(kUnpatchableCode1, override, prefix));
598   EXPECT_TRUE(TestFunctionPatching(kUnpatchableCode2, override, prefix));
599   EXPECT_FALSE(TestFunctionPatching(kUnpatchableCode3, override, prefix));
600   EXPECT_FALSE(TestFunctionPatching(kUnpatchableCode4, override, prefix));
601   EXPECT_FALSE(TestFunctionPatching(kUnpatchableCode5, override, prefix));
602   EXPECT_FALSE(TestFunctionPatching(kUnpatchableCode6, override, prefix));
603 }
604 
TEST(Interception,PatchableFunctionWithTrampoline)605 TEST(Interception, PatchableFunctionWithTrampoline) {
606   TestOverrideFunction override = OverrideFunctionWithTrampoline;
607   FunctionPrefixKind prefix = FunctionPrefixPadding;
608 
609   EXPECT_TRUE(TestFunctionPatching(kPatchableCode1, override, prefix));
610   EXPECT_TRUE(TestFunctionPatching(kPatchableCode2, override, prefix));
611 #if SANITIZER_WINDOWS64
612   EXPECT_FALSE(TestFunctionPatching(kPatchableCode3, override, prefix));
613 #else
614   EXPECT_TRUE(TestFunctionPatching(kPatchableCode3, override, prefix));
615 #endif
616   EXPECT_FALSE(TestFunctionPatching(kPatchableCode4, override, prefix));
617 
618   EXPECT_FALSE(TestFunctionPatching(kUnpatchableCode1, override, prefix));
619   EXPECT_FALSE(TestFunctionPatching(kUnpatchableCode2, override, prefix));
620   EXPECT_FALSE(TestFunctionPatching(kUnpatchableCode3, override, prefix));
621   EXPECT_FALSE(TestFunctionPatching(kUnpatchableCode4, override, prefix));
622   EXPECT_FALSE(TestFunctionPatching(kUnpatchableCode5, override, prefix));
623   EXPECT_FALSE(TestFunctionPatching(kUnpatchableCode6, override, prefix));
624 }
625 
TEST(Interception,PatchableFunctionPadding)626 TEST(Interception, PatchableFunctionPadding) {
627   TestOverrideFunction override = OverrideFunction;
628   FunctionPrefixKind prefix = FunctionPrefixPadding;
629 
630   EXPECT_TRUE(TestFunctionPatching(kPatchableCode1, override, prefix));
631   EXPECT_TRUE(TestFunctionPatching(kPatchableCode2, override, prefix));
632 #if SANITIZER_WINDOWS64
633   EXPECT_FALSE(TestFunctionPatching(kPatchableCode3, override, prefix));
634 #else
635   EXPECT_TRUE(TestFunctionPatching(kPatchableCode3, override, prefix));
636 #endif
637   EXPECT_TRUE(TestFunctionPatching(kPatchableCode4, override, prefix));
638 
639   EXPECT_FALSE(TestFunctionPatching(kUnpatchableCode1, override, prefix));
640   EXPECT_TRUE(TestFunctionPatching(kUnpatchableCode2, override, prefix));
641   EXPECT_FALSE(TestFunctionPatching(kUnpatchableCode3, override, prefix));
642   EXPECT_FALSE(TestFunctionPatching(kUnpatchableCode4, override, prefix));
643   EXPECT_FALSE(TestFunctionPatching(kUnpatchableCode5, override, prefix));
644   EXPECT_FALSE(TestFunctionPatching(kUnpatchableCode6, override, prefix));
645 }
646 
TEST(Interception,EmptyExportTable)647 TEST(Interception, EmptyExportTable) {
648   // We try to get a pointer to a function from an executable that doesn't
649   // export any symbol (empty export table).
650   uptr FunPtr = InternalGetProcAddress((void *)GetModuleHandleA(0), "example");
651   EXPECT_EQ(0U, FunPtr);
652 }
653 
654 }  // namespace __interception
655 
656 #endif  // SANITIZER_WINDOWS
657 #endif  // #if !SANITIZER_DEBUG
658