Fix #7086 - plt calculation with partial relro elf

This commit is contained in:
alvarofe 2017-04-09 12:17:56 +02:00
parent 94d85cad32
commit e1c89440b3
3 changed files with 33 additions and 30 deletions

View File

@ -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);

View File

@ -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));

View File

@ -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) {