From 7880e647f5ec0ce9fb14b7e4e3a9e301654f38ef Mon Sep 17 00:00:00 2001 From: nganhkhoa Date: Fri, 2 Jun 2023 12:05:03 +0700 Subject: [PATCH] clean code --- research/custom_loader/b.cc | 106 ++++++++++++++++++++++-------------- 1 file changed, 66 insertions(+), 40 deletions(-) diff --git a/research/custom_loader/b.cc b/research/custom_loader/b.cc index 8fbf73b..682e877 100644 --- a/research/custom_loader/b.cc +++ b/research/custom_loader/b.cc @@ -37,17 +37,10 @@ void set_cwd(const char *const *envp) { const uint32_t magic64 = 0xfeedfacf; const uint32_t magic32 = 0xfeedface; -struct ProgramVars { - void *mh; // mach_header or mach_header64 - int *NXArgcPtr; - const char ***NXArgvPtr; - const char ***environPtr; - const char **__prognamePtr; -}; - struct libcache_item { void *header; void *trie; + uint32_t trie_size; uint32_t hash; }; @@ -79,7 +72,14 @@ uint32_t fnv_hash(const char *str) { return h; } -uint32_t calculate_libname_hash(const char *name) { +// calculate the hash to search +// _dyld_get_image_name returns the full path to the library +// while the static path in LC_DYLIB (and such) could be relative +// we should expand the path to fullpath to correctly compute the hash +// +// the hardest part is the @rpath, because there can be many LC_RPATH +// and @rpath can also reference @loader_path +uint32_t calculate_libname_hash(const libcache *cache, const char *name) { uint32_t hash; uint32_t (*hash_func)(const char *) = fnv_hash; if (name[0] == '.') { @@ -101,7 +101,12 @@ uint32_t calculate_libname_hash(const char *name) { return hash; } +// dummy no sus function to look for dyld header +// i don't know if dyld_stub_binder should be better +// because if they are not familiar with dyld +// they would not suspect dyld_stub_binder inside modern macho extern "C" uint32_t dyld_get_sdk_version(const mach_header *mh); +void exported_from_c(); void decode_uleb128(char *&addr, uint32_t *ret) { uint32_t result = 0; @@ -377,7 +382,7 @@ void *find_in_reexport(struct libcache *cache, struct libcache_item *lib, } uint32_t name_offset = *((uint32_t *)ptr + 2); char *name = (char *)ptr + name_offset; - uint32_t hash = calculate_libname_hash(name); + uint32_t hash = calculate_libname_hash(cache, name); for (int j = 0; j < cache->size; j++) { struct libcache_item reexport = cache->libs[j]; if (reexport.hash != hash) { @@ -397,14 +402,13 @@ void *find_in_lib(struct libcache *cache, struct libcache_item *lib, void *direct = find_in_export_trie(lib->header, lib->trie, symbol); if (direct) return direct; - // we cannot find in directly exported trie, so we loop through all reexport - // libs + // cannot find in directly exported trie, loop through all reexport libs return find_in_reexport(cache, lib, symbol); } void *custom_dlsym(struct libcache *cache, const char *libname, const char *symbol) { - uint32_t hash = calculate_libname_hash(libname); + uint32_t hash = calculate_libname_hash(cache, libname); for (int i = 0; i < cache->size; i++) { struct libcache_item cache_lib = cache->libs[i]; if (cache_lib.hash == hash) { @@ -453,6 +457,14 @@ int hook_printf(const char *format, ...) { return status; } +struct ProgramVars { + void *mh; // mach_header or mach_header64 + int *NXArgcPtr; + const char ***NXArgvPtr; + const char ***environPtr; + const char **__prognamePtr; +}; + __attribute__((constructor)) static void bruh(int argc, const char *const argv[], const char *const envp[], const char *const apple[], const struct ProgramVars *vars) { @@ -465,10 +477,11 @@ bruh(int argc, const char *const argv[], const char *const envp[], const void *thislib = find_header((void *)bruh); // Find dyld lib (mapped) file using a no-sus function const void *libdyld = find_header((void *)dyld_get_sdk_version); - uint32_t libsystem_hash = - calculate_libname_hash("/usr/lib/libSystem.B.dylib"); - struct libcache cache = {0, nlib, main, thislib, libdyld}; + struct libcache cache = {0, 0, (void *)main, (void *)thislib, + (void *)libdyld}; + uint32_t libsystem_hash = + calculate_libname_hash(&cache, "/usr/lib/libSystem.B.dylib"); // From libdyld header, we can list exports table // to find all function we want to use @@ -511,41 +524,54 @@ bruh(int argc, const char *const argv[], const char *const envp[], (dyld_get_image_name_t)find_in_export_trie(libdyld, libdyld_export_trie, "__dyld_get_image_name"); - uint32_t nlib = dyld_image_count_func(); - struct libcache_item *liblist = - (struct libcache_item *)malloc(sizeof(struct libcache_item) * nlib); - cache->libs = liblist; + cache.size = dyld_image_count_func(); + cache.libs = + (struct libcache_item *)malloc(sizeof(struct libcache_item) * cache.size); for (int i = 0; i < cache.size; i++) { void *header = dyld_get_image_header_func(i); char *name = dyld_get_image_name_func(i); cache.libs[i].header = header; cache.libs[i].trie = get_export_trie(header, trie_size); - cache.libs[i].hash = calculate_libname_hash(name); - printf("%s %x\n", name, cache.libs[i].hash); + cache.libs[i].trie_size = trie_size; + cache.libs[i].hash = calculate_libname_hash(&cache, name); + printf("%p %s\n", header, name); } - // { // test search using name - // void* printf_func = custom_dlsym(&cache, "/usr/lib/libSystem.B.dylib", - // "_printf"); printf("Indirect search: Found=%p Expected=%p\n", - // printf_func, printf); // dump_export_trie_of("/usr/lib/system/libsystem_c.dylib", &cache, "../scripts/libsystem_c_export_trie.bin"); - // void* vm_protect_func = custom_dlsym(&cache, - // "/usr/lib/libSystem.B.dylib", "_vm_protect"); printf("Indirect search: - // Found=%p Expected=%p\n", vm_protect_func, vm_protect); - // } + if (false) { // test search using name + void *printf_func = + custom_dlsym(&cache, "/usr/lib/libSystem.B.dylib", "_printf"); + printf("Indirect search: Found=%p Expected=%p\n", printf_func, printf); - { // test search using hash of name - // void* printf_func = custom_dlsym(&cache, libsystem_hash, "_printf"); - // printf("Indirect search: Found=%p Expected=%p\n", printf_func, printf); + void *vm_protect_func = + custom_dlsym(&cache, "/usr/lib/libSystem.B.dylib", "_vm_protect"); + printf("Indirect search: Found=%p Expected=%p\n", vm_protect_func, + vm_protect); - // void* vm_protect_func = custom_dlsym(&cache, libsystem_hash, - // "_vm_protect"); printf("Indirect search: Found=%p Expected=%p\n", - // vm_protect_func, vm_protect); - - void *func_c = + // using relative path + void *func_c_1 = custom_dlsym(&cache, "./out/libb.dylib", "__Z15exported_from_cv"); - printf("Indirect search: Found=%p Expected=%p\n", func_c, 0); + printf("Indirect search: Found=%p Expected=%p\n", func_c_1, + exported_from_c); + + // using rpath + void *func_c_2 = + custom_dlsym(&cache, "@rpath/libb.dylib", "__Z15exported_from_cv"); + printf("Indirect search: Found=%p Expected=%p\n", func_c_2, + exported_from_c); + } + + if (false) { // test search using hash of name + void *printf_func = custom_dlsym(&cache, libsystem_hash, "_printf"); + printf("Indirect search: Found=%p Expected=%p\n", printf_func, printf); + + void *vm_protect_func = custom_dlsym(&cache, libsystem_hash, "_vm_protect"); + printf("Indirect search: Found=%p Expected=%p\n", vm_protect_func, + vm_protect); + + void *realpath_func = custom_dlsym(&cache, libsystem_hash, "_realpath$DARWIN_EXTSN"); + printf("Indirect search: Found=%p Expected=%p\n", realpath_func, realpath); } // now we have function to find exported symbols @@ -642,5 +668,5 @@ bruh(int argc, const char *const argv[], const char *const envp[], vm_protect_func(mach_task_self_func(), start_page, 0x4000, 0, VM_PROT_READ); } - free(liblist); + free(cache.libs); }