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