int main(int argc, char **argv) { struct hp_options opts = { 0 }; hotpatch_t *hp = NULL; int rc = 0; /* parse all arguments first */ if ((rc = parse_arguments(argc, argv, &opts)) != 0) { return rc; } print_options(&opts); /* break from execution whenever a step fails */ do { uintptr_t ptr = 0; hp = hotpatch_create(opts.pid, opts.verbose); if (!hp) { fprintf(stderr, "[%s:%d] Unable to create hotpatch for PID %d\n", __func__, __LINE__, opts.pid); rc = -1; break; } if (opts.dryrun) break; if (opts.dll) { uintptr_t dlres = 0; uintptr_t symres = 0; rc = hotpatch_inject_library(hp, opts.dll, opts.symbol, NULL, 0, &dlres, &symres); if (rc >=0) { printf("Dll was injected at %p\n", (void *)dlres); printf("Invocation of %s() returned %p\n", (opts.symbol ? opts.symbol : "_init"), (void *)symres); } } else { /* handles the stripped apps as well */ if (opts.is__start) { ptr = hotpatch_get_entry_point(hp); } else { ptr = hotpatch_read_symbol(hp, opts.symbol, NULL, NULL); } if (!ptr) { printf("Symbol %s not found. Cannot proceed\n", opts.symbol); break; } printf("Setting execution pointer to %s at 0x"LX"\n", opts.symbol, ptr); rc = hotpatch_attach(hp); if (rc < 0) { printf("Failed to attach to process. Cannot proceed\n"); break; } rc = hotpatch_exec_symbol(hp, ptr, opts.verbose); if (rc < 0) { printf("Failed to execute the symbol in 0x"LX"\n", ptr); rc = hotpatch_detach(hp); break; } rc = hotpatch_detach(hp); } } while (0); hotpatch_destroy(hp); hp = NULL; if (opts.symbol) free(opts.symbol); opts.symbol = NULL; if (opts.dll) free(opts.dll); opts.dll = NULL; return rc; }
hotpatch_t *hotpatch_create(pid_t pid, int verbose) { int rc = 0; hotpatch_t *hp = NULL; do { char filename[OS_MAX_BUFFER]; if (pid <= 0) { LOG_ERROR_INVALID_PID(pid); break; } memset(filename, 0, sizeof(filename)); snprintf(filename, sizeof(filename), "/proc/%d/exe", pid); if (verbose > 3) fprintf(stderr, "[%s:%d] Exe symlink for pid %d : %s\n", __func__, __LINE__, pid, filename); hp = malloc(sizeof(*hp)); if (!hp) { LOG_ERROR_OUT_OF_MEMORY; rc = -1; break; } memset(hp, 0, sizeof(*hp)); hp->verbose = verbose; hp->pid = pid; hp->is64 = HOTPATCH_EXE_IS_NEITHER; hp->exe_symbols = exe_load_symbols(filename, hp->verbose, &hp->exe_symbols_num, &hp->exe_entry_point, &hp->exe_interp, &hp->is64); if (!hp->exe_symbols) { fprintf(stderr, "[%s:%d] Unable to find any symbols in exe.\n", __func__, __LINE__); rc = -1; break; } if (hp->exe_entry_point == 0) { fprintf(stderr, "[%s:%d] Entry point is 0. Invalid.\n", __func__, __LINE__); rc = -1; break; } LOG_INFO_HEADERS_LOADED(verbose); hp->ld_maps = ld_load_maps(hp->pid, hp->verbose, &hp->ld_maps_num); if (!hp->ld_maps) { fprintf(stderr, "[%s:%d] Unable to load data in " "/proc/%d/maps.\n", __func__, __LINE__, pid); rc = -1; break; } if (verbose > 2) fprintf(stderr, "[%s:%d] /proc/%d/maps loaded.\n", __func__, __LINE__, pid); if (hp->exe_symbols && hp->exe_symbols_num > 0) { qsort(hp->exe_symbols, hp->exe_symbols_num, sizeof(*hp->exe_symbols), elf_symbol_cmpqsort); } if (hotpatch_gather_functions(hp) < 0) { fprintf(stderr, "[%s:%d] Unable to find all the functions" " needed. Cannot proceed.\n", __func__, __LINE__); rc = -1; break; } if (rc < 0) { hotpatch_destroy(hp); hp = NULL; } } while (0); return hp; }