| OLD | NEW |
| 1 // mach_override.c semver:1.2.0 | 1 // mach_override.c semver:1.2.0 |
| 2 // Copyright (c) 2003-2012 Jonathan 'Wolf' Rentzsch: http://rentzsch.com | 2 // Copyright (c) 2003-2012 Jonathan 'Wolf' Rentzsch: http://rentzsch.com |
| 3 // Some rights reserved: http://opensource.org/licenses/mit | 3 // Some rights reserved: http://opensource.org/licenses/mit |
| 4 // https://github.com/rentzsch/mach_override | 4 // https://github.com/rentzsch/mach_override |
| 5 | 5 |
| 6 #include "mach_override.h" | 6 #include "mach_override.h" |
| 7 #if defined(__i386__) || defined(__x86_64__) | 7 #if defined(__i386__) || defined(__x86_64__) |
| 8 #include "udis86.h" | 8 #include "udis86.h" |
| 9 #endif | 9 #endif |
| 10 | 10 |
| 11 #include <mach-o/dyld.h> | 11 #include <mach-o/dyld.h> |
| 12 #include <mach/mach_host.h> | |
| 13 #include <mach/mach_init.h> | 12 #include <mach/mach_init.h> |
| 14 #include <mach/vm_map.h> | 13 #include <mach/vm_map.h> |
| 15 #include <mach/vm_statistics.h> | 14 #include <mach/vm_statistics.h> |
| 16 #include <sys/mman.h> | 15 #include <sys/mman.h> |
| 17 | 16 |
| 18 #include <CoreServices/CoreServices.h> | 17 #include <CoreServices/CoreServices.h> |
| 19 | 18 |
| 20 /************************** | 19 /************************** |
| 21 * | 20 * |
| 22 * Constants | 21 * Constants |
| (...skipping 130 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 153 * | 152 * |
| 154 * Interface | 153 * Interface |
| 155 * | 154 * |
| 156 *******************************************************************************/ | 155 *******************************************************************************/ |
| 157 #pragma mark - | 156 #pragma mark - |
| 158 #pragma mark (Interface) | 157 #pragma mark (Interface) |
| 159 | 158 |
| 160 #if defined(__i386__) || defined(__x86_64__) | 159 #if defined(__i386__) || defined(__x86_64__) |
| 161 mach_error_t makeIslandExecutable(void *address) { | 160 mach_error_t makeIslandExecutable(void *address) { |
| 162 mach_error_t err = err_none; | 161 mach_error_t err = err_none; |
| 163 vm_size_t pageSize; | 162 uintptr_t page = (uintptr_t)address & ~(uintptr_t)(PAGE_SIZE - 1); |
| 164 host_page_size( mach_host_self(), &pageSize ); | |
| 165 uintptr_t page = (uintptr_t)address & ~(uintptr_t)(pageSize-1); | |
| 166 int e = err_none; | 163 int e = err_none; |
| 167 e |= mprotect((void *)page, pageSize, PROT_EXEC | PROT_READ); | 164 e |= mprotect((void *)page, PAGE_SIZE, PROT_EXEC | PROT_READ); |
| 168 e |= msync((void *)page, pageSize, MS_INVALIDATE ); | 165 e |= msync((void *)page, PAGE_SIZE, MS_INVALIDATE ); |
| 169 if (e) { | 166 if (e) { |
| 170 err = err_cannot_override; | 167 err = err_cannot_override; |
| 171 } | 168 } |
| 172 return err; | 169 return err; |
| 173 } | 170 } |
| 174 #endif | 171 #endif |
| 175 | 172 |
| 176 mach_error_t | 173 mach_error_t |
| 177 mach_override_ptr( | 174 mach_override_ptr( |
| 178 void *originalFunctionAddress, | 175 void *originalFunctionAddress, |
| (...skipping 157 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 336
(void*) ((char *)originalFunctionPtr+eatenCount), originalInstructions ); | 333
(void*) ((char *)originalFunctionPtr+eatenCount), originalInstructions ); |
| 337 // try making islands executable before planting the jmp | 334 // try making islands executable before planting the jmp |
| 338 #if defined(__x86_64__) || defined(__i386__) | 335 #if defined(__x86_64__) || defined(__i386__) |
| 339 if( !err ) | 336 if( !err ) |
| 340 err = makeIslandExecutable(escapeIsland); | 337 err = makeIslandExecutable(escapeIsland); |
| 341 if( !err && reentryIsland ) | 338 if( !err && reentryIsland ) |
| 342 err = makeIslandExecutable(reentryIsland); | 339 err = makeIslandExecutable(reentryIsland); |
| 343 #endif | 340 #endif |
| 344 if ( !err ) | 341 if ( !err ) |
| 345 atomic_mov64((uint64_t *)originalFunctionPtr, jumpRelati
veInstruction); | 342 atomic_mov64((uint64_t *)originalFunctionPtr, jumpRelati
veInstruction); |
| 346 | 343 » » mach_error_t prot_err = err_none; |
| 347 » » mach_error_t prot_err = err_none;» | |
| 348 prot_err = vm_protect( mach_task_self(), | 344 prot_err = vm_protect( mach_task_self(), |
| 349 (vm_address_t) originalFunctionPtr, 8, fa
lse, | 345 (vm_address_t) originalFunctionPtr, 8, fa
lse, |
| 350 (VM_PROT_READ | VM_PROT_EXECUTE) ); | 346 (VM_PROT_READ | VM_PROT_EXECUTE) ); |
| 351 » » if (prot_err) fprintf(stderr, "err = %x %s:%d\n", prot_err, __FI
LE__, __LINE__); | 347 » » if(prot_err) fprintf(stderr, "err = %x %s:%d\n", prot_err, __FIL
E__, __LINE__); |
| 352 } | 348 } |
| 353 #endif | 349 #endif |
| 354 | 350 |
| 355 // Clean up on error. | 351 // Clean up on error. |
| 356 if( err ) { | 352 if( err ) { |
| 357 if( reentryIsland ) | 353 if( reentryIsland ) |
| 358 freeBranchIsland( reentryIsland ); | 354 freeBranchIsland( reentryIsland ); |
| 359 if( escapeIsland ) | 355 if( escapeIsland ) |
| 360 freeBranchIsland( escapeIsland ); | 356 freeBranchIsland( escapeIsland ); |
| 361 } | 357 } |
| (...skipping 24 matching lines...) Expand all Loading... |
| 386 allocateBranchIsland( | 382 allocateBranchIsland( |
| 387 BranchIsland **island, | 383 BranchIsland **island, |
| 388 int allocateHigh, | 384 int allocateHigh, |
| 389 void *originalFunctionAddress) | 385 void *originalFunctionAddress) |
| 390 { | 386 { |
| 391 assert( island ); | 387 assert( island ); |
| 392 | 388 |
| 393 mach_error_t err = err_none; | 389 mach_error_t err = err_none; |
| 394 | 390 |
| 395 if( allocateHigh ) { | 391 if( allocateHigh ) { |
| 396 » » vm_size_t pageSize; | 392 » » assert( sizeof( BranchIsland ) <= PAGE_SIZE ); |
| 397 » » err = host_page_size( mach_host_self(), &pageSize ); | 393 » » vm_address_t page = 0; |
| 398 » » if( !err ) { | |
| 399 » » » assert( sizeof( BranchIsland ) <= pageSize ); | |
| 400 #if defined(__i386__) | 394 #if defined(__i386__) |
| 401 » » » vm_address_t page = 0; | 395 » » err = vm_allocate( mach_task_self(), &page, PAGE_SIZE, VM_FLAGS_
ANYWHERE ); |
| 402 » » » mach_error_t err = vm_allocate( mach_task_self(), &page,
pageSize, VM_FLAGS_ANYWHERE ); | 396 » » if( err == err_none ) |
| 403 » » » if( err == err_none ) { | 397 » » » *island = (BranchIsland*) page; |
| 404 » » » » *island = (BranchIsland*) page; | |
| 405 » » » » return err_none; | |
| 406 » » » } | |
| 407 » » » return err; | |
| 408 #else | 398 #else |
| 409 | 399 |
| 410 #if defined(__ppc__) || defined(__POWERPC__) | 400 #if defined(__ppc__) || defined(__POWERPC__) |
| 411 » » » vm_address_t first = 0xfeffffff; | 401 » » vm_address_t first = 0xfeffffff; |
| 412 » » » vm_address_t last = 0xfe000000 + pageSize; | 402 » » vm_address_t last = 0xfe000000 + PAGE_SIZE; |
| 413 #elif defined(__x86_64__) | 403 #elif defined(__x86_64__) |
| 414 » » » vm_address_t first = ((uint64_t)originalFunctionAddress
& ~(uint64_t)(((uint64_t)1 << 31) - 1)) | ((uint64_t)1 << 31); // start in the m
iddle of the page? | 404 » » // 64-bit ASLR is in bits 13-28 |
| 415 » » » vm_address_t last = 0x0; | 405 » » vm_address_t first = ((uint64_t)originalFunctionAddress & ~( (0x
FUL << 28) | (PAGE_SIZE - 1) ) ) | (0x1UL << 31); |
| 406 » » vm_address_t last = (uint64_t)originalFunctionAddress & ~((0x1UL
<< 32) - 1); |
| 416 #endif | 407 #endif |
| 417 | 408 |
| 418 » » » vm_address_t page = first; | 409 » » page = first; |
| 419 » » » int allocated = 0; | 410 » » int allocated = 0; |
| 420 » » » vm_map_t task_self = mach_task_self(); | 411 » » vm_map_t task_self = mach_task_self(); |
| 421 » » » | |
| 422 » » » while( !err && !allocated && page != last ) { | |
| 423 | 412 |
| 424 » » » » err = vm_allocate( task_self, &page, pageSize, 0
); | 413 » » while( !err && !allocated && page != last ) { |
| 425 » » » » if( err == err_none ) | 414 |
| 426 » » » » » allocated = 1; | 415 » » » err = vm_allocate( task_self, &page, PAGE_SIZE, 0 ); |
| 427 » » » » else if( err == KERN_NO_SPACE ) { | 416 » » » if( err == err_none ) |
| 417 » » » » allocated = 1; |
| 418 » » » else if( err == KERN_NO_SPACE ) { |
| 428 #if defined(__x86_64__) | 419 #if defined(__x86_64__) |
| 429 » » » » » page -= pageSize; | 420 » » » » page -= PAGE_SIZE; |
| 430 #else | 421 #else |
| 431 » » » » » page += pageSize; | 422 » » » » page += PAGE_SIZE; |
| 432 #endif | 423 #endif |
| 433 » » » » » err = err_none; | 424 » » » » err = err_none; |
| 434 » » » » } | |
| 435 } | 425 } |
| 436 » » » if( allocated ) | 426 » » } |
| 437 » » » » *island = (BranchIsland*) page; | 427 » » if( allocated ) |
| 438 » » » else if( !allocated && !err ) | 428 » » » *island = (BranchIsland*) page; |
| 439 » » » » err = KERN_NO_SPACE; | 429 » » else if( !allocated && !err ) |
| 430 » » » err = KERN_NO_SPACE; |
| 440 #endif | 431 #endif |
| 441 } | |
| 442 } else { | 432 } else { |
| 443 void *block = malloc( sizeof( BranchIsland ) ); | 433 void *block = malloc( sizeof( BranchIsland ) ); |
| 444 if( block ) | 434 if( block ) |
| 445 *island = block; | 435 *island = block; |
| 446 else | 436 else |
| 447 err = KERN_NO_SPACE; | 437 err = KERN_NO_SPACE; |
| 448 } | 438 } |
| 449 if( !err ) | 439 if( !err ) |
| 450 (**island).allocatedHigh = allocateHigh; | 440 (**island).allocatedHigh = allocateHigh; |
| 451 | 441 |
| (...skipping 12 matching lines...) Expand all Loading... |
| 464 freeBranchIsland( | 454 freeBranchIsland( |
| 465 BranchIsland *island ) | 455 BranchIsland *island ) |
| 466 { | 456 { |
| 467 assert( island ); | 457 assert( island ); |
| 468 assert( (*(long*)&island->instructions[0]) == kIslandTemplate[0] ); | 458 assert( (*(long*)&island->instructions[0]) == kIslandTemplate[0] ); |
| 469 assert( island->allocatedHigh ); | 459 assert( island->allocatedHigh ); |
| 470 | 460 |
| 471 mach_error_t err = err_none; | 461 mach_error_t err = err_none; |
| 472 | 462 |
| 473 if( island->allocatedHigh ) { | 463 if( island->allocatedHigh ) { |
| 474 » » vm_size_t pageSize; | 464 » » assert( sizeof( BranchIsland ) <= PAGE_SIZE ); |
| 475 » » err = host_page_size( mach_host_self(), &pageSize ); | 465 » » err = vm_deallocate(mach_task_self(), (vm_address_t) island, PAG
E_SIZE ); |
| 476 » » if( !err ) { | |
| 477 » » » assert( sizeof( BranchIsland ) <= pageSize ); | |
| 478 » » » err = vm_deallocate( | |
| 479 » » » » » mach_task_self(), | |
| 480 » » » » » (vm_address_t) island, pageSize ); | |
| 481 » » } | |
| 482 } else { | 466 } else { |
| 483 free( island ); | 467 free( island ); |
| 484 } | 468 } |
| 485 | 469 |
| 486 return err; | 470 return err; |
| 487 } | 471 } |
| 488 | 472 |
| 489 /******************************************************************************* | 473 /******************************************************************************* |
| 490 Implementation: Sets the branch island's target, with an optional | 474 Implementation: Sets the branch island's target, with an optional |
| 491 instruction. | 475 instruction. |
| (...skipping 215 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 707 ); | 691 ); |
| 708 #elif defined(__x86_64__) | 692 #elif defined(__x86_64__) |
| 709 void atomic_mov64( | 693 void atomic_mov64( |
| 710 uint64_t *targetAddress, | 694 uint64_t *targetAddress, |
| 711 uint64_t value ) | 695 uint64_t value ) |
| 712 { | 696 { |
| 713 *targetAddress = value; | 697 *targetAddress = value; |
| 714 } | 698 } |
| 715 #endif | 699 #endif |
| 716 #endif | 700 #endif |
| OLD | NEW |