diff --git a/include/injector.h b/include/injector.h index e7b5280..c26f191 100644 --- a/include/injector.h +++ b/include/injector.h @@ -53,11 +53,13 @@ extern "C" { #define INJERR_UNSUPPORTED_TARGET -9 /* linux, windows */ #define INJERR_INVALID_ELF_FORMAT -10 /* linux */ #define INJERR_WAIT_TRACEE -11 /* linux */ +#define INJERR_FUNCTION_MISSING -12 /* linux, windows */ typedef struct injector injector_t; int injector_attach(injector_t **injector, injector_pid_t pid); int injector_inject(injector_t *injector, const char *path, void **handle); +int injector_call(injector_t *injector, void *handle, const char* name); int injector_uninject(injector_t *injector, void *handle); int injector_detach(injector_t *injector); const char *injector_error(void); diff --git a/src/linux/elf.c b/src/linux/elf.c index 1e73b0e..d7899ca 100644 --- a/src/linux/elf.c +++ b/src/linux/elf.c @@ -60,6 +60,8 @@ int injector__collect_libc_information(injector_t *injector) size_t dlopen_offset; size_t dlclose_st_name; size_t dlclose_offset; + size_t dlsym_st_name; + size_t dlsym_offset; Elf_Sym sym; int idx; int rv; @@ -158,9 +160,29 @@ int injector__collect_libc_information(injector_t *injector) break; } } + + dlsym_st_name = find_strtab_offset(fp, str_offset, str_size, "__libc_dlsym"); + if (dlsym_st_name == 0) { + injector__set_errmsg("failed to find __libc_dlsym in the .dynstr section."); + rv = INJERR_NO_FUNCTION; + goto cleanup; + } + + fseek(fp, sym_offset, SEEK_SET); + for (idx = 0; idx < sym_num; idx++) { + rv = read_elf_sym(fp, &sym, sym_entsize); + if (rv != 0) { + goto cleanup; + } + if (sym.st_name == dlsym_st_name) { + dlsym_offset = sym.st_value; + break; + } + } injector->dlopen_addr = libc_addr + dlopen_offset; injector->dlclose_addr = libc_addr + dlclose_offset; + injector->dlsym_addr = libc_addr + dlsym_offset; injector->code_addr = libc_addr + ehdr.e_entry; switch (ehdr.e_machine) { diff --git a/src/linux/injector.c b/src/linux/injector.c index 23efb04..e65f6b9 100644 --- a/src/linux/injector.c +++ b/src/linux/injector.c @@ -150,6 +150,27 @@ int injector_inject(injector_t *injector, const char *path, void **handle) return 0; } +int injector_call(injector_t *injector, void *handle, const char* name) +{ + int rv; + long retval; + size_t len = strlen(name) + 1; + if (len > injector->text_size) { + injector__set_errmsg("too long function name: %s", name); + return INJERR_FUNCTION_MISSING; + } + rv = injector__write(injector, injector->text, name, len); + if (rv != 0) { + return rv; + } + rv = injector__call_function(injector, &retval, injector->dlsym_addr, handle, injector->text); + if (retval == 0) { + injector__set_errmsg("function not found: %s", name); + return INJERR_FUNCTION_MISSING; + } + return injector__call_function(injector, &retval, retval); +} + int injector_uninject(injector_t *injector, void *handle) { int rv; diff --git a/src/linux/injector_internal.h b/src/linux/injector_internal.h index ceb2fd6..9d209e4 100644 --- a/src/linux/injector_internal.h +++ b/src/linux/injector_internal.h @@ -73,6 +73,7 @@ struct injector { struct user_regs_struct regs; size_t dlopen_addr; size_t dlclose_addr; + size_t dlsym_addr; size_t code_addr; /* address where instructions are written */ code_t backup_code; long sys_mmap;