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