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 |