From da200d3ac0204abadd5992820486321970d689b8 Mon Sep 17 00:00:00 2001 From: Jari Vetoniemi Date: Mon, 19 Feb 2018 15:51:56 +0200 Subject: refactoring, fixing and implementing messy commits yay --- src/linker/dlfcn.c | 49 ++++++++++-------------------- src/linker/linker.c | 87 ++++++++--------------------------------------------- 2 files changed, 28 insertions(+), 108 deletions(-) (limited to 'src/linker') diff --git a/src/linker/dlfcn.c b/src/linker/dlfcn.c index 3f76e92..a044094 100644 --- a/src/linker/dlfcn.c +++ b/src/linker/dlfcn.c @@ -21,12 +21,7 @@ #include "linker.h" #include "linker_format.h" -/* for apkenv_get_hooked_symbol */ -// #include "../compat/hooks.h" - -/* for create_wrapper */ -// #include "../debug/wrappers.h" - +#include "wrapper/wrapper.h" #include "linker_debug.h" #ifdef APKENV_DEBUG @@ -66,7 +61,7 @@ static void set_dlerror(int err) dl_err_str = (const char *)&dl_err_buf[0]; } -void *apkenv_android_dlopen(const char *filename, int flag) +void *bionic_dlopen(const char *filename, int flag) { soinfo *ret; @@ -83,18 +78,7 @@ void *apkenv_android_dlopen(const char *filename, int flag) return ret; } -static void *apkenv_android_dlopen_wrap(const char *filename, int flag) -{ -#if 0 - void *ret = get_builtin_lib_handle(filename); - if (ret) - return ret; -#endif - - return apkenv_android_dlopen(filename, flag); -} - -const char *apkenv_android_dlerror(void) +const char *bionic_dlerror(void) { const char *tmp = dl_err_str; dl_err_str = NULL; @@ -105,7 +89,7 @@ enum { WRAPPER_DYNHOOK, }; -void *apkenv_android_dlsym(void *handle, const char *symbol) +void *bionic_dlsym(void *handle, const char *symbol) { soinfo *found; Elf32_Sym *sym; @@ -159,7 +143,7 @@ void *apkenv_android_dlsym(void *handle, const char *symbol) if(likely((bind == STB_GLOBAL) && (sym->st_shndx != 0))) { unsigned ret = sym->st_value + found->base; pthread_mutex_unlock(&apkenv_dl_lock); - return create_wrapper((char*)symbol, (void*)ret, WRAPPER_DYNHOOK); + return wrapper_create((char*)symbol, (void*)ret); } set_dlerror(DL_ERR_SYMBOL_NOT_GLOBAL); @@ -173,7 +157,7 @@ err: return 0; } -int apkenv_android_dladdr(const void *addr, Dl_info *info) +int bionic_dladdr(const void *addr, Dl_info *info) { int ret = 0; @@ -204,7 +188,7 @@ int apkenv_android_dladdr(const void *addr, Dl_info *info) return ret; } -int apkenv_android_dlclose(void *handle) +int bionic_dlclose(void *handle) { #if 0 if (is_builtin_lib_handle(handle)) @@ -224,7 +208,7 @@ int apkenv_android_dlclose(void *handle) #define ANDROID_LIBDL_STRTAB \ "dlopen\0dlclose\0dlsym\0dlerror\0dladdr\0dl_unwind_find_exidx\0" -_Unwind_Ptr apkenv_android_dl_unwind_find_exidx(_Unwind_Ptr pc, int *pcount); +_Unwind_Ptr bionic_dl_unwind_find_exidx(_Unwind_Ptr pc, int *pcount); #elif defined(ANDROID_X86_LINKER) // 0000000 00011111 111112 22222222 2333333 3333444444444455 @@ -232,8 +216,7 @@ _Unwind_Ptr apkenv_android_dl_unwind_find_exidx(_Unwind_Ptr pc, int *pcount); #define ANDROID_LIBDL_STRTAB \ "dlopen\0dlclose\0dlsym\0dlerror\0dladdr\0dl_iterate_phdr\0" int -apkenv_android_dl_iterate_phdr(int (*cb)(struct dl_phdr_info *info, size_t size, void *data), - void *data); +bionic_dl_iterate_phdr(int (*cb)(struct dl_phdr_info *info, size_t size, void *data), void *data); #else #error Unsupported architecture. Only ARM and x86 are presently supported. @@ -289,41 +272,41 @@ construct(void) .st_name = sizeof(ANDROID_LIBDL_STRTAB) - 1, }, { .st_name = 0, // starting index of the name in apkenv_libdl_info.strtab - .st_value = (Elf32_Addr)(uintptr_t)apkenv_android_dlopen_wrap, + .st_value = (Elf32_Addr)(uintptr_t)bionic_dlopen, .st_info = STB_GLOBAL << 4, .st_shndx = 1, }, { .st_name = 7, - .st_value = (Elf32_Addr)(uintptr_t)apkenv_android_dlclose, + .st_value = (Elf32_Addr)(uintptr_t)bionic_dlclose, .st_info = STB_GLOBAL << 4, .st_shndx = 1, }, { .st_name = 15, - .st_value = (Elf32_Addr)(uintptr_t)apkenv_android_dlsym, + .st_value = (Elf32_Addr)(uintptr_t)bionic_dlsym, .st_info = STB_GLOBAL << 4, .st_shndx = 1, }, { .st_name = 21, - .st_value = (Elf32_Addr)(uintptr_t)apkenv_android_dlerror, + .st_value = (Elf32_Addr)(uintptr_t)bionic_dlerror, .st_info = STB_GLOBAL << 4, .st_shndx = 1, }, { .st_name = 29, - .st_value = (Elf32_Addr)(uintptr_t)apkenv_android_dladdr, + .st_value = (Elf32_Addr)(uintptr_t)bionic_dladdr, .st_info = STB_GLOBAL << 4, .st_shndx = 1, }, #ifdef ANDROID_ARM_LINKER { .st_name = 36, - .st_value = (Elf32_Addr)(uintptr_t)apkenv_android_dl_unwind_find_exidx, + .st_value = (Elf32_Addr)(uintptr_t)bionic_dl_unwind_find_exidx, .st_info = STB_GLOBAL << 4, .st_shndx = 1, }, #elif defined(ANDROID_X86_LINKER) { .st_name = 36, - .st_value = (Elf32_Addr)(uintptr_t)apkenv_android_dl_iterate_phdr, + .st_value = (Elf32_Addr)(uintptr_t)bionic_dl_iterate_phdr, .st_info = STB_GLOBAL << 4, .st_shndx = 1, }, diff --git a/src/linker/linker.c b/src/linker/linker.c index 09ebf8f..e5e1095 100644 --- a/src/linker/linker.c +++ b/src/linker/linker.c @@ -54,10 +54,7 @@ #include "strlcpy.h" -/* for apkenv_get_hooked_symbol */ -// #include "../compat/hooks.h" -/* for create_wrapper */ -// #include "../debug/wrappers.h" +#include "wrapper/wrapper.h" #include "linker.h" #include "linker_debug.h" @@ -163,50 +160,6 @@ enum { WRAPPER_ARM_INJECTION, }; -static char* (*__cxa_demangle)(const char *mangled_name, char *output_buffer, size_t *length, int *status); - -static void -trace(const char *const symbol) -{ - if (__cxa_demangle) { - // >If output_buffer is not long enough, it is expanded using realloc - // Holy fuck gcc what the fuck? Guess we don't use stack then, thanks - int status; - char *demangled; - if ((demangled = __cxa_demangle(symbol, NULL, NULL, &status))) { - printf("trace: %s\n", demangled); - free(demangled); // so pointless... - return; - } - } - - printf("trace: %s\n", symbol); -} - -__asm__( - "wrapper_start: nop\n" - "wrapper_symbol: pushl $0xFAFBFCFD\n" - "wrapper_trace: movl $0xFAFBFCFD, %eax\ncall *%eax\npop %eax\n" - "wrapper_call: movl $0xFAFBFCFD, %eax\njmp *%eax\n" - "wrapper_end: nop\n" -); - -extern char wrapper_start, wrapper_symbol, wrapper_trace, wrapper_call, wrapper_end; - -void* -create_wrapper(const char *const symbol, void *function, int wrapper_type) -{ - const size_t sz = &wrapper_end - &wrapper_start; - unsigned char *fun = mmap(NULL, sz, PROT_READ | PROT_WRITE, MAP_ANONYMOUS | MAP_PRIVATE, -1, 0); - assert(fun != MAP_FAILED); - memcpy(fun, &wrapper_start, sz); - memcpy(fun + (&wrapper_symbol - &wrapper_start) + 1, &symbol, sizeof(symbol)); - memcpy(fun + (&wrapper_trace - &wrapper_start) + 1, (uintptr_t[]){ (uintptr_t)trace }, sizeof(uintptr_t)); - memcpy(fun + (&wrapper_call - &wrapper_start) + 1, &function, sizeof(function)); - mprotect(fun, sz, PROT_READ | PROT_EXEC); - return fun; -} - /* * This function is an empty stub where GDB locates a breakpoint to get notified * about linker activity. @@ -388,19 +341,6 @@ static void apkenv_free_info(soinfo *si) apkenv_freelist = si; } -static const char *apkenv_addr_to_name(unsigned addr) -{ - soinfo *si; - - for(si = apkenv_solist; si != 0; si = si->next){ - if((addr >= si->base) && (addr < (si->base + si->size))) { - return si->name; - } - } - - return ""; -} - /* For a given PC, find the .so that it belongs to. * Returns the base address of the .ARM.exidx section * for that .so, and the number of 8-byte entries @@ -411,7 +351,7 @@ static const char *apkenv_addr_to_name(unsigned addr) * This function is exposed via dlfcn.c and libdl.so. */ #ifdef ANDROID_ARM_LINKER -_Unwind_Ptr apkenv_android_dl_unwind_find_exidx(_Unwind_Ptr pc, int *pcount) +_Unwind_Ptr bionic_dl_unwind_find_exidx(_Unwind_Ptr pc, int *pcount) { soinfo *si; unsigned addr = (unsigned)pc; @@ -428,7 +368,7 @@ _Unwind_Ptr apkenv_android_dl_unwind_find_exidx(_Unwind_Ptr pc, int *pcount) /* Here, we only have to provide a callback to iterate across all the * loaded libraries. gcc_eh does the rest. */ int -apkenv_android_dl_iterate_phdr(int (*cb)(struct dl_phdr_info *info, size_t size, void *data), +bionic_dl_iterate_phdr(int (*cb)(struct dl_phdr_info *info, size_t size, void *data), void *data) { soinfo *si; @@ -1427,7 +1367,7 @@ static int apkenv_reloc_library(soinfo *si, Elf32_Rel *rel, unsigned count) if (!strcmp(sym_name, "dl_iterate_phdr")) { // FIXME: hack, move to libc.so - sym_addr = apkenv_android_dl_iterate_phdr; + sym_addr = bionic_dl_iterate_phdr; } else if ((sym_addr = dlsym(RTLD_DEFAULT, wrap_sym_name))) { LINKER_DEBUG_PRINTF("%s hooked symbol %s to %x\n", si->name, wrap_sym_name, sym_addr); } else if ((sym_addr = dlsym(RTLD_DEFAULT, sym_name))) { @@ -1444,7 +1384,7 @@ static int apkenv_reloc_library(soinfo *si, Elf32_Rel *rel, unsigned count) } if(sym_addr != 0) { - sym_addr = (unsigned)create_wrapper(sym_name, (void*)sym_addr, WRAPPER_UNHOOKED); + sym_addr = (unsigned)wrapper_create(sym_name, (void*)sym_addr); } else if(s == NULL) { /* We only allow an undefined symbol if this is a weak @@ -1515,7 +1455,7 @@ static int apkenv_reloc_library(soinfo *si, Elf32_Rel *rel, unsigned count) sym_addr = (unsigned)(s->st_value + base); LINKER_DEBUG_PRINTF("%s symbol (from %s) %s to %x\n", si->name, apkenv_last_library_used, sym_name, sym_addr); if(ELF32_ST_TYPE(s->st_info) == STT_FUNC) { - sym_addr = (unsigned)create_wrapper(sym_name, (void*)sym_addr, WRAPPER_UNHOOKED); + sym_addr = (unsigned)wrapper_create(sym_name, (void*)sym_addr); } } @@ -1834,7 +1774,7 @@ static void apkenv_wrap_function(void *sym_addr, char *sym_name, int is_thumb, s { DEBUG("HOOKING INTERNAL (ARM) FUNCTION %s@%x (in %s) TO: %x\n",sym_name,sym_addr,si->name,hook); ((int32_t*)sym_addr)[0] = 0xe51ff004; // ldr pc, [pc, -#4] (load the hooks address into pc) - ((int32_t*)sym_addr)[1] = (uint32_t)create_wrapper(sym_name, hook, WRAPPER_LATEHOOK); + ((int32_t*)sym_addr)[1] = (uint32_t)wrapper_create(sym_name, hook); __clear_cache((int32_t*)sym_addr, (int32_t*)sym_addr + 2); } @@ -1850,7 +1790,7 @@ static void apkenv_wrap_function(void *sym_addr, char *sym_name, int is_thumb, s ((int16_t*)sym_addr)[4] = 0xBC01; /* pop {r0} */ ((int16_t*)sym_addr)[5] = 0x4760; /* bx ip */ - void *wrp = create_wrapper(sym_name, hook, WRAPPER_LATEHOOK); + void *wrp = wrapper_create(sym_name, hook); // store the hooks address ((int16_t*)sym_addr)[6] = (uint32_t)wrp & 0x0000FFFF; @@ -1867,7 +1807,7 @@ static void apkenv_wrap_function(void *sym_addr, char *sym_name, int is_thumb, s { DEBUG("CREATING ARM WRAPPER FOR: %s@%x (in %s)\n", sym_name, (unsigned)sym_addr, si->name); - create_wrapper(sym_name, sym_addr, WRAPPER_ARM_INJECTION); + wrapper_create(sym_name, sym_addr); } // TODO: this will fail if the first 2-5 instructions do something pc related // (this DOES happen very often) @@ -1875,7 +1815,7 @@ static void apkenv_wrap_function(void *sym_addr, char *sym_name, int is_thumb, s { DEBUG("CREATING THUMB WRAPPER FOR: %s@%x (in %s)\n",sym_name, (unsigned)sym_addr,si->name); - create_wrapper(sym_name, sym_addr, WRAPPER_THUMB_INJECTION); + wrapper_create(sym_name, sym_addr); } } @@ -2133,9 +2073,6 @@ static int apkenv_link_image(soinfo *si, unsigned wr_offset) lsi = apkenv_find_library(si->strtab + d[1]); if (!lsi && dlopen(si->strtab + d[1], RTLD_NOW | RTLD_GLOBAL)) { DEBUG("Loaded %s with glibc dlopen\n", si->strtab + d[1]); - - if (!__cxa_demangle) - __cxa_demangle = dlsym(RTLD_DEFAULT, "__cxa_demangle"); } #endif if(lsi == 0) { @@ -2234,7 +2171,7 @@ fail: return -1; } -void apkenv_parse_library_path(const char *path, char *delim) +void dl_parse_library_path(const char *path, char *delim) { size_t len; char *apkenv_ldpaths_bufp = apkenv_ldpaths_buf; @@ -2428,7 +2365,7 @@ sanitize: /* Use LD_LIBRARY_PATH if we aren't setuid/setgid */ if (ldpath_env) - apkenv_parse_library_path(ldpath_env, ":"); + dl_parse_library_path(ldpath_env, ":"); if (ldpreload_env) { apkenv_parse_apkenv_preloads(ldpreload_env, " :"); -- cgit v1.2.3