diff --git a/research/custom_loader/b.cc b/research/custom_loader/b.cc index 679b626..1b66cfe 100644 --- a/research/custom_loader/b.cc +++ b/research/custom_loader/b.cc @@ -72,17 +72,18 @@ struct libcache { void *main; void *thislib; void *libdyld; + + int nrpath; + char** rpaths; }; -// try these hashes -// https://gist.github.com/sgsfak/9ba382a0049f6ee885f68621ae86079b -uint32_t fnv_hash(const char *str) { +uint32_t fnv_hash_extend(const char *str, uint32_t h) { unsigned char *s = (unsigned char *)str; /* unsigned string */ /* See the FNV parameters at www.isthe.com/chongo/tech/comp/fnv/#FNV-param */ const uint32_t FNV_32_PRIME = 0x01000193; /* 16777619 */ - uint32_t h = 0x811c9dc5; /* 2166136261 */ + // uint32_t h = 0x811c9dc5; /* 2166136261 */x while (*s != 0) { /* xor the bottom with the current octet */ h ^= *s++; @@ -92,6 +93,12 @@ uint32_t fnv_hash(const char *str) { return h; } +uint32_t fnv_hash(const char* str) { + return fnv_hash_extend(str, 0x811c9dc5); +} + +// try these hashes +// https://gist.github.com/sgsfak/9ba382a0049f6ee885f68621ae86079b // calculate the hash to search // _dyld_get_image_name returns the full path to the library @@ -115,7 +122,20 @@ uint32_t calculate_libname_hash(const libcache *cache, const char *name) { // then resolve the full path for all rpath // // which rpath is correct can be done by checking if the cache has that hash - printf("resolver for @rpath is not supported yet\n"); + for (int i = 0; i < cache->nrpath; i++){ + char* rpath = cache->rpaths[i]; + char* p = realpath(rpath, 0); + hash = hash_func(p); + hash = fnv_hash_extend(&name[6], hash); + for (size_t i = 0; i < cache->size; i++) { + if (cache->libs[i].hash == hash) { + free(p); + return hash; + } + } + free(p); + } + // printf("resolver for @rpath is not supported yet\n"); } else { hash = hash_func(name); } @@ -745,6 +765,7 @@ struct ProgramVars { void build_cache(struct libcache &cache, void *main); void fix(struct libcache &cache); +void find_all_rpath(struct libcache &cache, void *main); void test(struct libcache &cache); @@ -832,6 +853,7 @@ void build_cache(struct libcache &cache, void *main) { printf("lib header at %p\n", thislib); printf("libdyld header at %p\n", libdyld); + find_all_rpath(cache ,main); uint32_t trie_size; void *libdyld_export_trie = get_export_trie(libdyld, trie_size); @@ -863,6 +885,41 @@ void build_cache(struct libcache &cache, void *main) { } } +// Function to find all rpath entries of the main executable +void find_all_rpath(struct libcache &cache, void *header) { + const uint32_t magic = *(uint32_t *)header; + char *ptr = (char *)header; + if (magic == magic64) { + ptr += 0x20; + } else { + ptr += 0x20 - 0x4; + } + printf("xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\n"); + const uint32_t ncmds = *((uint32_t *)header + 4); + printf("RPATHS:\n"); + cache.nrpath = 0; + for (uint32_t i = 0; i < ncmds; i++) { + const uint32_t cmd = *((uint32_t *)ptr + 0); + const uint32_t cmdsize = *((uint32_t *)ptr + 1); + if (cmd == LC_RPATH) cache.nrpath++; + ptr += cmdsize; + } + uint32_t idx = 0; + ptr = (char *)header; + ptr += (magic == magic64) ? 0x20 : 0x20 - 0x4; + cache.rpaths = (char **)malloc(sizeof(char *) * cache.nrpath); + for (uint32_t i = 0; i < ncmds; i++) { + const uint32_t cmd = *((uint32_t *)ptr + 0); + const uint32_t cmdsize = *((uint32_t *)ptr + 1); + if (cmd == LC_RPATH) { + cache.rpaths[idx++] = (char *)ptr + 12; + printf("%s\n", cache.rpaths[idx - 1]); + } + ptr += cmdsize; + } + printf("xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\n"); +} + void fix_binds(struct libcache_item *libfixing, struct libcache *cache, int n_ins, uint32_t *instructions, char *libs, char *symbols) { uint32_t libsystem_hash =