Fix #11981 - Show PE resource name instead of just the index and use pj.c ##bin

This commit is contained in:
koffiedrinker 2019-01-22 09:44:54 +01:00 committed by radare
parent 01d5dfe306
commit 1393eca17d
3 changed files with 47 additions and 13 deletions

View File

@ -1215,6 +1215,7 @@ static int bin_pe_init_exports(struct PE_(r_bin_pe_obj_t)* bin) {
static void _free_resources(r_pe_resource *rs) {
if (rs) {
free (rs->name);
free (rs->timestr);
free (rs->data);
free (rs->type);
@ -2242,7 +2243,7 @@ static char* _resource_type_str(int type) {
return strdup (typeName);
}
static void _parse_resource_directory(struct PE_(r_bin_pe_obj_t) *bin, Pe_image_resource_directory *dir, ut64 offDir, int type, int id, HtUU *dirs) {
static void _parse_resource_directory(struct PE_(r_bin_pe_obj_t) *bin, Pe_image_resource_directory *dir, ut64 offDir, int type, int id, HtUU *dirs, char *resource_name) {
int index = 0;
ut32 totalRes = dir->NumberOfNamedEntries + dir->NumberOfIdEntries;
ut64 rsrc_base = bin->resource_directory_offset;
@ -2264,6 +2265,16 @@ static void _parse_resource_directory(struct PE_(r_bin_pe_obj_t) *bin, Pe_image_
eprintf ("Warning: read resource entry\n");
break;
}
ut8 *resourceEntryName = NULL;
if (entry.u1.s.NameIsString) {
ut16 resourceEntryNameLength;
r_buf_read_at (bin->b, bin->resource_directory_offset + entry.u1.s.NameOffset, (ut8*)&resourceEntryNameLength, sizeof (ut16));
resourceEntryName = calloc (resourceEntryNameLength, sizeof (ut8));
for(int i = 0; i < 2 * resourceEntryNameLength; i += 2) { /* Convert Unicode to ASCII */
r_buf_read_at (bin->b, bin->resource_directory_offset + entry.u1.s.NameOffset + 2 + i, resourceEntryName + (i/2), sizeof (ut8));
}
}
if (entry.u2.s.DataIsDirectory) {
//detect here malicious file trying to making us infinite loop
Pe_image_resource_directory identEntry;
@ -2272,9 +2283,16 @@ static void _parse_resource_directory(struct PE_(r_bin_pe_obj_t) *bin, Pe_image_
if (len < 1 || len != sizeof (Pe_image_resource_directory)) {
eprintf ("Warning: parsing resource directory\n");
}
if(resource_name != NULL && resourceEntryName != NULL) {
/* We're about to recursively call this function with a new resource entry name
and we haven't used resource_name, so free it. Only happens in weird PEs. */
free (resource_name);
}
_parse_resource_directory (bin, &identEntry,
entry.u2.s.OffsetToDirectory, type, entry.u1.Id, dirs);
entry.u2.s.OffsetToDirectory, type, entry.u1.Id, dirs, (char *)resourceEntryName);
continue;
} else {
free (resourceEntryName);
}
Pe_image_resource_data_entry *data = R_NEW0 (Pe_image_resource_data_entry);
@ -2346,7 +2364,12 @@ static void _parse_resource_directory(struct PE_(r_bin_pe_obj_t) *bin, Pe_image_
rs->type = _resource_type_str (type);
rs->language = strdup (_resource_lang_str (entry.u1.Name & 0x3ff));
rs->data = data;
rs->name = id;
if (resource_name) {
rs->name = resource_name;
} else {
char numberbuf[6];
rs->name = strdup (sdb_itoa (id, numberbuf, 10));
}
r_list_append (bin->resources, rs);
}
}
@ -2368,7 +2391,7 @@ static void _store_resource_sdb(struct PE_(r_bin_pe_obj_t) *bin) {
vaddr = bin_pe_rva_to_va (bin, rs->data->OffsetToData);
sdb_num_set (sdb, key, vaddr, 0);
key = sdb_fmt ("resource.%d.name", index);
sdb_num_set (sdb, key, rs->name, 0);
sdb_set (sdb, key, rs->name, 0);
key = sdb_fmt ("resource.%d.size", index);
sdb_num_set (sdb, key, rs->data->Size, 0);
key = sdb_fmt ("resource.%d.type", index);
@ -2421,7 +2444,7 @@ R_API void PE_(bin_pe_parse_resource)(struct PE_(r_bin_pe_obj_t) *bin) {
if (len < 1 || len != sizeof (identEntry)) {
eprintf ("Warning: parsing resource directory\n");
}
_parse_resource_directory (bin, &identEntry, typeEntry.u2.s.OffsetToDirectory, typeEntry.u1.Id, 0, dirs);
_parse_resource_directory (bin, &identEntry, typeEntry.u2.s.OffsetToDirectory, typeEntry.u1.Id, 0, dirs, NULL);
}
}
ht_uu_free (dirs);

View File

@ -68,7 +68,7 @@ typedef struct _PE_RESOURCE {
char *timestr;
char *type;
char *language;
int name;
char *name;
Pe_image_resource_data_entry *data;
} r_pe_resource;

View File

@ -3232,6 +3232,7 @@ static void bin_mach0_versioninfo(RCore *r) {
static void bin_pe_resources(RCore *r, int mode) {
Sdb *sdb = NULL;
int index = 0;
PJ *pj = NULL;
const char *pe_path = "bin/cur/info/pe_resource";
if (!(sdb = sdb_ns_path (r->sdb, pe_path, 0))) {
return;
@ -3241,7 +3242,8 @@ static void bin_pe_resources(RCore *r, int mode) {
} else if (IS_MODE_RAD (mode)) {
r_cons_printf ("fs resources\n");
} else if (IS_MODE_JSON (mode)) {
r_cons_printf ("[");
pj = pj_new ();
pj_a (pj);
}
while (true) {
const char *timestrKey = sdb_fmt ("resource.%d.timestr", index);
@ -3256,7 +3258,7 @@ static void bin_pe_resources(RCore *r, int mode) {
}
ut64 vaddr = sdb_num_get (sdb, vaddrKey, 0);
int size = (int)sdb_num_get (sdb, sizeKey, 0);
int name = (int)sdb_num_get (sdb, nameKey, 0);
char *name = sdb_get (sdb, nameKey, 0);
char *type = sdb_get (sdb, typeKey, 0);
char *lang = sdb_get (sdb, languageKey, 0);
@ -3266,14 +3268,20 @@ static void bin_pe_resources(RCore *r, int mode) {
} else if (IS_MODE_RAD (mode)) {
r_cons_printf ("f resource.%d %d 0x%08"PFMT32x"\n", index, size, vaddr);
} else if (IS_MODE_JSON (mode)) {
r_cons_printf ("%s{\"name\":%d,\"index\":%d, \"type\":\"%s\","
"\"vaddr\":%"PFMT64d", \"size\":%d, \"lang\":\"%s\", \"timestamp\":\"%s\"}",
index? ",": "", name, index, type, vaddr, size, lang, timestr);
pj_o (pj);
pj_ks (pj, "name", name);
pj_ki (pj, "index", index);
pj_ks (pj, "type", type);
pj_kn (pj, "vaddr", vaddr);
pj_ki (pj, "size", size);
pj_ks (pj, "lang", lang);
pj_ks (pj, "timestamp", timestr);
pj_end (pj);
} else {
char humansz[8];
r_num_units (humansz, sizeof (humansz), size);
r_cons_printf ("Resource %d\n", index);
r_cons_printf (" name: %d\n", name);
r_cons_printf (" name: %s\n", name);
r_cons_printf (" timestamp: %s\n", timestr);
r_cons_printf (" vaddr: 0x%08"PFMT64x"\n", vaddr);
r_cons_printf (" size: %s\n", humansz);
@ -3282,13 +3290,16 @@ static void bin_pe_resources(RCore *r, int mode) {
}
R_FREE (timestr);
R_FREE (name);
R_FREE (type);
R_FREE (lang)
index++;
}
if (IS_MODE_JSON (mode)) {
r_cons_printf ("]");
pj_end (pj);
r_cons_printf ("%s\n", pj_string (pj));
pj_free (pj);
} else if (IS_MODE_RAD (mode)) {
r_cons_printf ("fs *");
}