const struct section_64 * getsectbyname( const char *segname, const char *sectname) { struct mach_header_64 *mhp = _NSGetMachExecuteHeader(); return(getsectbynamefromheader_64(mhp, segname, sectname)); }
GSList* mono_w32process_get_modules (pid_t pid) { GSList *ret = NULL; MonoW32ProcessModule *mod; guint32 count; int i = 0; if (pid != getpid ()) return NULL; count = _dyld_image_count (); for (i = 0; i < count; i++) { #if SIZEOF_VOID_P == 8 const struct mach_header_64 *hdr; const struct section_64 *sec; #else const struct mach_header *hdr; const struct section *sec; #endif const char *name; name = _dyld_get_image_name (i); #if SIZEOF_VOID_P == 8 hdr = (const struct mach_header_64*)_dyld_get_image_header (i); sec = getsectbynamefromheader_64 (hdr, SEG_DATA, SECT_DATA); #else hdr = _dyld_get_image_header (i); sec = getsectbynamefromheader (hdr, SEG_DATA, SECT_DATA); #endif /* Some dynlibs do not have data sections on osx (#533893) */ if (sec == 0) continue; mod = g_new0 (MonoW32ProcessModule, 1); mod->address_start = GINT_TO_POINTER (sec->addr); mod->address_end = GINT_TO_POINTER (sec->addr+sec->size); mod->perms = g_strdup ("r--p"); mod->address_offset = 0; mod->device = makedev (0, 0); mod->inode = i; mod->filename = g_strdup (name); if (g_slist_find_custom (ret, mod, mono_w32process_module_equals) == NULL) { ret = g_slist_prepend (ret, mod); } else { mono_w32process_module_free (mod); } } return g_slist_reverse (ret); }
/* * This routine returns the a pointer to the data for the named section in the * named segment if it exist in the 64-bit mach header passed to it. Also it * returns the size of the section data indirectly through the pointer size. * Otherwise it returns zero for the pointer and the size. */ char * getsectdatafromheader_64( struct mach_header_64 *mhp, const char *segname, const char *sectname, unsigned long *size) { const struct section_64 *sp; sp = getsectbynamefromheader_64(mhp, segname, sectname); if(sp == NULL) { *size = 0; return(NULL); } *size = sp->size; return((char *)((uintptr_t)(sp->addr))); }
/* * This routine returns the a pointer to the data for the named section in the * named segment if it exist in the named Framework. Also it returns the size * of the section data indirectly through the pointer size. Otherwise it * returns zero for the pointer and the size. The last component of the path * of the Framework is passed as FrameworkName. */ void * getsectdatafromFramework( const char *FrameworkName, const char *segname, const char *sectname, unsigned long *size) { uint32_t i, n; uintptr_t vmaddr_slide; #ifndef __LP64__ struct mach_header *mh; const struct section *s; #else /* defined(__LP64__) */ struct mach_header_64 *mh; const struct section_64 *s; #endif /* defined(__LP64__) */ char *name, *p; n = _dyld_image_count(); for(i = 0; i < n ; i++) { name = _dyld_get_image_name(i); p = strrchr(name, '/'); if(p != NULL && p[1] != '\0') name = p + 1; if(strcmp(name, FrameworkName) != 0) continue; mh = _dyld_get_image_header(i); vmaddr_slide = _dyld_get_image_vmaddr_slide(i); #ifndef __LP64__ s = getsectbynamefromheader(mh, segname, sectname); #else /* defined(__LP64__) */ s = getsectbynamefromheader_64(mh, segname, sectname); #endif /* defined(__LP64__) */ if(s == NULL) { *size = 0; return(NULL); } *size = s->size; return((void *)(s->addr + vmaddr_slide)); } *size = 0; return(NULL); }
/* * iterate over __cstring section to find location of m3u and m3u8 strings, and patch'em! * could be better :-) */ int find_and_patch_addresses(struct header_info *hi) { // get pointer to the __cstring section const struct section_64 *cstring_section = getsectbynamefromheader_64(hi->mh, "__TEXT", "__cstring"); // header values do not have ASLR slide so fix it mach_vm_address_t cstring_addr = cstring_section->addr + hi->aslr_slide; // search for the addresses of the right strings to be patched char *cstring_mem = (char*)cstring_addr; int index = 0; for (uint64_t w = 0 ; w < cstring_section->size; w++) { // match m3u if (*(int*)cstring_mem == 0x0075336d) { mach_vm_address_t patch_addr = cstring_addr + w; hi->patch_addresses[index++] = patch_addr; DEBUG_MSG("Found m3u address to be patched %p\n", (void*)patch_addr); if (patchmemory(patch_addr) != 0) { ERROR_MSG("Failed to patch m3u."); return -1; } } // match first bytes of m3u8 else if (*(int*)cstring_mem == 0x3875336d) { mach_vm_address_t patch_addr = cstring_addr + w; hi->patch_addresses[index++] = patch_addr; DEBUG_MSG("Found m3u8 address to be patched %p\n", (void*)patch_addr); if (patchmemory(patch_addr) != 0) { ERROR_MSG("Failed to patch m3u8."); return -1; } } // move to the next byte in the array cstring_mem++; } return 0; }
primitiveExecutableModulesAndOffsets(void) { const struct mach_header *h; const struct mach_header_64 *h64; sqInt i; const char *name; char *nameObjData; sqInt nimages; sqInt resultObj; const struct section *s; const struct section_64 *s64; usqIntptr_t size; usqIntptr_t slide; usqIntptr_t start; sqInt valueObj; # if MAC_OS_X_VERSION_MIN_REQUIRED <= MAC_OS_X_VERSION_10_4 /* _dyld_present was deprecated in 10.5 */ if (!(_dyld_present())) { return primitiveFail(); } # endif /* MAC_OS_X_VERSION_MIN_REQUIRED <= MAC_OS_X_VERSION_10_4 */ nimages = _dyld_image_count(); resultObj = instantiateClassindexableSize(classArray(), nimages * 4); if (resultObj == 0) { return primitiveFail(); } pushRemappableOop(resultObj); for (i = 0; i < nimages; i += 1) { /* impossible start & size */ start = (size = -1); name = _dyld_get_image_name(i); slide = _dyld_get_image_vmaddr_slide(i); # if __x86_64__ h64 = (const struct mach_header_64 *)_dyld_get_image_header(i); if (!(h64 == null)) { s64 = getsectbynamefromheader_64(h64,SEG_TEXT,SECT_TEXT); if (!(s64 == null)) { start = s64->addr; size = s64->size; } } # else /* __x86_64__ */ h = _dyld_get_image_header(i); if (!(h == null)) { s = getsectbynamefromheader(h,SEG_TEXT,SECT_TEXT); if (!(s == null)) { start = s->addr; size = s->size; } } # endif /* __x86_64__ */ valueObj = instantiateClassindexableSize(classString(), strlen(name)); if (failed()) { popRemappableOop(); return primitiveFail(); } storePointerofObjectwithValue(i * 4, topRemappableOop(), valueObj); nameObjData = arrayValueOf(valueObj); memcpy(nameObjData, name, strlen(name)); valueObj = (BytesPerWord == 8 ? signed64BitIntegerFor(slide) : signed32BitIntegerFor(slide)); if (failed()) { popRemappableOop(); return primitiveFail(); } storePointerofObjectwithValue((i * 4) + 1, topRemappableOop(), valueObj); /* begin positiveMachineIntegerFor: */ valueObj = (BytesPerWord == 8 ? positive64BitIntegerFor(start) : positive32BitIntegerFor(start)); if (failed()) { popRemappableOop(); return primitiveFail(); } storePointerofObjectwithValue((i * 4) + 2, topRemappableOop(), valueObj); /* begin positiveMachineIntegerFor: */ valueObj = (BytesPerWord == 8 ? positive64BitIntegerFor(size) : positive32BitIntegerFor(size)); if (failed()) { popRemappableOop(); return primitiveFail(); } storePointerofObjectwithValue((i * 4) + 3, topRemappableOop(), valueObj); } resultObj = popRemappableOop(); return popthenPush(1, resultObj); }
void loaderMach(Desasembleur* desas, Fichier* fichier) { char* chemin = fichier->chemin; int fd = open(chemin, O_RDONLY); struct stat stat_buf; fstat(fd, &stat_buf); size_t size = stat_buf.st_size; /*============================= chargement en mémoire====================*/ void* debutReel = mmap(0, size, PROT_READ | PROT_WRITE, MAP_FILE | MAP_PRIVATE, fd, 0); DISASM* prog = desas->disasm; struct fat_header* fat = (struct fat_header*) debutReel; if (fat->magic == FAT_CIGAM) { // du coup ça m apprend que mon processeur est un little-endian // en effet, apres recherche, les intels sont little-endien, les motorola sont big-endian printf("c est un fat binary : je ne peux de le desassembler\n(dans un prochaine version sans doute...)\n"); exit(EXIT_FAILURE); } // unsigned long addr = (unsigned long) debutReel; // // // The first bytes of a Mach-O file comprise its header //// struct mach_header_64 *mh = (struct mach_header_64 *) addr; // // // Load commands follow the header // addr += sizeof (struct mach_header_64); // //// printf("There are %d load commands\n", mh->ncmds); // // int fini = 0; // unsigned long debutVirtuel; // unsigned long taille; // while (!fini) { // struct load_command *lc = (struct load_command *) addr; // if (lc->cmd == LC_SEGMENT_64) { // struct segment_command_64 *sc = (struct segment_command_64 *) addr; // if (strcmp(sc->segname, "__TEXT") == 0) { // unsigned long addrSec = addr + sizeof (struct segment_command_64); // while (!fini) { // il y a forcement un __text dans ce cas // struct section_64* sec = (struct section_64*) addrSec; // addrSec += sizeof (struct section_64); // if (strcmp(sec->sectname, "__text") == 0) { // fini = 1; // debutVirtuel = 0x100000000 + sec->offset; // /*+ sizeof (struct mach_header_64)*/ + (unsigned long) debutReel; //// printf("début du bloc : 0x%lx\n", debutVirtuel); // taille = sec->size; //// printf("taille du bloc : 0x%lx\n", taille); // } // } // } // } // //avance a la prochaine load_command // addr += lc->cmdsize; // } //=============================================================== const struct section_64* section = getsectbynamefromheader_64(debutReel, "__TEXT", "__text"); unsigned long debutVirtuel = section->addr; unsigned long taille = section->size; desas->debutVirtuel = debutVirtuel; unsigned long pev; unsigned long addr = (unsigned long) debutReel + sizeof (struct mach_header_64); int fini = 0; while (!fini) { struct load_command *lc = (struct load_command *) addr; if (lc->cmd == LC_UNIXTHREAD) { struct lecteurRegistre* t = (struct lecteurRegistre*) addr; pev = t->state.uts.ts64.__rip; initialiseRegistre(desas->proc, t->state); fini = 1; } addr += lc->cmdsize; } unsigned long per = ((unsigned long) debutReel) + pev - (debutVirtuel - section->offset); prog->EIP = (UIntPtr) per; prog->Archi = 64; prog->Options = Tabulation + NasmSyntax + PrefixedNumeral + ShowSegmentRegs; prog->VirtualAddr = pev; prog->SecurityBlock = (unsigned int) (taille - (pev - debutVirtuel)); // printf("\nDone.\n\n"); close(fd); return; }