|
|
@ -74,7 +74,7 @@ struct libcache {
|
|
|
|
void *libdyld;
|
|
|
|
void *libdyld;
|
|
|
|
|
|
|
|
|
|
|
|
int nrpath;
|
|
|
|
int nrpath;
|
|
|
|
char** rpaths;
|
|
|
|
char **rpaths;
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
uint32_t fnv_hash_extend(const char *str, uint32_t h) {
|
|
|
|
uint32_t fnv_hash_extend(const char *str, uint32_t h) {
|
|
|
@ -93,9 +93,7 @@ uint32_t fnv_hash_extend(const char *str, uint32_t h) {
|
|
|
|
|
|
|
|
|
|
|
|
return h;
|
|
|
|
return h;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
uint32_t fnv_hash(const char* str) {
|
|
|
|
uint32_t fnv_hash(const char *str) { return fnv_hash_extend(str, 0x811c9dc5); }
|
|
|
|
return fnv_hash_extend(str, 0x811c9dc5);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// try these hashes
|
|
|
|
// try these hashes
|
|
|
|
// https://gist.github.com/sgsfak/9ba382a0049f6ee885f68621ae86079b
|
|
|
|
// https://gist.github.com/sgsfak/9ba382a0049f6ee885f68621ae86079b
|
|
|
@ -122,9 +120,9 @@ uint32_t calculate_libname_hash(const libcache *cache, const char *name) {
|
|
|
|
// then resolve the full path for all rpath
|
|
|
|
// then resolve the full path for all rpath
|
|
|
|
//
|
|
|
|
//
|
|
|
|
// which rpath is correct can be done by checking if the cache has that hash
|
|
|
|
// which rpath is correct can be done by checking if the cache has that hash
|
|
|
|
for (int i = 0; i < cache->nrpath; i++){
|
|
|
|
for (int i = 0; i < cache->nrpath; i++) {
|
|
|
|
char* rpath = cache->rpaths[i];
|
|
|
|
char *rpath = cache->rpaths[i];
|
|
|
|
char* p = realpath(rpath, 0);
|
|
|
|
char *p = realpath(rpath, 0);
|
|
|
|
hash = hash_func(p);
|
|
|
|
hash = hash_func(p);
|
|
|
|
hash = fnv_hash_extend(&name[6], hash);
|
|
|
|
hash = fnv_hash_extend(&name[6], hash);
|
|
|
|
for (size_t j = 0; j < cache->size; j++) {
|
|
|
|
for (size_t j = 0; j < cache->size; j++) {
|
|
|
@ -448,7 +446,7 @@ uint32_t should_follow_symbol(char *&buffer, char *&_find) {
|
|
|
|
return is_prefix;
|
|
|
|
return is_prefix;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void *find_in_export_trie(const void *header, void *trie, char *& symbol) {
|
|
|
|
void *find_in_export_trie(const void *header, void *trie, char *&symbol) {
|
|
|
|
uint32_t func = 0;
|
|
|
|
uint32_t func = 0;
|
|
|
|
|
|
|
|
|
|
|
|
char *ptr = (char *)trie;
|
|
|
|
char *ptr = (char *)trie;
|
|
|
@ -512,10 +510,10 @@ void *find_in_export_trie(const void *header, void *trie, char *& symbol) {
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void *find_in_lib(struct libcache *cache, struct libcache_item *lib,
|
|
|
|
void *find_in_lib(struct libcache *cache, struct libcache_item *lib,
|
|
|
|
char *& symbol);
|
|
|
|
char *&symbol);
|
|
|
|
|
|
|
|
|
|
|
|
void *find_in_reexport(struct libcache *cache, struct libcache_item *lib,
|
|
|
|
void *find_in_reexport(struct libcache *cache, struct libcache_item *lib,
|
|
|
|
char *& symbol) {
|
|
|
|
char *&symbol) {
|
|
|
|
void *header = lib->header;
|
|
|
|
void *header = lib->header;
|
|
|
|
const uint32_t magic = *(uint32_t *)header;
|
|
|
|
const uint32_t magic = *(uint32_t *)header;
|
|
|
|
char *ptr = (char *)header;
|
|
|
|
char *ptr = (char *)header;
|
|
|
@ -551,7 +549,7 @@ void *find_in_reexport(struct libcache *cache, struct libcache_item *lib,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
void *find_in_lib(struct libcache *cache, struct libcache_item *lib,
|
|
|
|
void *find_in_lib(struct libcache *cache, struct libcache_item *lib,
|
|
|
|
char *& symbol) {
|
|
|
|
char *&symbol) {
|
|
|
|
void *direct = find_in_export_trie(lib->header, lib->trie, symbol);
|
|
|
|
void *direct = find_in_export_trie(lib->header, lib->trie, symbol);
|
|
|
|
if (direct) {
|
|
|
|
if (direct) {
|
|
|
|
return direct;
|
|
|
|
return direct;
|
|
|
@ -582,8 +580,8 @@ void *custom_dlsym(struct libcache *cache, uint32_t hash, const char *symbol) {
|
|
|
|
// C has X but it is a re-export from B with the name Y
|
|
|
|
// C has X but it is a re-export from B with the name Y
|
|
|
|
// then we have to perform a search again from the top
|
|
|
|
// then we have to perform a search again from the top
|
|
|
|
// but with symbol Y
|
|
|
|
// but with symbol Y
|
|
|
|
char** symbol_copy = (char**)&symbol;
|
|
|
|
char **symbol_copy = (char **)&symbol;
|
|
|
|
void* func = find_in_lib(cache, cache_lib, *symbol_copy);
|
|
|
|
void *func = find_in_lib(cache, cache_lib, *symbol_copy);
|
|
|
|
if (*symbol_copy != symbol) {
|
|
|
|
if (*symbol_copy != symbol) {
|
|
|
|
func = find_in_lib(cache, cache_lib, *symbol_copy);
|
|
|
|
func = find_in_lib(cache, cache_lib, *symbol_copy);
|
|
|
|
}
|
|
|
|
}
|
|
|
@ -896,7 +894,7 @@ void build_cache(struct libcache &cache, void *main) {
|
|
|
|
printf("lib header at %p\n", thislib);
|
|
|
|
printf("lib header at %p\n", thislib);
|
|
|
|
printf("libdyld header at %p\n", libdyld);
|
|
|
|
printf("libdyld header at %p\n", libdyld);
|
|
|
|
|
|
|
|
|
|
|
|
find_all_rpath(cache ,main);
|
|
|
|
find_all_rpath(cache, main);
|
|
|
|
uint32_t trie_size;
|
|
|
|
uint32_t trie_size;
|
|
|
|
void *libdyld_export_trie = get_export_trie(libdyld, trie_size);
|
|
|
|
void *libdyld_export_trie = get_export_trie(libdyld, trie_size);
|
|
|
|
|
|
|
|
|
|
|
@ -908,16 +906,16 @@ void build_cache(struct libcache &cache, void *main) {
|
|
|
|
typedef char *(*dyld_get_image_name_t)(int);
|
|
|
|
typedef char *(*dyld_get_image_name_t)(int);
|
|
|
|
typedef void *(*dyld_get_image_header_t)(int);
|
|
|
|
typedef void *(*dyld_get_image_header_t)(int);
|
|
|
|
|
|
|
|
|
|
|
|
char* dyld_image_count_s = "__dyld_image_count";
|
|
|
|
char *dyld_image_count_s = (char*)"__dyld_image_count";
|
|
|
|
int (*dyld_image_count_func)(void) = (dyld_image_count_t)find_in_export_trie(
|
|
|
|
int (*dyld_image_count_func)(void) = (dyld_image_count_t)find_in_export_trie(
|
|
|
|
libdyld, libdyld_export_trie, dyld_image_count_s);
|
|
|
|
libdyld, libdyld_export_trie, dyld_image_count_s);
|
|
|
|
|
|
|
|
|
|
|
|
char* dyld_get_image_header_s = "__dyld_get_image_header";
|
|
|
|
char *dyld_get_image_header_s = (char*)"__dyld_get_image_header";
|
|
|
|
void *(*dyld_get_image_header_func)(int) =
|
|
|
|
void *(*dyld_get_image_header_func)(int) =
|
|
|
|
(dyld_get_image_header_t)find_in_export_trie(libdyld, libdyld_export_trie,
|
|
|
|
(dyld_get_image_header_t)find_in_export_trie(libdyld, libdyld_export_trie,
|
|
|
|
dyld_get_image_header_s);
|
|
|
|
dyld_get_image_header_s);
|
|
|
|
|
|
|
|
|
|
|
|
char* dyld_get_image_name_s = "__dyld_get_image_name";
|
|
|
|
char *dyld_get_image_name_s = (char*)"__dyld_get_image_name";
|
|
|
|
char *(*dyld_get_image_name_func)(int) =
|
|
|
|
char *(*dyld_get_image_name_func)(int) =
|
|
|
|
(dyld_get_image_name_t)find_in_export_trie(libdyld, libdyld_export_trie,
|
|
|
|
(dyld_get_image_name_t)find_in_export_trie(libdyld, libdyld_export_trie,
|
|
|
|
dyld_get_image_name_s);
|
|
|
|
dyld_get_image_name_s);
|
|
|
@ -950,7 +948,8 @@ void find_all_rpath(struct libcache &cache, void *header) {
|
|
|
|
for (uint32_t i = 0; i < ncmds; i++) {
|
|
|
|
for (uint32_t i = 0; i < ncmds; i++) {
|
|
|
|
const uint32_t cmd = *((uint32_t *)ptr + 0);
|
|
|
|
const uint32_t cmd = *((uint32_t *)ptr + 0);
|
|
|
|
const uint32_t cmdsize = *((uint32_t *)ptr + 1);
|
|
|
|
const uint32_t cmdsize = *((uint32_t *)ptr + 1);
|
|
|
|
if (cmd == LC_RPATH) cache.nrpath++;
|
|
|
|
if (cmd == LC_RPATH)
|
|
|
|
|
|
|
|
cache.nrpath++;
|
|
|
|
ptr += cmdsize;
|
|
|
|
ptr += cmdsize;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
uint32_t idx = 0;
|
|
|
|
uint32_t idx = 0;
|
|
|
@ -1333,16 +1332,18 @@ void fix_objc(struct libcache_item *libfixing, struct libcache &cache) {
|
|
|
|
uint64_t *data_ptr = (uint64_t *)(addr + slide);
|
|
|
|
uint64_t *data_ptr = (uint64_t *)(addr + slide);
|
|
|
|
|
|
|
|
|
|
|
|
uint32_t trie_size;
|
|
|
|
uint32_t trie_size;
|
|
|
|
void* libdyld = cache.libdyld;
|
|
|
|
char* symbol = (char*)"__dyld_get_objc_selector";
|
|
|
|
|
|
|
|
void *libdyld = cache.libdyld;
|
|
|
|
void *libdyld_export_trie = get_export_trie(libdyld, trie_size);
|
|
|
|
void *libdyld_export_trie = get_export_trie(libdyld, trie_size);
|
|
|
|
typedef void *(*dyld_get_objc_selector_t)(const char*);
|
|
|
|
typedef void *(*dyld_get_objc_selector_t)(const char *);
|
|
|
|
dyld_get_objc_selector_t dyld_get_objc_selector_func = (dyld_get_objc_selector_t)find_in_export_trie(
|
|
|
|
dyld_get_objc_selector_t dyld_get_objc_selector_func =
|
|
|
|
libdyld, libdyld_export_trie, "__dyld_get_objc_selector");
|
|
|
|
(dyld_get_objc_selector_t)find_in_export_trie(
|
|
|
|
|
|
|
|
libdyld, libdyld_export_trie, symbol);
|
|
|
|
|
|
|
|
|
|
|
|
// resolve method names that cached in the dyld
|
|
|
|
// resolve method names that cached in the dyld
|
|
|
|
for (int i = 0; i < bshield_data::n_selectors; i++) {
|
|
|
|
for (int i = 0; i < bshield_data::n_selectors; i++) {
|
|
|
|
uint32_t idx = bshield_data::special_selectors_idx[i];
|
|
|
|
uint32_t idx = bshield_data::special_selectors_idx[i];
|
|
|
|
char* name = bshield_data::special_selectors_name[i];
|
|
|
|
const char *name = bshield_data::special_selectors_name[i];
|
|
|
|
data_ptr[idx] = (uint64_t)dyld_get_objc_selector_func(name);
|
|
|
|
data_ptr[idx] = (uint64_t)dyld_get_objc_selector_func(name);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|