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 |