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. 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> 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 366 int InterceptorFunction(int x) { 367 ++InterceptorFunctionCalled; 368 return InterceptedRealFunction(x); 369 } 370 371 } // namespace 372 373 // Tests for interception_win.h 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> 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 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 443 TEST(Interception, OverrideFunctionWithRedirectJump) { 444 TestOverrideFunction override = OverrideFunctionWithRedirectJump; 445 TestIdentityFunctionPatching(kIdentityCodeWithJump, override); 446 TestIdentityFunctionPatching(kIdentityCodeWithJumpBackwards, override, 447 FunctionPrefixNone, 448 kIdentityCodeWithJumpBackwardsOffset); 449 } 450 451 TEST(Interception, OverrideFunctionWithHotPatch) { 452 TestOverrideFunction override = OverrideFunctionWithHotPatch; 453 FunctionPrefixKind prefix = FunctionPrefixHotPatch; 454 TestIdentityFunctionPatching(kIdentityCodeWithMov, override, prefix); 455 } 456 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 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> 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 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 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> 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 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 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 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 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 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 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 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