From e1c89440b316692b7760ac4d92fc3cddbd9b542f Mon Sep 17 00:00:00 2001 From: alvarofe Date: Sun, 9 Apr 2017 12:17:56 +0200 Subject: [PATCH] Fix #7086 - plt calculation with partial relro elf --- libr/bin/format/elf/elf.c | 55 +++++++++++++++++++++------------------ libr/bin/p/bin_elf.c | 3 +-- libr/core/cbin.c | 5 ++-- 3 files changed, 33 insertions(+), 30 deletions(-) diff --git a/libr/bin/format/elf/elf.c b/libr/bin/format/elf/elf.c index bdcf334b4b..b184cfabfd 100644 --- a/libr/bin/format/elf/elf.c +++ b/libr/bin/format/elf/elf.c @@ -1107,7 +1107,7 @@ static ut64 get_import_addr(ELFOBJ *bin, int sym) { ut8 rl[sizeof (Elf_(Rel))] = {0}; ut8 rla[sizeof (Elf_(Rela))] = {0}; RBinElfSection *rel_sec = NULL; - Elf_(Addr) plt_sym_addr = -1; + Elf_(Addr) plt_sym_addr = UT32_MAX; ut64 got_addr, got_offset; ut64 plt_addr; int j, k, tsize, len, nrel; @@ -1116,15 +1116,15 @@ static ut64 get_import_addr(ELFOBJ *bin, int sym) { const char *rela_sect[] = { ".rela.plt", ".rel.plt", ".rela.dyn", ".rel.dyn", NULL }; if ((!bin->shdr || !bin->strtab) && !bin->phdr) { - return -1; + return UT32_MAX; } if ((got_offset = Elf_(r_bin_elf_get_section_offset) (bin, ".got")) == -1 && (got_offset = Elf_(r_bin_elf_get_section_offset) (bin, ".got.plt")) == -1) { - return -1; + return UT32_MAX; } if ((got_addr = Elf_(r_bin_elf_get_section_addr) (bin, ".got")) == -1 && (got_addr = Elf_(r_bin_elf_get_section_addr) (bin, ".got.plt")) == -1) { - return -1; + return UT32_MAX; } if (bin->is_rela == DT_REL) { j = 0; @@ -1141,24 +1141,24 @@ static ut64 get_import_addr(ELFOBJ *bin, int sym) { tsize = sizeof (Elf_(Rela)); } if (!rel_sec) { - return -1; + return UT32_MAX; } if (rel_sec->size < 1) { - return -1; + return UT32_MAX; } nrel = (ut32)((int)rel_sec->size / (int)tsize); if (nrel < 1) { - return -1; + return UT32_MAX; } if (is_rela) { rela = calloc (nrel, tsize); if (!rela) { - return -1; + return UT32_MAX; } } else { rel = calloc (nrel, tsize); if (!rel) { - return -1; + return UT32_MAX; } } for (j = k = 0; j < rel_sec->size && k < nrel; j += tsize, k++) { @@ -1169,7 +1169,9 @@ static ut64 get_import_addr(ELFOBJ *bin, int sym) { if (rel_sec->offset + j + tsize > bin->size) { goto out; } - len = r_buf_read_at (bin->b, rel_sec->offset + j, is_rela? rla: rl, is_rela? sizeof (Elf_(Rela)): sizeof (Elf_(Rel))); + len = r_buf_read_at ( + bin->b, rel_sec->offset + j, is_rela ? rla : rl, + is_rela ? sizeof (Elf_ (Rela)) : sizeof (Elf_ (Rel))); if (len < 1) { goto out; } @@ -1225,7 +1227,7 @@ static ut64 get_import_addr(ELFOBJ *bin, int sym) { plt_addr = Elf_(r_bin_elf_get_section_addr) (bin, ".plt"); if (plt_addr == -1) { free (rela); - return -1; + return UT32_MAX; } if (reloc_type == R_386_PC16) { plt_addr += k * 12 + 20; @@ -1245,7 +1247,7 @@ static ut64 get_import_addr(ELFOBJ *bin, int sym) { plt_addr = Elf_(r_bin_elf_get_section_addr) (bin, ".plt"); if (plt_addr == -1) { free (rela); - return -1; + return UT32_MAX; } switch (reloc_type) { case R_386_8: @@ -1293,7 +1295,7 @@ static ut64 get_import_addr(ELFOBJ *bin, int sym) { //XXX HACK ALERT!!!! full relro?? try to fix it //will there always be .plt.got, what would happen if is .got.plt? RBinElfSection *s = get_section_by_name (bin, ".plt.got"); - if (Elf_(r_bin_elf_has_relro)(bin) != R_ELF_FULL_RELRO || !s) { + if (Elf_(r_bin_elf_has_relro)(bin) < R_ELF_PART_RELRO || !s) { goto done; } plt_addr = s->offset; @@ -1304,7 +1306,7 @@ static ut64 get_import_addr(ELFOBJ *bin, int sym) { form ff253a152000 JMP QWORD [RIP + 0x20153A] - 6690 NOP + 6690 NOP ---- ff25ec9f0408 JMP DWORD [reloc.puts_236] @@ -1382,7 +1384,7 @@ done: return plt_sym_addr; out: free (REL); - return -1; + return UT32_MAX; } int Elf_(r_bin_elf_has_nx)(ELFOBJ *bin) { @@ -2462,7 +2464,7 @@ static RBinElfSymbol* get_symbols_from_phdr(ELFOBJ *bin, int type) { if (!sym || !ret) { goto beach; } - for (i = 0, ret_ctr = 0; i < nsym; i++) { + for (i = 1, ret_ctr = 0; i < nsym; i++) { if (i >= capacity1) { // maybe grow // You take what you want, but you eat what you take. Elf_(Sym)* temp_sym = (Elf_(Sym)*) realloc(sym, (capacity1 * GROWTH_FACTOR) * sym_size); @@ -2502,13 +2504,12 @@ static RBinElfSymbol* get_symbols_from_phdr(ELFOBJ *bin, int type) { sym[i].st_shndx = READ16 (s, j); #endif // zero symbol is always empty - if (i == 0) continue; // Examine entry and maybe store if (type == R_BIN_ELF_IMPORTS && sym[i].st_shndx == STN_UNDEF) { if (sym[i].st_value) { toffset = sym[i].st_value; - } else if ((toffset = get_import_addr (bin, i)) == -1) { - toffset = 0; + } else { + toffset = get_import_addr (bin, i); } tsize = 16; } else if (type == R_BIN_ELF_SYMBOLS && @@ -2630,7 +2631,8 @@ static int Elf_(fix_symbols)(ELFOBJ *bin, int nsym, int type, RBinElfSymbol **sy if (d->offset == p->offset) { p->in_shdr = true; if (*p->name && strcmp (d->name, p->name)) { - strcpy (d->name, p->name); + //eprintf ("%s by %s\n", p->name, d->name); + //strcpy (d->name, p->name); } } p++; @@ -2784,15 +2786,17 @@ static RBinElfSymbol* Elf_(_r_bin_elf_get_symbols_imports)(ELFOBJ *bin, int type if (type == R_BIN_ELF_IMPORTS && sym[k].st_shndx == STN_UNDEF) { if (sym[k].st_value) { toffset = sym[k].st_value; - } else if ((toffset = get_import_addr (bin, k)) == -1) { - toffset = 0; + } else { + toffset = get_import_addr (bin, k); } tsize = 16; - } else if (type == R_BIN_ELF_SYMBOLS && sym[k].st_shndx != STN_UNDEF && - ELF_ST_TYPE(sym[k].st_info) != STT_SECTION && ELF_ST_TYPE(sym[k].st_info) != STT_FILE) { + } else if (type == R_BIN_ELF_SYMBOLS && + sym[k].st_shndx != STN_UNDEF && + ELF_ST_TYPE (sym[k].st_info) != STT_SECTION && + ELF_ST_TYPE (sym[k].st_info) != STT_FILE) { //int idx = sym[k].st_shndx; tsize = sym[k].st_size; - toffset = (ut64)sym[k].st_value; //-sym_offset; // + (ELF_ST_TYPE(sym[k].st_info) == STT_FUNC?sym_offset:data_offset); + toffset = (ut64)sym[k].st_value; } else { continue; } @@ -2830,6 +2834,7 @@ static RBinElfSymbol* Elf_(_r_bin_elf_get_symbols_imports)(ELFOBJ *bin, int type } } if (!ret) { + eprintf ("CALLING FROM PHDR\n"); return (type == R_BIN_ELF_SYMBOLS) ? Elf_(r_bin_elf_get_phdr_symbols) (bin) : Elf_(r_bin_elf_get_phdr_imports) (bin); diff --git a/libr/bin/p/bin_elf.c b/libr/bin/p/bin_elf.c index d34747a904..ac7d92efc9 100644 --- a/libr/bin/p/bin_elf.c +++ b/libr/bin/p/bin_elf.c @@ -592,10 +592,9 @@ static RList* relocs(RBinFile *arch) { return NULL; } bin = arch->o->bin_obj; - if (!(ret = r_list_new ())) { + if (!(ret = r_list_newf (free))) { return NULL; } - ret->free = free; /* FIXME: This is a _temporary_ fix/workaround to prevent a use-after- * free detected by ASan that would corrupt the relocation names */ r_list_free (imports (arch)); diff --git a/libr/core/cbin.c b/libr/core/cbin.c index 5dc62648f7..94790c6b79 100644 --- a/libr/core/cbin.c +++ b/libr/core/cbin.c @@ -1396,7 +1396,7 @@ static RBinSymbol *get_symbol(RBin *bin, RList *symbols, const char *name, ut64 /* XXX: This is a hack to get PLT references in rabin2 -i */ /* imp. is a prefix that can be rewritten by the symbol table */ static ut64 impaddr(RBin *bin, int va, const char *name) { - char impname[512]; + char *impname; RList *symbols; RBinSymbol *s; @@ -1406,8 +1406,7 @@ static ut64 impaddr(RBin *bin, int va, const char *name) { if (!(symbols = r_bin_get_symbols (bin))) { return false; } - // TODO: avoid using snprintf here - snprintf (impname, sizeof (impname), "imp.%s", name); + impname = sdb_fmt (2, "imp.%s", name); s = get_symbol (bin, symbols, impname, 0LL); if (s) { if (va) {