RBin: fix PE and ELF versioninfo

PE parser is now able to get the StringTable value even if the
wValueLength of the structure is incorrect.

Fix a regression with ELF versioninfo.
This commit is contained in:
Adrien Garin 2016-03-17 12:59:46 +01:00 committed by pancake
parent 76fa5bddcf
commit 10de21de7e
3 changed files with 64 additions and 37 deletions

View File

@ -449,13 +449,16 @@ static Sdb *store_versioninfo_gnu_versym(struct Elf_(r_bin_elf_obj_t) *bin, Elf_
ut64 offset = Elf_(r_bin_elf_v2p) (bin, bin->version_info[DT_VERSIONTAGIDX (DT_VERNEED)]);
do {
Elf_(Vernaux) vna;
ut64 a_off = offset + vn.vn_aux;
ut64 a_off;
if (offset > bin->size || offset + sizeof (vn) > bin->size)
goto beach;
if (r_buf_read_at (bin->b, offset, (ut8*)&vn, sizeof (vn)) < 0) {
eprintf ("Warning: Cannot read Verneed for Versym\n");
goto beach;
}
a_off = offset + vn.vn_aux;
do {
if (a_off > bin->size || a_off + sizeof (vna) > bin->size)
goto beach;
@ -469,6 +472,7 @@ static Sdb *store_versioninfo_gnu_versym(struct Elf_(r_bin_elf_obj_t) *bin, Elf_
if (vna.vna_other == data[i + j]) {
if (vna.vna_name > bin->strtab_size)
goto beach;
sdb_set (sdb_entry, key, sdb_fmt (0, "%s(%s)", tmp_val, bin->strtab + vna.vna_name), 0);
check_def = false;
break;
@ -482,8 +486,10 @@ static Sdb *store_versioninfo_gnu_versym(struct Elf_(r_bin_elf_obj_t) *bin, Elf_
if (check_def && data[i + j] != 0x8001 && vinfoaddr) {
Elf_(Verdef) vd;
ut64 offset = Elf_(r_bin_elf_v2p) (bin, vinfoaddr);
if (offset > bin->size || offset + sizeof (vd) > bin->size)
goto beach;
do {
if (r_buf_read_at (bin->b, offset, (ut8*)&vd, sizeof (vd)) < 0) {
eprintf ("Warning: Cannot read Verdef for Versym\n");
@ -504,6 +510,7 @@ static Sdb *store_versioninfo_gnu_versym(struct Elf_(r_bin_elf_obj_t) *bin, Elf_
}
if (vda.vda_name > bin->strtab_size)
goto beach;
const char *name = bin->strtab + vda.vda_name;
sdb_set (sdb_entry, key, sdb_fmt (0,"%s(%s%-*s)", tmp_val, name, (int)(12 - strlen (name)),")") , 0);
}
@ -652,9 +659,7 @@ static Sdb *store_versioninfo_gnu_verneed(struct Elf_(r_bin_elf_obj_t) *bin, Elf
aux = (Elf_(Vernaux)*)(vstart);
if (aux->vna_name > bin->dynstr_size)
goto beach;
if (!aux->vna_next)
//it'll loop forever
goto beach;
sdb_num_set (sdb_vernaux, "idx", isum, 0);
sdb_set (sdb_vernaux, "name", &bin->dynstr[aux->vna_name], 0);
sdb_set (sdb_vernaux, "flags", get_ver_flags (aux->vna_flags), 0);
@ -679,16 +684,16 @@ beach:
}
static Sdb *store_versioninfo(struct Elf_(r_bin_elf_obj_t) *bin) {
Sdb *sdb_versioninfo;
Sdb *sdb_versioninfo = NULL;
int num_verdef = 0;
int num_verneed = 0;
int num_versym = 0;
int i;
if (!bin || !bin->shdr || !sdb_versioninfo) {
if (!bin || !bin->shdr)
return NULL;
if (!(sdb_versioninfo = sdb_new0 ()))
return NULL;
}
sdb_versioninfo = sdb_new0 ();
for (i = 0; i < bin->ehdr.e_shnum; ++i) {
Sdb *sdb = NULL;

View File

@ -1178,6 +1178,10 @@ static VarFileInfo *Pe_r_bin_pe_parse_var_file_info(struct PE_(r_bin_pe_obj_t)*
static String *Pe_r_bin_pe_parse_string(struct PE_(r_bin_pe_obj_t)* bin, PE_DWord *curAddr) {
String *string = calloc (1, sizeof(*string));
PE_DWord begAddr = *curAddr;
int len_value = 0;
int i = 0;
if (string == NULL) {
eprintf ("Warning: calloc (String)\n");
return NULL;
@ -1210,36 +1214,43 @@ static String *Pe_r_bin_pe_parse_string(struct PE_(r_bin_pe_obj_t)* bin, PE_DWor
return NULL;
}
string->wKeyLen = string->wLength - string->wValueLength * 2 - sizeof(string->wLength) * 3;
string->szKey = (ut16 *) malloc (string->wKeyLen); //If there was padding, we would read it in string
if (string->szKey == NULL) {
eprintf ("Warning: malloc (String szKey)\n");
free_String(string);
return NULL;
}
for (i = 0; *curAddr < begAddr + string->wLength; ++i, *curAddr += sizeof (ut16)) {
ut16 utf16_char;
if (r_buf_read_at(bin->b, *curAddr, (ut8*)&utf16_char, sizeof (ut16)) != sizeof (ut16)) {
eprintf ("Warning: check (String szKey)\n");
free_String(string);
return NULL;
}
if (r_buf_read_at(bin->b, *curAddr, (ut8*)string->szKey, string->wKeyLen) != string->wKeyLen) {
eprintf ("Warning: read (String szKey)\n");
free_String(string);
return NULL;
string->szKey = (ut16*)realloc (string->szKey, (i + 1) * sizeof (ut16));
string->szKey[i] = utf16_char;
string->wKeyLen += sizeof (ut16);
if (!utf16_char) {
*curAddr += sizeof (ut16);
break;
}
}
*curAddr += string->wKeyLen;
align32(*curAddr);
string->Value = (ut16 *) calloc (string->wValueLength, 2);
len_value = R_MIN (string->wValueLength * 2, string->wLength - (*curAddr - begAddr));
if (len_value < 0)
len_value = 0;
string->Value = (ut16 *) calloc (len_value, 1);
if (string->Value == NULL) {
eprintf ("Warning: malloc (String Value)\n");
free_String(string);
return NULL;
}
if (r_buf_read_at(bin->b, *curAddr, (ut8*)string->Value, string->wValueLength * 2) != string->wValueLength * 2) {
if (r_buf_read_at(bin->b, *curAddr, (ut8*)string->Value, len_value) != len_value) {
eprintf ("Warning: read (String Value)\n");
free_String(string);
return NULL;
}
*curAddr += string->wValueLength * 2;
*curAddr += len_value;
return string;
}

View File

@ -1894,19 +1894,30 @@ static void bin_pe_versioninfo(RCore *r) {
if (!(sdb = sdb_ns_path (r->sdb, path_fixedfileinfo, 0)))
break;
r_cons_printf ("Signature: %s\n", sdb_const_get (sdb, "Signature", 0));
r_cons_printf ("StrucVersion: %s\n", sdb_const_get (sdb, "FileVersionMS", 0));
r_cons_printf ("FileVersionMS: %s\n", sdb_const_get (sdb, "FileVersionMS", 0));
r_cons_printf ("FileVersionLS: %s\n", sdb_const_get (sdb, "FileVersionLS", 0));
r_cons_printf ("ProductVersionMS: %s\n", sdb_const_get (sdb, "ProductVersionMS", 0));
r_cons_printf ("ProductVersionLS: %s\n", sdb_const_get (sdb, "ProductVersionLS", 0));
r_cons_printf ("FileFlagsMask: %s\n", sdb_const_get (sdb, "FileFlagsMask", 0));
r_cons_printf ("FileFlags: %s\n", sdb_const_get (sdb, "FileFlags", 0));
r_cons_printf ("FileOS: %s\n", sdb_const_get (sdb, "FileOS", 0));
r_cons_printf ("FileType: %s\n", sdb_const_get (sdb, "FileType", 0));
r_cons_printf ("FileSubType: %s\n", sdb_const_get (sdb, "FileSubType", 0));
r_cons_printf ("FileDateMS: %s\n", sdb_const_get (sdb, "FileDateMS", 0));
r_cons_printf ("FileDateLS: %s\n", sdb_const_get (sdb, "FileDateLS", 0));
r_cons_printf (" Signature: 0x%"PFMT64x"\n", sdb_num_get (sdb, "Signature", 0));
r_cons_printf (" StrucVersion: 0x%"PFMT64x"\n", sdb_num_get (sdb, "StrucVersion", 0));
r_cons_printf (" FileVersion: %"PFMT64d".%"PFMT64d".%"PFMT64d".%"PFMT64d"\n",
sdb_num_get (sdb, "FileVersionMS", 0) >> 16,
sdb_num_get (sdb, "FileVersionMS", 0) & 0xFFFF,
sdb_num_get (sdb, "FileVersionLS", 0) >> 16,
sdb_num_get (sdb, "FileVersionLS", 0) & 0xFFFF);
r_cons_printf (" ProductVersion: %"PFMT64d".%"PFMT64d".%"PFMT64d".%"PFMT64d"\n",
sdb_num_get (sdb, "ProductVersionMS", 0) >> 16,
sdb_num_get (sdb, "ProductVersionMS", 0) & 0xFFFF,
sdb_num_get (sdb, "ProductVersionLS", 0) >> 16,
sdb_num_get (sdb, "ProductVersionLS", 0) & 0xFFFF);
r_cons_printf (" FileFlagsMask: 0x%"PFMT64x"\n", sdb_num_get (sdb, "FileFlagsMask", 0));
r_cons_printf (" FileFlags: 0x%"PFMT64x"\n", sdb_num_get (sdb, "FileFlags", 0));
r_cons_printf (" FileOS: 0x%"PFMT64x"\n", sdb_num_get (sdb, "FileOS", 0));
r_cons_printf (" FileType: 0x%"PFMT64x"\n", sdb_num_get (sdb, "FileType", 0));
r_cons_printf (" FileSubType: 0x%"PFMT64x"\n", sdb_num_get (sdb, "FileSubType", 0));
#if 0
r_cons_printf (" FileDate: %d.%d.%d.%d\n",
sdb_num_get (sdb, "FileDateMS", 0) >> 16,
sdb_num_get (sdb, "FileDateMS", 0) & 0xFFFF,
sdb_num_get (sdb, "FileDateLS", 0) >> 16,
sdb_num_get (sdb, "FileDateLS", 0) & 0xFFFF);
#endif
r_cons_printf ("\n");
r_cons_printf ("# StringTable\n\n");
@ -1930,7 +1941,7 @@ static void bin_pe_versioninfo(RCore *r) {
|| r_str_utf16_to_utf8 (val_utf8, lenval * 2, val_utf16, lenval, true) < 0) {
eprintf ("Warning: Cannot decode utf16 to utf8\n");
} else {
r_cons_printf ("%s: %s\n", (char*)key_utf8, (char*)val_utf8);
r_cons_printf (" %s: %s\n", (char*)key_utf8, (char*)val_utf8);
}
free (key_utf8);