Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 /******************************************************************************* | 1 // mach_override.c semver:1.2.0 |
|
Mark Mentovai
2013/11/05 23:35:37
This patch set, patch set 1, contains the virgin u
| |
| 2 » mach_override.c | 2 // Copyright (c) 2003-2012 Jonathan 'Wolf' Rentzsch: http://rentzsch.com |
| 3 » » Copyright (c) 2003-2009 Jonathan 'Wolf' Rentzsch: <http://rentzs ch.com> | 3 // Some rights reserved: http://opensource.org/licenses/mit |
| 4 » » Some rights reserved: <http://opensource.org/licenses/mit-licens e.php> | 4 // https://github.com/rentzsch/mach_override |
| 5 | 5 |
| 6 ************************************************************************ ***/ | |
| 7 | |
| 8 #include "mach_override.h" | 6 #include "mach_override.h" |
| 7 #if defined(__i386__) || defined(__x86_64__) | |
| 8 #include "udis86.h" | |
| 9 #endif | |
| 9 | 10 |
| 10 #include <mach-o/dyld.h> | 11 #include <mach-o/dyld.h> |
| 11 #include <mach/mach_host.h> | 12 #include <mach/mach_host.h> |
| 12 #include <mach/mach_init.h> | 13 #include <mach/mach_init.h> |
| 13 #include <mach/vm_map.h> | 14 #include <mach/vm_map.h> |
| 14 #include <mach/vm_statistics.h> | |
| 15 #include <sys/mman.h> | 15 #include <sys/mman.h> |
| 16 | 16 |
| 17 #include <CoreServices/CoreServices.h> | 17 #include <CoreServices/CoreServices.h> |
| 18 | 18 |
| 19 /************************** | 19 /************************** |
| 20 * | 20 * |
| 21 * Constants | 21 * Constants |
| 22 * | 22 * |
| 23 **************************/ | 23 **************************/ |
| 24 #pragma mark - | 24 #pragma mark - |
| 25 #pragma mark (Constants) | 25 #pragma mark (Constants) |
| 26 | 26 |
| 27 #define kPageSize 4096 | |
| 28 #if defined(__ppc__) || defined(__POWERPC__) | 27 #if defined(__ppc__) || defined(__POWERPC__) |
| 29 | 28 |
| 30 long kIslandTemplate[] = { | 29 long kIslandTemplate[] = { |
| 31 0x9001FFFC, // stw r0,-4(SP) | 30 0x9001FFFC, // stw r0,-4(SP) |
| 32 0x3C00DEAD, // lis r0,0xDEAD | 31 0x3C00DEAD, // lis r0,0xDEAD |
| 33 0x6000BEEF, // ori r0,r0,0xBEEF | 32 0x6000BEEF, // ori r0,r0,0xBEEF |
| 34 0x7C0903A6, // mtctr r0 | 33 0x7C0903A6, // mtctr r0 |
| 35 0x8001FFFC, // lwz r0,-4(SP) | 34 0x8001FFFC, // lwz r0,-4(SP) |
| 36 0x60000000, // nop ; optionally replaced | 35 0x60000000, // nop ; optionally replaced |
| 37 0x4E800420 // bctr | 36 0x4E800420 // bctr |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 71 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, | 70 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, |
| 72 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, | 71 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, |
| 73 // Now the real jump instruction | 72 // Now the real jump instruction |
| 74 0xFF, 0x25, 0x00, 0x00, 0x00, 0x00, | 73 0xFF, 0x25, 0x00, 0x00, 0x00, 0x00, |
| 75 0x00, 0x00, 0x00, 0x00, | 74 0x00, 0x00, 0x00, 0x00, |
| 76 0x00, 0x00, 0x00, 0x00 | 75 0x00, 0x00, 0x00, 0x00 |
| 77 }; | 76 }; |
| 78 | 77 |
| 79 #endif | 78 #endif |
| 80 | 79 |
| 80 #define kAllocateHigh 1 | |
| 81 #define kAllocateNormal 0 | |
| 82 | |
| 81 /************************** | 83 /************************** |
| 82 * | 84 * |
| 83 * Data Types | 85 * Data Types |
| 84 * | 86 * |
| 85 **************************/ | 87 **************************/ |
| 86 #pragma mark - | 88 #pragma mark - |
| 87 #pragma mark (Data Types) | 89 #pragma mark (Data Types) |
| 88 | 90 |
| 89 typedef struct { | 91 typedef struct { |
| 90 char instructions[sizeof(kIslandTemplate)]; | 92 char instructions[sizeof(kIslandTemplate)]; |
| 93 int allocatedHigh; | |
| 91 } BranchIsland; | 94 } BranchIsland; |
| 92 | 95 |
| 93 /************************** | 96 /************************** |
| 94 * | 97 * |
| 95 * Funky Protos | 98 * Funky Protos |
| 96 * | 99 * |
| 97 **************************/ | 100 **************************/ |
| 98 #pragma mark - | 101 #pragma mark - |
| 99 #pragma mark (Funky Protos) | 102 #pragma mark (Funky Protos) |
| 100 | 103 |
| 101 mach_error_t | 104 mach_error_t |
| 102 allocateBranchIsland( | 105 allocateBranchIsland( |
| 103 BranchIsland **island, | 106 BranchIsland **island, |
| 107 int allocateHigh, | |
| 104 void *originalFunctionAddress); | 108 void *originalFunctionAddress); |
| 105 | 109 |
| 106 mach_error_t | 110 mach_error_t |
| 107 freeBranchIsland( | 111 freeBranchIsland( |
| 108 BranchIsland *island ); | 112 BranchIsland *island ); |
| 109 | 113 |
| 110 #if defined(__ppc__) || defined(__POWERPC__) | 114 #if defined(__ppc__) || defined(__POWERPC__) |
| 111 mach_error_t | 115 mach_error_t |
| 112 setBranchIslandTarget( | 116 setBranchIslandTarget( |
| 113 BranchIsland *island, | 117 BranchIsland *island, |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 148 * | 152 * |
| 149 * Interface | 153 * Interface |
| 150 * | 154 * |
| 151 *******************************************************************************/ | 155 *******************************************************************************/ |
| 152 #pragma mark - | 156 #pragma mark - |
| 153 #pragma mark (Interface) | 157 #pragma mark (Interface) |
| 154 | 158 |
| 155 #if defined(__i386__) || defined(__x86_64__) | 159 #if defined(__i386__) || defined(__x86_64__) |
| 156 mach_error_t makeIslandExecutable(void *address) { | 160 mach_error_t makeIslandExecutable(void *address) { |
| 157 mach_error_t err = err_none; | 161 mach_error_t err = err_none; |
| 158 uintptr_t page = (uintptr_t)address & ~(uintptr_t)(kPageSize-1); | 162 vm_size_t pageSize; |
| 163 host_page_size( mach_host_self(), &pageSize ); | |
| 164 uintptr_t page = (uintptr_t)address & ~(uintptr_t)(pageSize-1); | |
| 159 int e = err_none; | 165 int e = err_none; |
| 160 e |= mprotect((void *)page, kPageSize, PROT_EXEC | PROT_READ); | 166 e |= mprotect((void *)page, pageSize, PROT_EXEC | PROT_READ | PROT_WRITE); |
| 161 e |= msync((void *)page, kPageSize, MS_INVALIDATE ); | 167 e |= msync((void *)page, pageSize, MS_INVALIDATE ); |
| 162 if (e) { | 168 if (e) { |
| 163 err = err_cannot_override; | 169 err = err_cannot_override; |
| 164 } | 170 } |
| 165 return err; | 171 return err; |
| 166 } | 172 } |
| 167 #endif | 173 #endif |
| 168 | 174 |
| 169 mach_error_t | 175 mach_error_t |
| 170 mach_override_ptr( | 176 mach_override_ptr( |
| 171 void *originalFunctionAddress, | 177 void *originalFunctionAddress, |
| (...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 229 if( err ) | 235 if( err ) |
| 230 err = vm_protect( mach_task_self(), | 236 err = vm_protect( mach_task_self(), |
| 231 (vm_address_t) originalFunctionPtr, 8, f alse, | 237 (vm_address_t) originalFunctionPtr, 8, f alse, |
| 232 (VM_PROT_DEFAULT | VM_PROT_COPY) ); | 238 (VM_PROT_DEFAULT | VM_PROT_COPY) ); |
| 233 } | 239 } |
| 234 if (err) fprintf(stderr, "err = %x %s:%d\n", err, __FILE__, __LINE__); | 240 if (err) fprintf(stderr, "err = %x %s:%d\n", err, __FILE__, __LINE__); |
| 235 | 241 |
| 236 // Allocate and target the escape island to the overriding function . | 242 // Allocate and target the escape island to the overriding function . |
| 237 BranchIsland *escapeIsland = NULL; | 243 BranchIsland *escapeIsland = NULL; |
| 238 if( !err ) | 244 if( !err ) |
| 239 » » err = allocateBranchIsland( &escapeIsland, originalFunctionAddre ss ); | 245 » » err = allocateBranchIsland( &escapeIsland, kAllocateHigh, origin alFunctionAddress ); |
| 240 if (err) fprintf(stderr, "err = %x %s:%d\n", err, __FILE__, __LI NE__); | 246 if (err) fprintf(stderr, "err = %x %s:%d\n", err, __FILE__, __LI NE__); |
| 241 | 247 |
| 242 | 248 |
| 243 #if defined(__ppc__) || defined(__POWERPC__) | 249 #if defined(__ppc__) || defined(__POWERPC__) |
| 244 if( !err ) | 250 if( !err ) |
| 245 err = setBranchIslandTarget( escapeIsland, overrideFunctionAddre ss, 0 ); | 251 err = setBranchIslandTarget( escapeIsland, overrideFunctionAddre ss, 0 ); |
| 246 | 252 |
| 247 // Build the branch absolute instruction to the escape island. | 253 // Build the branch absolute instruction to the escape island. |
| 248 long branchAbsoluteInstruction = 0; // Set to 0 just to silence warni ng. | 254 long branchAbsoluteInstruction = 0; // Set to 0 just to silence warni ng. |
| 249 if( !err ) { | 255 if( !err ) { |
| (...skipping 21 matching lines...) Expand all Loading... | |
| 271 jumpRelativeInstruction = OSSwapInt64(jumpRelativeInstruction); | 277 jumpRelativeInstruction = OSSwapInt64(jumpRelativeInstruction); |
| 272 } | 278 } |
| 273 #endif | 279 #endif |
| 274 | 280 |
| 275 // Optionally allocate & return the reentry island. This may contai n relocated | 281 // Optionally allocate & return the reentry island. This may contai n relocated |
| 276 // jmp instructions and so has all the same addressing reachability req uirements | 282 // jmp instructions and so has all the same addressing reachability req uirements |
| 277 // the escape island has to the original function, except the escape is land is | 283 // the escape island has to the original function, except the escape is land is |
| 278 // technically our original function. | 284 // technically our original function. |
| 279 BranchIsland *reentryIsland = NULL; | 285 BranchIsland *reentryIsland = NULL; |
| 280 if( !err && originalFunctionReentryIsland ) { | 286 if( !err && originalFunctionReentryIsland ) { |
| 281 » » err = allocateBranchIsland( &reentryIsland, escapeIsland); | 287 » » err = allocateBranchIsland( &reentryIsland, kAllocateHigh, escap eIsland); |
| 282 if( !err ) | 288 if( !err ) |
| 283 *originalFunctionReentryIsland = reentryIsland; | 289 *originalFunctionReentryIsland = reentryIsland; |
| 284 } | 290 } |
| 285 | 291 |
| 286 #if defined(__ppc__) || defined(__POWERPC__) | 292 #if defined(__ppc__) || defined(__POWERPC__) |
| 287 // Atomically: | 293 // Atomically: |
| 288 // o If the reentry island was allocated: | 294 // o If the reentry island was allocated: |
| 289 // o Insert the original instruction into the reentry islan d. | 295 // o Insert the original instruction into the reentry islan d. |
| 290 // o Target the reentry island at the 2nd instruction of th e | 296 // o Target the reentry island at the 2nd instruction of th e |
| 291 // original function. | 297 // original function. |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 329 (void*) ((char *)originalFunctionPtr+eatenCount), originalInstructions ); | 335 (void*) ((char *)originalFunctionPtr+eatenCount), originalInstructions ); |
| 330 // try making islands executable before planting the jmp | 336 // try making islands executable before planting the jmp |
| 331 #if defined(__x86_64__) || defined(__i386__) | 337 #if defined(__x86_64__) || defined(__i386__) |
| 332 if( !err ) | 338 if( !err ) |
| 333 err = makeIslandExecutable(escapeIsland); | 339 err = makeIslandExecutable(escapeIsland); |
| 334 if( !err && reentryIsland ) | 340 if( !err && reentryIsland ) |
| 335 err = makeIslandExecutable(reentryIsland); | 341 err = makeIslandExecutable(reentryIsland); |
| 336 #endif | 342 #endif |
| 337 if ( !err ) | 343 if ( !err ) |
| 338 atomic_mov64((uint64_t *)originalFunctionPtr, jumpRelati veInstruction); | 344 atomic_mov64((uint64_t *)originalFunctionPtr, jumpRelati veInstruction); |
| 339 | |
| 340 mach_error_t prot_err = err_none; | |
| 341 prot_err = vm_protect( mach_task_self(), | |
| 342 (vm_address_t) originalFunctionPtr, 8, fa lse, | |
| 343 (VM_PROT_READ | VM_PROT_EXECUTE) ); | |
| 344 if (prot_err) fprintf(stderr, "err = %x %s:%d\n", prot_err, __FI LE__, __LINE__); | |
| 345 } | 345 } |
| 346 #endif | 346 #endif |
| 347 | 347 |
| 348 // Clean up on error. | 348 // Clean up on error. |
| 349 if( err ) { | 349 if( err ) { |
| 350 if( reentryIsland ) | 350 if( reentryIsland ) |
| 351 freeBranchIsland( reentryIsland ); | 351 freeBranchIsland( reentryIsland ); |
| 352 if( escapeIsland ) | 352 if( escapeIsland ) |
| 353 freeBranchIsland( escapeIsland ); | 353 freeBranchIsland( escapeIsland ); |
| 354 } | 354 } |
| 355 | 355 |
| 356 return err; | 356 return err; |
| 357 } | 357 } |
| 358 | 358 |
| 359 /******************************************************************************* | 359 /******************************************************************************* |
| 360 * | 360 * |
| 361 * Implementation | 361 * Implementation |
| 362 * | 362 * |
| 363 *******************************************************************************/ | 363 *******************************************************************************/ |
| 364 #pragma mark - | 364 #pragma mark - |
| 365 #pragma mark (Implementation) | 365 #pragma mark (Implementation) |
| 366 | 366 |
| 367 /***************************************************************************//** | 367 /******************************************************************************* |
| 368 Implementation: Allocates memory for a branch island. | 368 Implementation: Allocates memory for a branch island. |
| 369 | 369 |
| 370 @param island <- The allocated island. | 370 @param island <- The allocated island. |
| 371 @param allocateHigh -> Whether to allocate the island at the en d of the | |
| 372 address space (f or use with the branch absolute | |
| 373 instruction). | |
| 371 @result <- mach_error_t | 374 @result <- mach_error_t |
| 372 | 375 |
| 373 ************************************************************************ ***/ | 376 ************************************************************************ ***/ |
| 374 | 377 |
| 375 mach_error_t | 378 mach_error_t |
| 376 allocateBranchIsland( | 379 allocateBranchIsland( |
| 377 BranchIsland **island, | 380 BranchIsland **island, |
| 381 int allocateHigh, | |
| 378 void *originalFunctionAddress) | 382 void *originalFunctionAddress) |
| 379 { | 383 { |
| 380 assert( island ); | 384 assert( island ); |
| 381 | 385 |
| 382 » assert( sizeof( BranchIsland ) <= kPageSize ); | 386 » mach_error_t» err = err_none; |
| 383 #if defined(__i386__) | 387 » |
| 384 » vm_address_t page = 0; | 388 » if( allocateHigh ) { |
| 385 » mach_error_t err = vm_allocate( mach_task_self(), &page, kPageSize, VM_F LAGS_ANYWHERE ); | 389 » » vm_size_t pageSize; |
| 386 » if( err == err_none ) { | 390 » » err = host_page_size( mach_host_self(), &pageSize ); |
| 387 » » *island = (BranchIsland*) page; | 391 » » if( !err ) { |
| 388 » » return err_none; | 392 » » » assert( sizeof( BranchIsland ) <= pageSize ); |
| 389 » } | 393 #if defined(__ppc__) || defined(__POWERPC__) |
| 390 » return err; | 394 » » » vm_address_t first = 0xfeffffff; |
| 395 » » » vm_address_t last = 0xfe000000 + pageSize; | |
| 396 #elif defined(__x86_64__) | |
| 397 » » » 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? | |
| 398 » » » vm_address_t last = 0x0; | |
| 391 #else | 399 #else |
| 392 | 400 » » » vm_address_t first = 0xffc00000; |
| 393 #if defined(__ppc__) || defined(__POWERPC__) | 401 » » » vm_address_t last = 0xfffe0000; |
| 394 » vm_address_t first = 0xfeffffff; | |
| 395 » vm_address_t last = 0xfe000000 + kPageSize; | |
| 396 #elif defined(__x86_64__) | |
| 397 » vm_address_t first = ((uint64_t)originalFunctionAddress & ~(uint64_t)((( uint64_t)1 << 31) - 1)) | ((uint64_t)1 << 31); // start in the middle of the pag e? | |
| 398 » vm_address_t last = 0x0; | |
| 399 #endif | 402 #endif |
| 400 | 403 |
| 401 » vm_address_t page = first; | 404 » » » vm_address_t page = first; |
| 402 » vm_map_t task_self = mach_task_self(); | 405 » » » int allocated = 0; |
| 406 » » » vm_map_t task_self = mach_task_self(); | |
| 407 » » » | |
| 408 » » » while( !err && !allocated && page != last ) { | |
| 403 | 409 |
| 404 » while( page != last ) { | 410 » » » » err = vm_allocate( task_self, &page, pageSize, 0 ); |
| 405 » » mach_error_t err = vm_allocate( task_self, &page, kPageSize, 0 ) ; | 411 » » » » if( err == err_none ) |
| 406 » » if( err == err_none ) { | 412 » » » » » allocated = 1; |
| 407 » » » *island = (BranchIsland*) page; | 413 » » » » else if( err == KERN_NO_SPACE ) { |
| 408 » » » return err_none; | |
| 409 } | |
| 410 » » if( err != KERN_NO_SPACE ) | |
| 411 » » » return err; | |
| 412 #if defined(__x86_64__) | 414 #if defined(__x86_64__) |
| 413 » » page -= kPageSize; | 415 » » » » » page -= pageSize; |
| 414 #else | 416 #else |
| 415 » » page += kPageSize; | 417 » » » » » page += pageSize; |
| 416 #endif | 418 #endif |
| 417 » » err = err_none; | 419 » » » » » err = err_none; |
| 420 » » » » } | |
| 421 » » » } | |
| 422 » » » if( allocated ) | |
| 423 » » » » *island = (BranchIsland*) page; | |
| 424 » » » else if( !allocated && !err ) | |
| 425 » » » » err = KERN_NO_SPACE; | |
| 426 » » } | |
| 427 » } else { | |
| 428 » » void *block = malloc( sizeof( BranchIsland ) ); | |
| 429 » » if( block ) | |
| 430 » » » *island = block; | |
| 431 » » else | |
| 432 » » » err = KERN_NO_SPACE; | |
| 418 } | 433 } |
| 419 | 434 » if( !err ) |
| 420 » return KERN_NO_SPACE; | 435 » » (**island).allocatedHigh = allocateHigh; |
| 421 #endif | 436 » |
| 437 » return err; | |
| 422 } | 438 } |
| 423 | 439 |
| 424 /***************************************************************************//** | 440 /******************************************************************************* |
| 425 Implementation: Deallocates memory for a branch island. | 441 Implementation: Deallocates memory for a branch island. |
| 426 | 442 |
| 427 @param island -> The island to deallocate. | 443 @param island -> The island to deallocate. |
| 428 @result <- mach_error_t | 444 @result <- mach_error_t |
| 429 | 445 |
| 430 ************************************************************************ ***/ | 446 ************************************************************************ ***/ |
| 431 | 447 |
| 432 mach_error_t | 448 mach_error_t |
| 433 freeBranchIsland( | 449 freeBranchIsland( |
| 434 BranchIsland *island ) | 450 BranchIsland *island ) |
| 435 { | 451 { |
| 436 assert( island ); | 452 assert( island ); |
| 437 assert( (*(long*)&island->instructions[0]) == kIslandTemplate[0] ); | 453 assert( (*(long*)&island->instructions[0]) == kIslandTemplate[0] ); |
| 438 » assert( sizeof( BranchIsland ) <= kPageSize ); | 454 » assert( island->allocatedHigh ); |
| 439 » return vm_deallocate( mach_task_self(), (vm_address_t) island, | 455 » |
| 440 » » » kPageSize ); | 456 » mach_error_t» err = err_none; |
| 457 » | |
| 458 » if( island->allocatedHigh ) { | |
| 459 » » vm_size_t pageSize; | |
| 460 » » err = host_page_size( mach_host_self(), &pageSize ); | |
| 461 » » if( !err ) { | |
| 462 » » » assert( sizeof( BranchIsland ) <= pageSize ); | |
| 463 » » » err = vm_deallocate( | |
| 464 » » » » » mach_task_self(), | |
| 465 » » » » » (vm_address_t) island, pageSize ); | |
| 466 » » } | |
| 467 » } else { | |
| 468 » » free( island ); | |
| 469 » } | |
| 470 » | |
| 471 » return err; | |
| 441 } | 472 } |
| 442 | 473 |
| 443 /***************************************************************************//** | 474 /******************************************************************************* |
| 444 Implementation: Sets the branch island's target, with an optional | 475 Implementation: Sets the branch island's target, with an optional |
| 445 instruction. | 476 instruction. |
| 446 | 477 |
| 447 @param island -> The branch island to insert target into. | 478 @param island -> The branch island to insert target into. |
| 448 @param branchTo -> The address of the target. | 479 @param branchTo -> The address of the target. |
| 449 @param instruction -> Optional instruction to execute prior to branch. Set | 480 @param instruction -> Optional instruction to execute prior to branch. Set |
| 450 to zero for nop. | 481 to zero for nop. |
| 451 @result <- mach_error_t | 482 @result <- mach_error_t |
| 452 | 483 |
| 453 ************************************************************************ ***/ | 484 ************************************************************************ ***/ |
| (...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 523 // Fill in the address. | 554 // Fill in the address. |
| 524 *((uint64_t *)(island->instructions + kJumpAddress)) = (uint64_t)branchTo; | 555 *((uint64_t *)(island->instructions + kJumpAddress)) = (uint64_t)branchTo; |
| 525 msync( island->instructions, sizeof( kIslandTemplate ), MS_INVALIDATE ); | 556 msync( island->instructions, sizeof( kIslandTemplate ), MS_INVALIDATE ); |
| 526 | 557 |
| 527 return err_none; | 558 return err_none; |
| 528 } | 559 } |
| 529 #endif | 560 #endif |
| 530 | 561 |
| 531 | 562 |
| 532 #if defined(__i386__) || defined(__x86_64__) | 563 #if defined(__i386__) || defined(__x86_64__) |
| 533 // simplistic instruction matching | |
| 534 typedef struct { | |
| 535 unsigned int length; // max 15 | |
| 536 unsigned char mask[15]; // sequence of bytes in memory order | |
| 537 unsigned char constraint[15]; // sequence of bytes in memory order | |
| 538 } AsmInstructionMatch; | |
| 539 | |
| 540 #if defined(__i386__) | |
| 541 static AsmInstructionMatch possibleInstructions[] = { | |
| 542 { 0x5, {0xFF, 0x00, 0x00, 0x00, 0x00}, {0xE9, 0x00, 0x00, 0x00, 0x00} }, // jmp 0x???????? | |
| 543 { 0x5, {0xFF, 0xFF, 0xFF, 0xFF, 0xFF}, {0x55, 0x89, 0xe5, 0xc9, 0xc3} }, // push %ebp; mov %esp,%ebp; leave; ret | |
| 544 { 0x1, {0xFF}, {0x90} }, // nop | |
| 545 { 0x1, {0xFF}, {0x55} }, // push %esp | |
| 546 { 0x2, {0xFF, 0xFF}, {0x89, 0xE5} }, // mov %esp,%ebp | |
| 547 { 0x1, {0xFF}, {0x53} }, // push %ebx | |
| 548 { 0x3, {0xFF, 0xFF, 0x00}, {0x83, 0xEC, 0x00} }, // sub 0x??, %esp | |
| 549 { 0x6, {0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00}, {0x81, 0xEC, 0x00, 0x00, 0x 00, 0x00} }, // sub 0x??, %esp with 32bit immediate | |
| 550 { 0x1, {0xFF}, {0x57} }, // push %edi | |
| 551 { 0x1, {0xFF}, {0x56} }, // push %esi | |
| 552 { 0x2, {0xFF, 0xFF}, {0x31, 0xC0} }, // xor %eax, %eax | |
| 553 { 0x3, {0xFF, 0x4F, 0x00}, {0x8B, 0x45, 0x00} }, // mov $imm(%ebp), %re g | |
| 554 { 0x3, {0xFF, 0x4C, 0x00}, {0x8B, 0x40, 0x00} }, // mov $imm(%eax-%edx) , %reg | |
| 555 { 0x4, {0xFF, 0xFF, 0xFF, 0x00}, {0x8B, 0x4C, 0x24, 0x00} }, // mov $im m(%esp), %ecx | |
| 556 { 0x5, {0xFF, 0x00, 0x00, 0x00, 0x00}, {0xB8, 0x00, 0x00, 0x00, 0x00} }, // mov $imm, %eax | |
| 557 { 0x0 } | |
| 558 }; | |
| 559 #elif defined(__x86_64__) | |
| 560 static AsmInstructionMatch possibleInstructions[] = { | |
| 561 { 0x5, {0xFF, 0x00, 0x00, 0x00, 0x00}, {0xE9, 0x00, 0x00, 0x00, 0x00} }, // jmp 0x???????? | |
| 562 { 0x1, {0xFF}, {0x90} }, // nop | |
| 563 { 0x1, {0xF8}, {0x50} }, // push %rX | |
| 564 { 0x3, {0xFF, 0xFF, 0xFF}, {0x48, 0x89, 0xE5} }, // mov %rsp,%rbp | |
| 565 { 0x4, {0xFF, 0xFF, 0xFF, 0x00}, {0x48, 0x83, 0xEC, 0x00} }, // sub 0x??, %rsp | |
| 566 { 0x4, {0xFB, 0xFF, 0x00, 0x00}, {0x48, 0x89, 0x00, 0x00} }, // move onto rbp | |
| 567 { 0x2, {0xFF, 0x00}, {0x41, 0x00} }, // push %rXX | |
| 568 { 0x2, {0xFF, 0x00}, {0x85, 0x00} }, // test %rX,%rX | |
| 569 { 0x5, {0xF8, 0x00, 0x00, 0x00, 0x00}, {0xB8, 0x00, 0x00, 0x00, 0x00} }, // mov $imm, %reg | |
| 570 { 0x3, {0xFF, 0xFF, 0x00}, {0xFF, 0x77, 0x00} }, // pushq $imm(%rdi) | |
| 571 { 0x2, {0xFF, 0xFF}, {0x31, 0xC0} }, // xor %eax, %eax | |
| 572 { 0x2, {0xFF, 0xFF}, {0x89, 0xF8} }, // mov %edi, %ea x | |
| 573 { 0x0 } | |
| 574 }; | |
| 575 #endif | |
| 576 | |
| 577 static Boolean codeMatchesInstruction(unsigned char *code, AsmInstructionMatch* instruction) | |
| 578 { | |
| 579 Boolean match = true; | |
| 580 | |
| 581 size_t i; | |
| 582 for (i=0; i<instruction->length; i++) { | |
| 583 unsigned char mask = instruction->mask[i]; | |
| 584 unsigned char constraint = instruction->constraint[i]; | |
| 585 unsigned char codeValue = code[i]; | |
| 586 | |
| 587 match = ((codeValue & mask) == constraint); | |
| 588 if (!match) break; | |
| 589 } | |
| 590 | |
| 591 return match; | |
| 592 } | |
| 593 | |
| 594 #if defined(__i386__) || defined(__x86_64__) | |
| 595 static Boolean | 564 static Boolean |
| 596 eatKnownInstructions( | 565 eatKnownInstructions( |
| 597 unsigned char *code, | 566 unsigned char *code, |
| 598 uint64_t *newInstruction, | 567 uint64_t *newInstruction, |
| 599 int *howManyEaten, | 568 int *howManyEaten, |
| 600 char *originalInstructions, | 569 char *originalInstructions, |
| 601 int *originalInstructionCount, | 570 int *originalInstructionCount, |
| 602 uint8_t *originalInstructionSizes ) | 571 uint8_t *originalInstructionSizes ) |
| 603 { | 572 { |
| 604 Boolean allInstructionsKnown = true; | 573 Boolean allInstructionsKnown = true; |
| 605 int totalEaten = 0; | 574 int totalEaten = 0; |
| 606 unsigned char* ptr = code; | |
| 607 int remainsToEat = 5; // a JMP instruction takes 5 bytes | 575 int remainsToEat = 5; // a JMP instruction takes 5 bytes |
| 608 int instructionIndex = 0; | 576 int instructionIndex = 0; |
| 577 ud_t ud_obj; | |
| 609 | 578 |
| 610 if (howManyEaten) *howManyEaten = 0; | 579 if (howManyEaten) *howManyEaten = 0; |
| 611 if (originalInstructionCount) *originalInstructionCount = 0; | 580 if (originalInstructionCount) *originalInstructionCount = 0; |
| 581 ud_init(&ud_obj); | |
| 582 #if defined(__i386__) | |
| 583 ud_set_mode(&ud_obj, 32); | |
| 584 #else | |
| 585 ud_set_mode(&ud_obj, 64); | |
| 586 #endif | |
| 587 ud_set_input_buffer(&ud_obj, code, 64); // Assume that 'code' points to at least 64bytes of data. | |
| 612 while (remainsToEat > 0) { | 588 while (remainsToEat > 0) { |
| 613 » » Boolean curInstructionKnown = false; | 589 » » if (!ud_disassemble(&ud_obj)) { |
| 614 » » | 590 » » allInstructionsKnown = false; |
| 615 » » // See if instruction matches one we know | 591 » » fprintf(stderr, "mach_override: some instructions unknown! N eed to update libudis86\n"); |
| 616 » » AsmInstructionMatch* curInstr = possibleInstructions; | 592 » » break; |
| 617 » » do { | |
| 618 » » » if ((curInstructionKnown = codeMatchesInstruction(ptr, c urInstr))) break; | |
| 619 » » » curInstr++; | |
| 620 » » } while (curInstr->length > 0); | |
| 621 » » | |
| 622 » » // if all instruction matches failed, we don't know current inst ruction then, stop here | |
| 623 » » if (!curInstructionKnown) { | |
| 624 » » » allInstructionsKnown = false; | |
| 625 » » » fprintf(stderr, "mach_override: some instructions unknow n! Need to update mach_override.c\n"); | |
| 626 » » » break; | |
| 627 } | 593 } |
| 628 | 594 |
| 629 // At this point, we've matched curInstr | 595 // At this point, we've matched curInstr |
| 630 » » int eaten = curInstr->length; | 596 » » int eaten = ud_insn_len(&ud_obj); |
| 631 » » ptr += eaten; | |
| 632 remainsToEat -= eaten; | 597 remainsToEat -= eaten; |
| 633 totalEaten += eaten; | 598 totalEaten += eaten; |
| 634 | 599 |
| 635 if (originalInstructionSizes) originalInstructionSizes[instructi onIndex] = eaten; | 600 if (originalInstructionSizes) originalInstructionSizes[instructi onIndex] = eaten; |
| 636 instructionIndex += 1; | 601 instructionIndex += 1; |
| 637 if (originalInstructionCount) *originalInstructionCount = instru ctionIndex; | 602 if (originalInstructionCount) *originalInstructionCount = instru ctionIndex; |
| 638 } | 603 } |
| 639 | 604 |
| 640 | 605 |
| 641 if (howManyEaten) *howManyEaten = totalEaten; | 606 if (howManyEaten) *howManyEaten = totalEaten; |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 682 uint32_t offset = (uintptr_t)originalFunction - (uintptr _t)escapeIsland; | 647 uint32_t offset = (uintptr_t)originalFunction - (uintptr _t)escapeIsland; |
| 683 uint32_t *jumpOffsetPtr = (uint32_t*)((uintptr_t)instruc tionsToFix + 1); | 648 uint32_t *jumpOffsetPtr = (uint32_t*)((uintptr_t)instruc tionsToFix + 1); |
| 684 *jumpOffsetPtr += offset; | 649 *jumpOffsetPtr += offset; |
| 685 } | 650 } |
| 686 | 651 |
| 687 originalFunction = (void*)((uintptr_t)originalFunction + instruc tionSizes[index]); | 652 originalFunction = (void*)((uintptr_t)originalFunction + instruc tionSizes[index]); |
| 688 escapeIsland = (void*)((uintptr_t)escapeIsland + instructionSize s[index]); | 653 escapeIsland = (void*)((uintptr_t)escapeIsland + instructionSize s[index]); |
| 689 instructionsToFix = (void*)((uintptr_t)instructionsToFix + instr uctionSizes[index]); | 654 instructionsToFix = (void*)((uintptr_t)instructionsToFix + instr uctionSizes[index]); |
| 690 } | 655 } |
| 691 } | 656 } |
| 692 #endif | |
| 693 | 657 |
| 694 #if defined(__i386__) | 658 #if defined(__i386__) |
| 695 __asm( | 659 __asm( |
| 696 ".text;" | 660 ".text;" |
| 697 ".align 2, 0x90;" | 661 ".align 2, 0x90;" |
| 698 "_atomic_mov64:;" | 662 "_atomic_mov64:;" |
| 699 " pushl %ebp;" | 663 " pushl %ebp;" |
| 700 " movl %esp, %ebp;" | 664 " movl %esp, %ebp;" |
| 701 " pushl %esi;" | 665 " pushl %esi;" |
| 702 " pushl %ebx;" | 666 " pushl %ebx;" |
| (...skipping 25 matching lines...) Expand all Loading... | |
| 728 ); | 692 ); |
| 729 #elif defined(__x86_64__) | 693 #elif defined(__x86_64__) |
| 730 void atomic_mov64( | 694 void atomic_mov64( |
| 731 uint64_t *targetAddress, | 695 uint64_t *targetAddress, |
| 732 uint64_t value ) | 696 uint64_t value ) |
| 733 { | 697 { |
| 734 *targetAddress = value; | 698 *targetAddress = value; |
| 735 } | 699 } |
| 736 #endif | 700 #endif |
| 737 #endif | 701 #endif |
| OLD | NEW |