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 kUnpatchableCode7[] = {
212     0x33, 0xc0,                     // xor     eax,eax
213     0x48, 0x85, 0xd2,               // test    rdx,rdx
214     0x74, 0x10,                     // je      +16  (unpatchable)
215 };
216 
217 const u8 kUnpatchableCode8[] = {
218     0x48, 0x8b, 0xc1,               // mov     rax,rcx
219     0x0f, 0xb7, 0x10,               // movzx   edx,word ptr [rax]
220     0x48, 0x83, 0xc0, 0x02,         // add     rax,2
221     0x66, 0x85, 0xd2,               // test    dx,dx
222     0x75, 0xf4,                     // jne     -12  (unpatchable)
223 };
224 
225 const u8 kUnpatchableCode9[] = {
226     0x4c, 0x8b, 0xc1,               // mov     r8,rcx
227     0x8a, 0x01,                     // mov     al,byte ptr [rcx]
228     0x48, 0xff, 0xc1,               // inc     rcx
229     0x84, 0xc0,                     // test    al,al
230     0x75, 0xf7,                     // jne     -9  (unpatchable)
231 };
232 
233 const u8 kPatchableCode6[] = {
234     0x48, 0x89, 0x54, 0x24, 0xBB, // mov QWORD PTR [rsp + 0xBB], rdx
235     0x33, 0xC9,                   // xor ecx,ecx
236     0xC3,                         // ret
237 };
238 
239 const u8 kPatchableCode7[] = {
240     0x4c, 0x89, 0x4c, 0x24, 0xBB,  // mov QWORD PTR [rsp + 0xBB], r9
241     0x33, 0xC9,                   // xor ecx,ecx
242     0xC3,                         // ret
243 };
244 
245 const u8 kPatchableCode8[] = {
246     0x4c, 0x89, 0x44, 0x24, 0xBB, // mov QWORD PTR [rsp + 0xBB], r8
247     0x33, 0xC9,                   // xor ecx,ecx
248     0xC3,                         // ret
249 };
250 
251 const u8 kPatchableCode9[] = {
252     0x8a, 0x01,                     // al,byte ptr [rcx]
253     0x45, 0x33, 0xc0,               // xor     r8d,r8d
254     0x84, 0xc0,                     // test    al,al
255 };
256 
257 const u8 kPatchableCode10[] = {
258     0x45, 0x33, 0xc0,               // xor     r8d,r8d
259     0x41, 0x8b, 0xc0,               // mov     eax,r8d
260     0x48, 0x85, 0xd2,               // test    rdx,rdx
261 };
262 
263 const u8 kPatchableCode11[] = {
264     0x48, 0x83, 0xec, 0x38,         // sub     rsp,38h
265     0x83, 0x64, 0x24, 0x28, 0x00,   // and     dword ptr [rsp+28h],0
266 };
267 
268 // A buffer holding the dynamically generated code under test.
269 u8* ActiveCode;
270 const size_t ActiveCodeLength = 4096;
271 
272 int InterceptorFunction(int x);
273 
274 /// Allocate code memory more than 2GB away from Base.
AllocateCode2GBAway(u8 * Base)275 u8 *AllocateCode2GBAway(u8 *Base) {
276   // Find a 64K aligned location after Base plus 2GB.
277   size_t TwoGB = 0x80000000;
278   size_t AllocGranularity = 0x10000;
279   Base = (u8 *)((((uptr)Base + TwoGB + AllocGranularity)) & ~(AllocGranularity - 1));
280 
281   // Check if that location is free, and if not, loop over regions until we find
282   // one that is.
283   MEMORY_BASIC_INFORMATION mbi = {};
284   while (sizeof(mbi) == VirtualQuery(Base, &mbi, sizeof(mbi))) {
285     if (mbi.State & MEM_FREE) break;
286     Base += mbi.RegionSize;
287   }
288 
289   // Allocate one RWX page at the free location.
290   return (u8 *)::VirtualAlloc(Base, ActiveCodeLength, MEM_COMMIT | MEM_RESERVE,
291                               PAGE_EXECUTE_READWRITE);
292 }
293 
294 template<class T>
LoadActiveCode(const T & code,uptr * entry_point,FunctionPrefixKind prefix_kind=FunctionPrefixNone)295 static void LoadActiveCode(
296     const T &code,
297     uptr *entry_point,
298     FunctionPrefixKind prefix_kind = FunctionPrefixNone) {
299   if (ActiveCode == nullptr) {
300     ActiveCode = AllocateCode2GBAway((u8*)&InterceptorFunction);
301     ASSERT_NE(ActiveCode, nullptr) << "failed to allocate RWX memory 2GB away";
302   }
303 
304   size_t position = 0;
305 
306   // Add padding to avoid memory violation when scanning the prefix.
307   for (int i = 0; i < 16; ++i)
308     ActiveCode[position++] = 0xC3;  // Instruction 'ret'.
309 
310   // Add function padding.
311   size_t padding = 0;
312   if (prefix_kind == FunctionPrefixPadding)
313     padding = 16;
314   else if (prefix_kind == FunctionPrefixDetour ||
315            prefix_kind == FunctionPrefixHotPatch)
316     padding = FIRST_32_SECOND_64(5, 6);
317   // Insert |padding| instructions 'nop'.
318   for (size_t i = 0; i < padding; ++i)
319     ActiveCode[position++] = 0x90;
320 
321   // Keep track of the entry point.
322   *entry_point = (uptr)&ActiveCode[position];
323 
324   // Add the detour instruction (i.e. mov edi, edi)
325   if (prefix_kind == FunctionPrefixDetour) {
326 #if SANITIZER_WINDOWS64
327     // Note that "mov edi,edi" is NOP in 32-bit only, in 64-bit it clears
328     // higher bits of RDI.
329     // Use 66,90H as NOP for Windows64.
330     ActiveCode[position++] = 0x66;
331     ActiveCode[position++] = 0x90;
332 #else
333     // mov edi,edi.
334     ActiveCode[position++] = 0x8B;
335     ActiveCode[position++] = 0xFF;
336 #endif
337 
338   }
339 
340   // Copy the function body.
341   for (size_t i = 0; i < sizeof(T); ++i)
342     ActiveCode[position++] = code[i];
343 }
344 
345 int InterceptorFunctionCalled;
346 IdentityFunction InterceptedRealFunction;
347 
InterceptorFunction(int x)348 int InterceptorFunction(int x) {
349   ++InterceptorFunctionCalled;
350   return InterceptedRealFunction(x);
351 }
352 
353 }  // namespace
354 
355 // Tests for interception_win.h
TEST(Interception,InternalGetProcAddress)356 TEST(Interception, InternalGetProcAddress) {
357   HMODULE ntdll_handle = ::GetModuleHandle("ntdll");
358   ASSERT_NE(nullptr, ntdll_handle);
359   uptr DbgPrint_expected = (uptr)::GetProcAddress(ntdll_handle, "DbgPrint");
360   uptr isdigit_expected = (uptr)::GetProcAddress(ntdll_handle, "isdigit");
361   uptr DbgPrint_adddress = InternalGetProcAddress(ntdll_handle, "DbgPrint");
362   uptr isdigit_address = InternalGetProcAddress(ntdll_handle, "isdigit");
363 
364   EXPECT_EQ(DbgPrint_expected, DbgPrint_adddress);
365   EXPECT_EQ(isdigit_expected, isdigit_address);
366   EXPECT_NE(DbgPrint_adddress, isdigit_address);
367 }
368 
369 template<class T>
TestIdentityFunctionPatching(const T & code,TestOverrideFunction override,FunctionPrefixKind prefix_kind=FunctionPrefixNone)370 static void TestIdentityFunctionPatching(
371     const T &code,
372     TestOverrideFunction override,
373     FunctionPrefixKind prefix_kind = FunctionPrefixNone) {
374   uptr identity_address;
375   LoadActiveCode(code, &identity_address, prefix_kind);
376   IdentityFunction identity = (IdentityFunction)identity_address;
377 
378   // Validate behavior before dynamic patching.
379   InterceptorFunctionCalled = 0;
380   EXPECT_EQ(0, identity(0));
381   EXPECT_EQ(42, identity(42));
382   EXPECT_EQ(0, InterceptorFunctionCalled);
383 
384   // Patch the function.
385   uptr real_identity_address = 0;
386   bool success = override(identity_address,
387                          (uptr)&InterceptorFunction,
388                          &real_identity_address);
389   EXPECT_TRUE(success);
390   EXPECT_NE(0U, real_identity_address);
391   IdentityFunction real_identity = (IdentityFunction)real_identity_address;
392   InterceptedRealFunction = real_identity;
393 
394   // Don't run tests if hooking failed or the real function is not valid.
395   if (!success || !real_identity_address)
396     return;
397 
398   // Calling the redirected function.
399   InterceptorFunctionCalled = 0;
400   EXPECT_EQ(0, identity(0));
401   EXPECT_EQ(42, identity(42));
402   EXPECT_EQ(2, InterceptorFunctionCalled);
403 
404   // Calling the real function.
405   InterceptorFunctionCalled = 0;
406   EXPECT_EQ(0, real_identity(0));
407   EXPECT_EQ(42, real_identity(42));
408   EXPECT_EQ(0, InterceptorFunctionCalled);
409 
410   TestOnlyReleaseTrampolineRegions();
411 }
412 
413 #if !SANITIZER_WINDOWS64
TEST(Interception,OverrideFunctionWithDetour)414 TEST(Interception, OverrideFunctionWithDetour) {
415   TestOverrideFunction override = OverrideFunctionWithDetour;
416   FunctionPrefixKind prefix = FunctionPrefixDetour;
417   TestIdentityFunctionPatching(kIdentityCodeWithPrologue, override, prefix);
418   TestIdentityFunctionPatching(kIdentityCodeWithPushPop, override, prefix);
419   TestIdentityFunctionPatching(kIdentityCodeWithMov, override, prefix);
420   TestIdentityFunctionPatching(kIdentityCodeWithJump, override, prefix);
421 }
422 #endif  // !SANITIZER_WINDOWS64
423 
TEST(Interception,OverrideFunctionWithRedirectJump)424 TEST(Interception, OverrideFunctionWithRedirectJump) {
425   TestOverrideFunction override = OverrideFunctionWithRedirectJump;
426   TestIdentityFunctionPatching(kIdentityCodeWithJump, override);
427 }
428 
TEST(Interception,OverrideFunctionWithHotPatch)429 TEST(Interception, OverrideFunctionWithHotPatch) {
430   TestOverrideFunction override = OverrideFunctionWithHotPatch;
431   FunctionPrefixKind prefix = FunctionPrefixHotPatch;
432   TestIdentityFunctionPatching(kIdentityCodeWithMov, override, prefix);
433 }
434 
TEST(Interception,OverrideFunctionWithTrampoline)435 TEST(Interception, OverrideFunctionWithTrampoline) {
436   TestOverrideFunction override = OverrideFunctionWithTrampoline;
437   FunctionPrefixKind prefix = FunctionPrefixNone;
438   TestIdentityFunctionPatching(kIdentityCodeWithPrologue, override, prefix);
439   TestIdentityFunctionPatching(kIdentityCodeWithPushPop, override, prefix);
440 
441   prefix = FunctionPrefixPadding;
442   TestIdentityFunctionPatching(kIdentityCodeWithPrologue, override, prefix);
443   TestIdentityFunctionPatching(kIdentityCodeWithPushPop, override, prefix);
444 }
445 
TEST(Interception,OverrideFunction)446 TEST(Interception, OverrideFunction) {
447   TestOverrideFunction override = OverrideFunction;
448   FunctionPrefixKind prefix = FunctionPrefixNone;
449   TestIdentityFunctionPatching(kIdentityCodeWithPrologue, override, prefix);
450   TestIdentityFunctionPatching(kIdentityCodeWithPushPop, override, prefix);
451   TestIdentityFunctionPatching(kIdentityCodeWithJump, override, prefix);
452 
453   prefix = FunctionPrefixPadding;
454   TestIdentityFunctionPatching(kIdentityCodeWithPrologue, override, prefix);
455   TestIdentityFunctionPatching(kIdentityCodeWithPushPop, override, prefix);
456   TestIdentityFunctionPatching(kIdentityCodeWithMov, override, prefix);
457   TestIdentityFunctionPatching(kIdentityCodeWithJump, override, prefix);
458 
459   prefix = FunctionPrefixHotPatch;
460   TestIdentityFunctionPatching(kIdentityCodeWithPrologue, override, prefix);
461   TestIdentityFunctionPatching(kIdentityCodeWithPushPop, override, prefix);
462   TestIdentityFunctionPatching(kIdentityCodeWithMov, override, prefix);
463   TestIdentityFunctionPatching(kIdentityCodeWithJump, override, prefix);
464 
465   prefix = FunctionPrefixDetour;
466   TestIdentityFunctionPatching(kIdentityCodeWithPrologue, override, prefix);
467   TestIdentityFunctionPatching(kIdentityCodeWithPushPop, override, prefix);
468   TestIdentityFunctionPatching(kIdentityCodeWithMov, override, prefix);
469   TestIdentityFunctionPatching(kIdentityCodeWithJump, override, prefix);
470 }
471 
472 template<class T>
TestIdentityFunctionMultiplePatching(const T & code,TestOverrideFunction override,FunctionPrefixKind prefix_kind=FunctionPrefixNone)473 static void TestIdentityFunctionMultiplePatching(
474     const T &code,
475     TestOverrideFunction override,
476     FunctionPrefixKind prefix_kind = FunctionPrefixNone) {
477   uptr identity_address;
478   LoadActiveCode(code, &identity_address, prefix_kind);
479 
480   // Patch the function.
481   uptr real_identity_address = 0;
482   bool success = override(identity_address,
483                           (uptr)&InterceptorFunction,
484                           &real_identity_address);
485   EXPECT_TRUE(success);
486   EXPECT_NE(0U, real_identity_address);
487 
488   // Re-patching the function should not work.
489   success = override(identity_address,
490                      (uptr)&InterceptorFunction,
491                      &real_identity_address);
492   EXPECT_FALSE(success);
493 
494   TestOnlyReleaseTrampolineRegions();
495 }
496 
TEST(Interception,OverrideFunctionMultiplePatchingIsFailing)497 TEST(Interception, OverrideFunctionMultiplePatchingIsFailing) {
498 #if !SANITIZER_WINDOWS64
499   TestIdentityFunctionMultiplePatching(kIdentityCodeWithPrologue,
500                                        OverrideFunctionWithDetour,
501                                        FunctionPrefixDetour);
502 #endif
503 
504   TestIdentityFunctionMultiplePatching(kIdentityCodeWithMov,
505                                        OverrideFunctionWithHotPatch,
506                                        FunctionPrefixHotPatch);
507 
508   TestIdentityFunctionMultiplePatching(kIdentityCodeWithPushPop,
509                                        OverrideFunctionWithTrampoline,
510                                        FunctionPrefixPadding);
511 }
512 
TEST(Interception,OverrideFunctionTwice)513 TEST(Interception, OverrideFunctionTwice) {
514   uptr identity_address1;
515   LoadActiveCode(kIdentityTwice, &identity_address1);
516   uptr identity_address2 = identity_address1 + kIdentityTwiceOffset;
517   IdentityFunction identity1 = (IdentityFunction)identity_address1;
518   IdentityFunction identity2 = (IdentityFunction)identity_address2;
519 
520   // Patch the two functions.
521   uptr real_identity_address = 0;
522   EXPECT_TRUE(OverrideFunction(identity_address1,
523                                (uptr)&InterceptorFunction,
524                                &real_identity_address));
525   EXPECT_TRUE(OverrideFunction(identity_address2,
526                                (uptr)&InterceptorFunction,
527                                &real_identity_address));
528   IdentityFunction real_identity = (IdentityFunction)real_identity_address;
529   InterceptedRealFunction = real_identity;
530 
531   // Calling the redirected function.
532   InterceptorFunctionCalled = 0;
533   EXPECT_EQ(42, identity1(42));
534   EXPECT_EQ(42, identity2(42));
535   EXPECT_EQ(2, InterceptorFunctionCalled);
536 
537   TestOnlyReleaseTrampolineRegions();
538 }
539 
540 template<class T>
TestFunctionPatching(const T & code,TestOverrideFunction override,FunctionPrefixKind prefix_kind=FunctionPrefixNone)541 static bool TestFunctionPatching(
542     const T &code,
543     TestOverrideFunction override,
544     FunctionPrefixKind prefix_kind = FunctionPrefixNone) {
545   uptr address;
546   LoadActiveCode(code, &address, prefix_kind);
547   uptr unused_real_address = 0;
548   bool result = override(
549       address, (uptr)&InterceptorFunction, &unused_real_address);
550 
551   TestOnlyReleaseTrampolineRegions();
552   return result;
553 }
554 
TEST(Interception,PatchableFunction)555 TEST(Interception, PatchableFunction) {
556   TestOverrideFunction override = OverrideFunction;
557   // Test without function padding.
558   EXPECT_TRUE(TestFunctionPatching(kPatchableCode1, override));
559   EXPECT_TRUE(TestFunctionPatching(kPatchableCode2, override));
560 #if SANITIZER_WINDOWS64
561   EXPECT_FALSE(TestFunctionPatching(kPatchableCode3, override));
562 #else
563   EXPECT_TRUE(TestFunctionPatching(kPatchableCode3, override));
564 #endif
565   EXPECT_TRUE(TestFunctionPatching(kPatchableCode4, override));
566   EXPECT_TRUE(TestFunctionPatching(kPatchableCode5, override));
567 #if SANITIZER_WINDOWS64
568   EXPECT_TRUE(TestFunctionPatching(kLoadGlobalCode, override));
569 #endif
570 
571   EXPECT_FALSE(TestFunctionPatching(kUnpatchableCode1, override));
572   EXPECT_FALSE(TestFunctionPatching(kUnpatchableCode2, override));
573   EXPECT_FALSE(TestFunctionPatching(kUnpatchableCode3, override));
574   EXPECT_FALSE(TestFunctionPatching(kUnpatchableCode4, override));
575   EXPECT_FALSE(TestFunctionPatching(kUnpatchableCode5, override));
576   EXPECT_FALSE(TestFunctionPatching(kUnpatchableCode6, override));
577 }
578 
579 #if !SANITIZER_WINDOWS64
TEST(Interception,PatchableFunctionWithDetour)580 TEST(Interception, PatchableFunctionWithDetour) {
581   TestOverrideFunction override = OverrideFunctionWithDetour;
582   // Without the prefix, no function can be detoured.
583   EXPECT_FALSE(TestFunctionPatching(kPatchableCode1, override));
584   EXPECT_FALSE(TestFunctionPatching(kPatchableCode2, override));
585   EXPECT_FALSE(TestFunctionPatching(kPatchableCode3, override));
586   EXPECT_FALSE(TestFunctionPatching(kPatchableCode4, override));
587   EXPECT_FALSE(TestFunctionPatching(kUnpatchableCode1, override));
588   EXPECT_FALSE(TestFunctionPatching(kUnpatchableCode2, override));
589   EXPECT_FALSE(TestFunctionPatching(kUnpatchableCode3, override));
590   EXPECT_FALSE(TestFunctionPatching(kUnpatchableCode4, override));
591   EXPECT_FALSE(TestFunctionPatching(kUnpatchableCode5, override));
592   EXPECT_FALSE(TestFunctionPatching(kUnpatchableCode6, override));
593 
594   // With the prefix, all functions can be detoured.
595   FunctionPrefixKind prefix = FunctionPrefixDetour;
596   EXPECT_TRUE(TestFunctionPatching(kPatchableCode1, override, prefix));
597   EXPECT_TRUE(TestFunctionPatching(kPatchableCode2, override, prefix));
598   EXPECT_TRUE(TestFunctionPatching(kPatchableCode3, override, prefix));
599   EXPECT_TRUE(TestFunctionPatching(kPatchableCode4, override, prefix));
600   EXPECT_TRUE(TestFunctionPatching(kUnpatchableCode1, override, prefix));
601   EXPECT_TRUE(TestFunctionPatching(kUnpatchableCode2, override, prefix));
602   EXPECT_TRUE(TestFunctionPatching(kUnpatchableCode3, override, prefix));
603   EXPECT_TRUE(TestFunctionPatching(kUnpatchableCode4, override, prefix));
604   EXPECT_TRUE(TestFunctionPatching(kUnpatchableCode5, override, prefix));
605   EXPECT_TRUE(TestFunctionPatching(kUnpatchableCode6, override, prefix));
606 }
607 #endif  // !SANITIZER_WINDOWS64
608 
TEST(Interception,PatchableFunctionWithRedirectJump)609 TEST(Interception, PatchableFunctionWithRedirectJump) {
610   TestOverrideFunction override = OverrideFunctionWithRedirectJump;
611   EXPECT_FALSE(TestFunctionPatching(kPatchableCode1, override));
612   EXPECT_FALSE(TestFunctionPatching(kPatchableCode2, override));
613   EXPECT_FALSE(TestFunctionPatching(kPatchableCode3, override));
614   EXPECT_TRUE(TestFunctionPatching(kPatchableCode4, override));
615   EXPECT_FALSE(TestFunctionPatching(kUnpatchableCode1, override));
616   EXPECT_FALSE(TestFunctionPatching(kUnpatchableCode2, override));
617   EXPECT_FALSE(TestFunctionPatching(kUnpatchableCode3, override));
618   EXPECT_FALSE(TestFunctionPatching(kUnpatchableCode4, override));
619   EXPECT_FALSE(TestFunctionPatching(kUnpatchableCode5, override));
620   EXPECT_FALSE(TestFunctionPatching(kUnpatchableCode6, override));
621 }
622 
TEST(Interception,PatchableFunctionWithHotPatch)623 TEST(Interception, PatchableFunctionWithHotPatch) {
624   TestOverrideFunction override = OverrideFunctionWithHotPatch;
625   FunctionPrefixKind prefix = FunctionPrefixHotPatch;
626 
627   EXPECT_TRUE(TestFunctionPatching(kPatchableCode1, override, prefix));
628   EXPECT_FALSE(TestFunctionPatching(kPatchableCode2, override, prefix));
629   EXPECT_FALSE(TestFunctionPatching(kPatchableCode3, override, prefix));
630   EXPECT_FALSE(TestFunctionPatching(kPatchableCode4, override, prefix));
631 #if SANITIZER_WINDOWS64
632   EXPECT_TRUE(TestFunctionPatching(kPatchableCode6, override, prefix));
633   EXPECT_TRUE(TestFunctionPatching(kPatchableCode7, override, prefix));
634   EXPECT_TRUE(TestFunctionPatching(kPatchableCode8, override, prefix));
635 #endif
636   EXPECT_FALSE(TestFunctionPatching(kUnpatchableCode1, override, prefix));
637   EXPECT_TRUE(TestFunctionPatching(kUnpatchableCode2, override, prefix));
638   EXPECT_FALSE(TestFunctionPatching(kUnpatchableCode3, override, prefix));
639   EXPECT_FALSE(TestFunctionPatching(kUnpatchableCode4, override, prefix));
640   EXPECT_FALSE(TestFunctionPatching(kUnpatchableCode5, override, prefix));
641   EXPECT_FALSE(TestFunctionPatching(kUnpatchableCode6, override, prefix));
642 }
643 
TEST(Interception,PatchableFunctionWithTrampoline)644 TEST(Interception, PatchableFunctionWithTrampoline) {
645   TestOverrideFunction override = OverrideFunctionWithTrampoline;
646   FunctionPrefixKind prefix = FunctionPrefixPadding;
647 
648   EXPECT_TRUE(TestFunctionPatching(kPatchableCode1, override, prefix));
649   EXPECT_TRUE(TestFunctionPatching(kPatchableCode2, override, prefix));
650 #if SANITIZER_WINDOWS64
651   EXPECT_FALSE(TestFunctionPatching(kPatchableCode3, override, prefix));
652   EXPECT_TRUE(TestFunctionPatching(kPatchableCode9, override, prefix));
653   EXPECT_TRUE(TestFunctionPatching(kPatchableCode10, override, prefix));
654   EXPECT_TRUE(TestFunctionPatching(kPatchableCode11, override, prefix));
655   EXPECT_FALSE(TestFunctionPatching(kUnpatchableCode7, override, prefix));
656   EXPECT_FALSE(TestFunctionPatching(kUnpatchableCode8, override, prefix));
657   EXPECT_FALSE(TestFunctionPatching(kUnpatchableCode9, override, prefix));
658 #else
659   EXPECT_TRUE(TestFunctionPatching(kPatchableCode3, override, prefix));
660 #endif
661   EXPECT_FALSE(TestFunctionPatching(kPatchableCode4, override, prefix));
662 
663   EXPECT_FALSE(TestFunctionPatching(kUnpatchableCode1, override, prefix));
664   EXPECT_FALSE(TestFunctionPatching(kUnpatchableCode2, override, prefix));
665   EXPECT_FALSE(TestFunctionPatching(kUnpatchableCode3, override, prefix));
666   EXPECT_FALSE(TestFunctionPatching(kUnpatchableCode4, override, prefix));
667   EXPECT_FALSE(TestFunctionPatching(kUnpatchableCode5, override, prefix));
668   EXPECT_FALSE(TestFunctionPatching(kUnpatchableCode6, override, prefix));
669 }
670 
TEST(Interception,PatchableFunctionPadding)671 TEST(Interception, PatchableFunctionPadding) {
672   TestOverrideFunction override = OverrideFunction;
673   FunctionPrefixKind prefix = FunctionPrefixPadding;
674 
675   EXPECT_TRUE(TestFunctionPatching(kPatchableCode1, override, prefix));
676   EXPECT_TRUE(TestFunctionPatching(kPatchableCode2, override, prefix));
677 #if SANITIZER_WINDOWS64
678   EXPECT_FALSE(TestFunctionPatching(kPatchableCode3, override, prefix));
679 #else
680   EXPECT_TRUE(TestFunctionPatching(kPatchableCode3, override, prefix));
681 #endif
682   EXPECT_TRUE(TestFunctionPatching(kPatchableCode4, override, prefix));
683 
684   EXPECT_FALSE(TestFunctionPatching(kUnpatchableCode1, override, prefix));
685   EXPECT_TRUE(TestFunctionPatching(kUnpatchableCode2, override, prefix));
686   EXPECT_FALSE(TestFunctionPatching(kUnpatchableCode3, override, prefix));
687   EXPECT_FALSE(TestFunctionPatching(kUnpatchableCode4, override, prefix));
688   EXPECT_FALSE(TestFunctionPatching(kUnpatchableCode5, override, prefix));
689   EXPECT_FALSE(TestFunctionPatching(kUnpatchableCode6, override, prefix));
690 }
691 
TEST(Interception,EmptyExportTable)692 TEST(Interception, EmptyExportTable) {
693   // We try to get a pointer to a function from an executable that doesn't
694   // export any symbol (empty export table).
695   uptr FunPtr = InternalGetProcAddress((void *)GetModuleHandleA(0), "example");
696   EXPECT_EQ(0U, FunPtr);
697 }
698 
699 }  // namespace __interception
700 
701 #endif  // SANITIZER_WINDOWS
702 #endif  // #if !SANITIZER_DEBUG
703