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