inline void drawEdgeAlignTextY(CSkPainter *p, int px, int py, const QString &text) { double offset = 4; int w, h; trfGetScreenSize(w, h); setSetFontColor(FONT_GRID, p); if (IS_NEAR(py, 0, 2)) { p->renderText(px, 0, offset, text, RT_BOTTOM); } else if (IS_NEAR(py, h, 2)) { p->renderText(px, h, offset, text, RT_TOP); } }
inline void drawEdgeAlignTextX(CSkPainter *p, int px, int py, const QString &text) { double offset = 4; int w, h; trfGetScreenSize(w, h); setSetFontColor(FONT_GRID, p); if (IS_NEAR(px, 0, 2)) { p->renderText(0, py, offset, text, RT_RIGHT); } else if (IS_NEAR(px, w, 2)) { p->renderText(w, py, offset, text, RT_LEFT); } }
void throw_hook(void *orig, void *repl, void **orig_ptr) { //__DBG("throw_hook: (%p)\n", orig); opst x; #ifdef __x86_64__ x.a = 0xb848; // mov rax, target x.c = 0xc350; // pop rax; ret #elif __i386__ x.a = 0xE9; // abs jump #endif pthread_mutex_lock(&hook_lck); void *tramp = zalloc(&zone_free_list); int hook_size = sizeof(opst); #ifdef __x86_64__ #ifdef __x86_64__COMPACT_HOOK opst_compact xc; vm_address_t nalloc=0; xc.a = 0xE9; if (IS_NEAR(orig,repl)) { printf("no trampoline needed for short jump to %p from %p\n", repl, orig); hook_size = sizeof(opst_compact); } else if (( nalloc = find_near((vm_address_t)orig)) != 0) { printf("allocated trampoline at %p\n", nalloc); hook_size = sizeof(opst_compact); x.b = (native_word_t) repl - ABSJUMP_SUB(orig); memcpy((void*)nalloc, &x, sizeof(x)); repl = (void*) nalloc; assert(IS_NEAR(orig,repl)); } #endif #endif // orig_ptr size_t eaten = eat_instructions(orig, hook_size); if (!eaten) { printf("throw_hook: eaten = 0, couldn't analyse function to hook\n"); goto out; } x.b = (native_word_t) repl - ABSJUMP_SUB(orig); vm_protect(mach_task_self_, (vm_address_t)orig, PAGE_SIZE, 0, VM_PROT_ALL); vm_protect(mach_task_self_, (vm_address_t)orig+sizeof(opst), PAGE_SIZE, 0, VM_PROT_ALL); #ifdef __x86_64__ #ifdef __x86_64__COMPACT_HOOK if ( hook_size == sizeof(opst_compact) ) { xc.b = (uint32_t) (repl - ABSJUMP_SUB_COMPACT(orig)); memcpy(tramp, orig, eaten); memset(orig, 0x90, eaten); memcpy(orig, &xc, sizeof(opst_compact)); } else #endif #endif { memcpy(tramp, orig, eaten); memset(orig, 0x90, eaten); memcpy(orig, &x, sizeof(opst)); } x.b = (native_word_t) (orig + eaten) - ABSJUMP_SUB(tramp+eaten); memcpy(tramp+eaten, &x, sizeof(opst)); vm_protect(mach_task_self_, (vm_address_t)orig, PAGE_SIZE, 0, VM_PROT_READ|VM_PROT_EXECUTE); vm_protect(mach_task_self_, (vm_address_t)orig+sizeof(opst), PAGE_SIZE, 0, VM_PROT_READ|VM_PROT_EXECUTE); if (orig_ptr) { *orig_ptr = tramp; } out: pthread_mutex_unlock(&hook_lck); }
vm_address_t find_near(vm_address_t addr) { struct current_zone* cur = &zbg; struct current_zone* prev = NULL; while (cur) { if (cur->zone_free_list && IS_NEAR(addr,cur->zone_free_list)) { vm_address_t rtn = (vm_address_t)zalloc(&cur->zone_free_list); if (prev && !cur->zone_free_list) { prev->list_next = cur->list_next; free(cur); } printf("got NEAR tramp\n"); return rtn; } prev = cur; cur = cur->list_next; } cur = &zbg; printf("allocating new near zone\n"); kern_return_t kr = KERN_SUCCESS; vm_size_t size = 0; vm_size_t old_size = 0; vm_address_t old_address = 0; vm_address_t address = addr - ((1ULL << 31ULL) - 1ULL); while (1) { mach_msg_type_number_t count; struct vm_region_submap_info_64 info; uint32_t nesting_depth; count = VM_REGION_SUBMAP_INFO_COUNT_64; kr = vm_region_recurse_64(mach_task_self_, &address, &size, &nesting_depth, (vm_region_info_64_t)&info, &count); if (kr == KERN_INVALID_ADDRESS) { break; } else if (kr) { mach_error("vm_region:", kr); break; /* last region done */ } if (info.is_submap) { nesting_depth++; } else { // printf("near_region[%p]: %p -> %p (%lx bytes)\n", addr, (void*)address, (void*)(address+size), size); if (old_address && old_address + old_size < address) { //printf("GOT SPACE_region[%p]: %p -> %p (%lx bytes)\n", addr, (void*)address, (void*)(address+size), size); if ((IS_NEAR(addr, old_address+old_size))) { if (ZONE_SIZE % 2 || ZONE_SIZE < sizeof(native_word_t)) { //puts("zalloc error: zone size must be a multiple of 2 and bigger than sizeof(native_word_t)"); exit(-1); } native_word_t* szfl = (native_word_t*)old_address + old_size; vm_allocate(mach_task_self_, (vm_address_t*)&szfl, PAGE_SIZE, 0); if (!szfl) { if (kr == KERN_INVALID_ADDRESS) { return 0; } continue; } vm_protect(mach_task_self_, (vm_address_t)szfl, PAGE_SIZE, 0, VM_PROT_ALL); if (cur->zone_free_list) { while (cur->list_next) { cur = cur->list_next; if (!cur->zone_free_list) { break; } } if (cur->zone_free_list) { cur->list_next = malloc(sizeof(struct current_zone)); cur->list_next->zone_free_list = 0; cur->list_next->list_next = 0; cur = cur->list_next; assert(cur->zone_free_list == 0); } } for (int i = 0; i < (PAGE_SIZE/ZONE_SIZE); i++) { zfree((void*)((native_word_t)&szfl[i*(ZONE_SIZE/sizeof(native_word_t))]), &cur->zone_free_list); } return (vm_address_t)zalloc(&cur->zone_free_list); } } old_address = address; old_size = size; address += size; } } return 0; }