diff --git a/research/custom_loader/b.cc b/research/custom_loader/b.cc index 20892c7..6f47ffb 100644 --- a/research/custom_loader/b.cc +++ b/research/custom_loader/b.cc @@ -20,6 +20,22 @@ int custom_strcmp(const char *p1, const char *p2) { return c1 - c2; } +int custom_strncmp(const char *s1, const char *s2, register size_t n) +{ + register unsigned char u1, u2; + + while (n-- > 0) + { + u1 = (unsigned char) *s1++; + u2 = (unsigned char) *s2++; + if (u1 != u2) + return u1 - u2; + if (u1 == '\0') + return 0; + } + return 0; +} + void set_cwd(const char *const *envp) { while (*envp) { // PWD= @@ -208,6 +224,9 @@ void print_macho_summary(const void *header) { } const uint32_t ncmds = *((uint32_t *)header + 4); + uint64_t linkedit_vmaddr; + uint64_t linkedit_fileoffset; + uint64_t slide; printf("parsing macho at %p\n", header); printf("ncmds %x\n", ncmds); for (int i = 0; i < ncmds; i++) { @@ -226,8 +245,11 @@ void print_macho_summary(const void *header) { uint64_t fileoffset = *((uint64_t *)ptr + 5); uint64_t filesize = *((uint64_t *)ptr + 6); if (custom_strcmp(name, "__TEXT") == 0) { - uint64_t slide = (uint64_t)header - vmaddr; + slide = (uint64_t)header - vmaddr; printf(" --- slide=0x%llx ---\n", slide); + } else if (custom_strcmp(name, "__LINKEDIT") == 0) { + linkedit_vmaddr = vmaddr; + linkedit_fileoffset = fileoffset; } printf(" Segment %s\n", name); printf(" vmaddr=0x%llx fileoffset=0x%llx\n", vmaddr, fileoffset); @@ -244,6 +266,31 @@ void print_macho_summary(const void *header) { printf(" addr=0x%llx size=0x%llx fileoffset=0x%x\n", addr, size, fileoffset); } } + if (cmd == LC_SYMTAB) { + uint32_t symoff = *((uint32_t *)ptr + 2); + uint32_t nsym = *((uint32_t *)ptr + 3); + uint32_t stroff = (*((uint32_t *)ptr + 4)); + uint32_t strsize = *((uint32_t *)ptr + 5); + + struct symbol_t { + uint32_t strx; + uint8_t flags; + uint8_t sect; + uint16_t desc; + uint64_t value; + }; + + uint64_t symtab_start = (uint64_t)symoff - linkedit_fileoffset + slide + linkedit_vmaddr; + uint64_t stroff_start = (uint64_t)stroff - linkedit_fileoffset + slide + linkedit_vmaddr; + + printf(" symtab: offset=0x%x nsym=0x%x\n", symoff, nsym); + for (int j = 0; j < nsym; j++) { + struct symbol_t* symtab = (struct symbol_t*)symtab_start; + struct symbol_t symbol = symtab[j]; + char* name = (char*)stroff_start + symbol.strx; + printf(" %s %llx => %p\n", name, symbol.value, (void*)(symbol.value + slide)); + } + } if (cmd == LC_REEXPORT_DYLIB) { uint32_t name_offset = *((uint32_t *)ptr + 2); char *name = (char *)ptr + name_offset; @@ -524,6 +571,79 @@ void dump_export_trie_of(const char* libname, const libcache* cache, const char* } } +void* find_in_symtab(const libcache_item* lib, const char* find) { + void* header = lib->header; + const uint32_t magic = *(uint32_t *)header; + char *ptr = (char *)header; + if (magic == magic64) { + ptr += 0x20; + } else { + ptr += 0x20 - 0x4; + } + + const uint32_t ncmds = *((uint32_t *)header + 4); + char* command_ptr = ptr; + + uint64_t linkedit_vmaddr; + uint64_t linkedit_fileoffset; + uint64_t slide; + for (int i = 0; i < ncmds; i++) { + const uint32_t cmd = *((uint32_t *)ptr + 0); + const uint32_t cmdsize = *((uint32_t *)ptr + 1); + if (cmd == LC_SYMTAB) { + uint32_t symoff = *((uint32_t *)ptr + 2); + uint32_t nsym = *((uint32_t *)ptr + 3); + uint32_t stroff = (*((uint32_t *)ptr + 4)); + uint32_t strsize = *((uint32_t *)ptr + 5); + + struct symbol_t { + uint32_t strx; + uint8_t flags; + uint8_t sect; + uint16_t desc; + uint64_t value; + }; + + uint64_t symtab_start = (uint64_t)symoff - linkedit_fileoffset + slide + linkedit_vmaddr; + uint64_t stroff_start = (uint64_t)stroff - linkedit_fileoffset + slide + linkedit_vmaddr; + + for (int j = 0; j < nsym; j++) { + struct symbol_t* symtab = (struct symbol_t*)symtab_start; + struct symbol_t symbol = symtab[j]; + char* name = (char*)stroff_start + symbol.strx; + if (custom_strcmp(name, find) == 0) { + return (void*)(symbol.value + slide); + } + } + break; + } + if (cmd == LC_SEGMENT_64) { + char *name = (char *)((uint64_t *)ptr + 1); + uint64_t vmaddr = *((uint64_t *)ptr + 3); + uint64_t fileoffset = *((uint64_t *)ptr + 5); + if (custom_strcmp(name, "__TEXT") == 0) { + slide = (uint64_t)header - vmaddr; + } else if (custom_strcmp(name, "__LINKEDIT") == 0) { + linkedit_vmaddr = vmaddr; + linkedit_fileoffset = fileoffset; + } + } + ptr += cmdsize; + } + return 0; +} + +void* find_in_symtab(const char* libname, const libcache* cache, const char* find) { + uint32_t hash = calculate_libname_hash(cache, libname); + struct libcache_item *cache_lib = 0; + for (int i = 0; i < cache->size; i++) { + if (cache->libs[i].hash == hash) { + cache_lib = &(cache->libs[i]); + break; + } + } + return find_in_symtab(cache_lib, find); +} int hook_printf(const char *format, ...) { va_list args; va_start(args, format); @@ -561,8 +681,15 @@ bruh(int argc, const char *const argv[], const char *const envp[], build_cache(cache, (void *)(vars->mh)); // dump_export_trie_of( - // "/usr/lib/system/libsystem_c.dylib", &cache, - // "../scripts/libsystem_c_export_trie.bin"); + // "/usr/lib/libobjc.A.dylib", &cache, + // "../scripts/lib_objc_export_trie.bin"); + + // dump_macho( + // "/usr/lib/libobjc.A.dylib", &cache, + // "../scripts/lib_objc_symtab.bin"); + + // struct libcache_item* objc = get_libcache_with_name(&cache, "/usr/lib/libobjc.A.dylib"); + // print_macho_summary(objc->header); // test(cache); @@ -621,9 +748,6 @@ void build_cache(struct libcache& cache, void* main) { printf("lib header at %p\n", thislib); printf("libdyld header at %p\n", libdyld); - // print_macho_summary(main); - // print_macho_summary(thislib); - uint32_t trie_size; void *libdyld_export_trie = get_export_trie(libdyld, trie_size);