clean code

This commit is contained in:
nganhkhoa 2023-06-02 12:05:03 +07:00
parent a2bee75ef9
commit 7880e647f5

View File

@ -37,17 +37,10 @@ void set_cwd(const char *const *envp) {
const uint32_t magic64 = 0xfeedfacf; const uint32_t magic64 = 0xfeedfacf;
const uint32_t magic32 = 0xfeedface; 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 { struct libcache_item {
void *header; void *header;
void *trie; void *trie;
uint32_t trie_size;
uint32_t hash; uint32_t hash;
}; };
@ -79,7 +72,14 @@ uint32_t fnv_hash(const char *str) {
return h; 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;
uint32_t (*hash_func)(const char *) = fnv_hash; uint32_t (*hash_func)(const char *) = fnv_hash;
if (name[0] == '.') { if (name[0] == '.') {
@ -101,7 +101,12 @@ uint32_t calculate_libname_hash(const char *name) {
return hash; 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); extern "C" uint32_t dyld_get_sdk_version(const mach_header *mh);
void exported_from_c();
void decode_uleb128(char *&addr, uint32_t *ret) { void decode_uleb128(char *&addr, uint32_t *ret) {
uint32_t result = 0; 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); uint32_t name_offset = *((uint32_t *)ptr + 2);
char *name = (char *)ptr + name_offset; 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++) { for (int j = 0; j < cache->size; j++) {
struct libcache_item reexport = cache->libs[j]; struct libcache_item reexport = cache->libs[j];
if (reexport.hash != hash) { 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); void *direct = find_in_export_trie(lib->header, lib->trie, symbol);
if (direct) if (direct)
return direct; return direct;
// we cannot find in directly exported trie, so we loop through all reexport // cannot find in directly exported trie, loop through all reexport libs
// libs
return find_in_reexport(cache, lib, symbol); return find_in_reexport(cache, lib, symbol);
} }
void *custom_dlsym(struct libcache *cache, const char *libname, void *custom_dlsym(struct libcache *cache, const char *libname,
const char *symbol) { 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++) { for (int i = 0; i < cache->size; i++) {
struct libcache_item cache_lib = cache->libs[i]; struct libcache_item cache_lib = cache->libs[i];
if (cache_lib.hash == hash) { if (cache_lib.hash == hash) {
@ -453,6 +457,14 @@ int hook_printf(const char *format, ...) {
return status; 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 __attribute__((constructor)) static void
bruh(int argc, const char *const argv[], const char *const envp[], bruh(int argc, const char *const argv[], const char *const envp[],
const char *const apple[], const struct ProgramVars *vars) { 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); const void *thislib = find_header((void *)bruh);
// Find dyld lib (mapped) file using a no-sus function // Find dyld lib (mapped) file using a no-sus function
const void *libdyld = find_header((void *)dyld_get_sdk_version); 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 // From libdyld header, we can list exports table
// to find all function we want to use // 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_t)find_in_export_trie(libdyld, libdyld_export_trie,
"__dyld_get_image_name"); "__dyld_get_image_name");
uint32_t nlib = dyld_image_count_func(); cache.size = dyld_image_count_func();
struct libcache_item *liblist = cache.libs =
(struct libcache_item *)malloc(sizeof(struct libcache_item) * nlib); (struct libcache_item *)malloc(sizeof(struct libcache_item) * cache.size);
cache->libs = liblist;
for (int i = 0; i < cache.size; i++) { for (int i = 0; i < cache.size; i++) {
void *header = dyld_get_image_header_func(i); void *header = dyld_get_image_header_func(i);
char *name = dyld_get_image_name_func(i); char *name = dyld_get_image_name_func(i);
cache.libs[i].header = header; cache.libs[i].header = header;
cache.libs[i].trie = get_export_trie(header, trie_size); cache.libs[i].trie = get_export_trie(header, trie_size);
cache.libs[i].hash = calculate_libname_hash(name); cache.libs[i].trie_size = trie_size;
printf("%s %x\n", name, cache.libs[i].hash); 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"); // dump_export_trie_of("/usr/lib/system/libsystem_c.dylib", &cache, "../scripts/libsystem_c_export_trie.bin");
// void* vm_protect_func = custom_dlsym(&cache, if (false) { // test search using name
// "/usr/lib/libSystem.B.dylib", "_vm_protect"); printf("Indirect search: void *printf_func =
// Found=%p Expected=%p\n", vm_protect_func, vm_protect); 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 *vm_protect_func =
// void* printf_func = custom_dlsym(&cache, libsystem_hash, "_printf"); custom_dlsym(&cache, "/usr/lib/libSystem.B.dylib", "_vm_protect");
// printf("Indirect search: Found=%p Expected=%p\n", printf_func, printf); printf("Indirect search: Found=%p Expected=%p\n", vm_protect_func,
vm_protect);
// void* vm_protect_func = custom_dlsym(&cache, libsystem_hash, // using relative path
// "_vm_protect"); printf("Indirect search: Found=%p Expected=%p\n", void *func_c_1 =
// vm_protect_func, vm_protect);
void *func_c =
custom_dlsym(&cache, "./out/libb.dylib", "__Z15exported_from_cv"); 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 // 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); vm_protect_func(mach_task_self_func(), start_page, 0x4000, 0, VM_PROT_READ);
} }
free(liblist); free(cache.libs);
} }