From 98d33eb08449abb731edc798053bb057bb199f24 Mon Sep 17 00:00:00 2001 From: pancake Date: Fri, 23 May 2014 14:34:27 +0200 Subject: [PATCH] Fix several segfaults found by matalaz in PE, MACH0 and COFF --- libr/bin/demangle.c | 3 +- libr/bin/format/coff/coff.c | 8 ++-- libr/bin/format/pe/pe.c | 92 +++++++++++++++++++++++++++---------- libr/bin/p/bin_coff.c | 4 +- libr/bin/p/bin_pe.c | 11 +++-- 5 files changed, 87 insertions(+), 31 deletions(-) diff --git a/libr/bin/demangle.c b/libr/bin/demangle.c index bff90cd29d..8adabbbd41 100644 --- a/libr/bin/demangle.c +++ b/libr/bin/demangle.c @@ -156,7 +156,8 @@ R_API char *r_bin_demangle_objc(RBinFile *binfile, const char *sym) { } if (type) { if (!strcmp (type, "field")) { - ret = malloc (strlen (clas)+strlen (name)+32); + int namelen = name?strlen (name):0; + ret = malloc (strlen (clas)+namelen+32); if (ret) sprintf (ret, "field int %s::%s", clas, name); } else { if (nargs) { diff --git a/libr/bin/format/coff/coff.c b/libr/bin/format/coff/coff.c index 04e1c12174..2da67e2737 100644 --- a/libr/bin/format/coff/coff.c +++ b/libr/bin/format/coff/coff.c @@ -200,7 +200,6 @@ static int r_bin_coff_init_symtable(struct r_bin_coff_obj *obj) for (i = 0; i < obj->hdr.symbols_num; i++) { r_mem_copyendian((ut8*)&short_name, obj->b->buf + offset, sizeof(ut32), obj->endian); - if (short_name) { obj->symbols[i].name = malloc(sizeof(char) * 9); strncpy(obj->symbols[i].name, @@ -209,9 +208,12 @@ static int r_bin_coff_init_symtable(struct r_bin_coff_obj *obj) offset += 8; } else { offset += sizeof(ut32); - r_mem_copyendian((ut8*)&ofst, obj->b->buf + offset, + r_mem_copyendian ((ut8*)&ofst, obj->b->buf + offset, sizeof(ut32), obj->endian); - + if (ofst+obj->hdr.symtable_offset > obj->b->length) { + eprintf ("Symtable offset out of bounds\n"); + return 0; + } obj->symbols[i].name = strdup((char*)(obj->b->buf + obj->hdr.symtable_offset + ofst + obj->hdr.symbols_num * 18)); diff --git a/libr/bin/format/pe/pe.c b/libr/bin/format/pe/pe.c index 09474f76b2..4c46100bff 100644 --- a/libr/bin/format/pe/pe.c +++ b/libr/bin/format/pe/pe.c @@ -12,6 +12,8 @@ ut64 PE_(r_bin_pe_get_main_vaddr)(struct PE_(r_bin_pe_obj_t) *bin) { ut64 addr = 0; ut8 buf[512]; + if (!bin || !bin->b) + return 0LL; // option2: /x 8bff558bec83ec20 buf[367] = 0; if (r_buf_read_at (bin->b, entry->paddr, buf, sizeof (buf)) == -1) { @@ -56,14 +58,19 @@ static PE_DWord PE_(r_bin_pe_paddr_to_vaddr)(struct PE_(r_bin_pe_obj_t)* bin, PE #endif static int PE_(r_bin_pe_get_import_dirs_count)(struct PE_(r_bin_pe_obj_t) *bin) { + if (!bin || !bin->nt_headers) + return 0; PE_(image_data_directory) *data_dir_import = &bin->nt_headers->optional_header.DataDirectory[PE_IMAGE_DIRECTORY_ENTRY_IMPORT]; return (int)(data_dir_import->Size / sizeof(PE_(image_import_directory)) - 1); } static int PE_(r_bin_pe_get_delay_import_dirs_count)(struct PE_(r_bin_pe_obj_t) *bin) { - PE_(image_data_directory) *data_dir_delay_import = \ - &bin->nt_headers->optional_header.DataDirectory[PE_IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT]; + PE_(image_data_directory) *data_dir_delay_import; + if (!bin || !bin->nt_headers) + return 0; + data_dir_delay_import = \ + &bin->nt_headers->optional_header.DataDirectory[PE_IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT]; return (int)(data_dir_delay_import->Size / sizeof(PE_(image_delay_import_directory)) - 1); } @@ -162,13 +169,11 @@ typedef struct { static struct r_bin_pe_export_t* parse_symbol_table(struct PE_(r_bin_pe_obj_t)* bin, struct r_bin_pe_export_t *exports, int sz) { //ut64 baddr = (ut64)bin->nt_headers->optional_header.ImageBase; - ut64 off = bin->nt_headers->file_header.PointerToSymbolTable; - ut64 num = bin->nt_headers->file_header.NumberOfSymbols; + ut64 off, num; const int srsz = 18; // symbol record size struct r_bin_pe_section_t* sections; struct r_bin_pe_export_t* exp; - int bufsz = num * srsz; - int I, i, shsz = bufsz; + int bufsz, I, i, shsz = bufsz; SymbolRecord *sr; ut64 text_off = 0LL; ut64 text_vaddr = 0LL; @@ -177,8 +182,11 @@ static struct r_bin_pe_export_t* parse_symbol_table(struct PE_(r_bin_pe_obj_t)* int exports_sz; int symctr = 0; char *buf; - if (bufsz<1 || bufsz>bin->size) + if (!bin || bufsz<1 || bufsz>bin->size) return 0; + off = bin->nt_headers->file_header.PointerToSymbolTable; + num = bin->nt_headers->file_header.NumberOfSymbols; + shsz = bufsz = num * srsz; buf = malloc (bufsz); if (!buf) return 0; @@ -510,6 +518,8 @@ static int PE_(r_bin_pe_init)(struct PE_(r_bin_pe_obj_t)* bin) { char* PE_(r_bin_pe_get_arch)(struct PE_(r_bin_pe_obj_t)* bin) { char *arch; + if (!bin || !bin->nt_headers) + return strdup ("x86"); switch (bin->nt_headers->file_header.Machine) { case PE_IMAGE_FILE_MACHINE_ALPHA: case PE_IMAGE_FILE_MACHINE_ALPHA64: @@ -543,6 +553,8 @@ char* PE_(r_bin_pe_get_arch)(struct PE_(r_bin_pe_obj_t)* bin) { struct r_bin_pe_addr_t* PE_(r_bin_pe_get_entrypoint)(struct PE_(r_bin_pe_obj_t)* bin) { struct r_bin_pe_addr_t *entry = NULL; + if (!bin || !bin->nt_headers) + return NULL; if ((entry = malloc(sizeof(struct r_bin_pe_addr_t))) == NULL) { perror("malloc (entrypoint)"); return NULL; @@ -560,12 +572,18 @@ struct r_bin_pe_export_t* PE_(r_bin_pe_get_exports)(struct PE_(r_bin_pe_obj_t)* PE_VWord functions_paddr, names_paddr, ordinals_paddr, function_vaddr, name_vaddr, name_paddr; char function_name[PE_NAME_LENGTH + 1], forwarder_name[PE_NAME_LENGTH + 1]; char dll_name[PE_NAME_LENGTH + 1], export_name[PE_NAME_LENGTH + 1]; - PE_(image_data_directory) *data_dir_export = \ - &bin->nt_headers->optional_header.DataDirectory[PE_IMAGE_DIRECTORY_ENTRY_EXPORT]; - PE_VWord export_dir_vaddr = data_dir_export->VirtualAddress; - int i, export_dir_size = data_dir_export->Size; + PE_(image_data_directory) *data_dir_export; + PE_VWord export_dir_vaddr ; + int i, export_dir_size; int exports_sz = 0; + if (!bin || !bin->nt_headers) + return NULL; + data_dir_export = \ + &bin->nt_headers->optional_header.DataDirectory[PE_IMAGE_DIRECTORY_ENTRY_EXPORT]; +export_dir_vaddr = data_dir_export->VirtualAddress; + export_dir_size = data_dir_export->Size; + if (bin->export_directory) { exports_sz = (bin->export_directory->NumberOfNames + 1) * sizeof(struct r_bin_pe_export_t); if (!(exports = malloc (exports_sz))) @@ -633,6 +651,8 @@ int PE_(r_bin_pe_get_file_alignment)(struct PE_(r_bin_pe_obj_t)* bin) { } ut64 PE_(r_bin_pe_get_image_base)(struct PE_(r_bin_pe_obj_t)* bin) { + if (!bin || !bin->nt_headers) + return 0LL; return (ut64)bin->nt_headers->optional_header.ImageBase; } @@ -683,6 +703,8 @@ struct r_bin_pe_lib_t* PE_(r_bin_pe_get_libs)(struct PE_(r_bin_pe_obj_t) *bin) { int delay_import_dirs_count = PE_(r_bin_pe_get_delay_import_dirs_count)(bin); int mallocsz, i, j = 0; + if (!bin) + return NULL; /* NOTE: import_dirs and delay_import_dirs can be -1 */ mallocsz = (import_dirs_count + delay_import_dirs_count + 3) * \ sizeof (struct r_bin_pe_lib_t); @@ -737,6 +759,8 @@ int PE_(r_bin_pe_get_image_size)(struct PE_(r_bin_pe_obj_t)* bin) { char* PE_(r_bin_pe_get_machine)(struct PE_(r_bin_pe_obj_t)* bin) { char *machine; + if (!bin || !bin->nt_headers) + return NULL; switch (bin->nt_headers->file_header.Machine) { case PE_IMAGE_FILE_MACHINE_ALPHA: machine = strdup("Alpha"); @@ -831,7 +855,8 @@ char* PE_(r_bin_pe_get_machine)(struct PE_(r_bin_pe_obj_t)* bin) { // TODO: make it const! like in elf char* PE_(r_bin_pe_get_os)(struct PE_(r_bin_pe_obj_t)* bin) { char *os; - + if (!bin || !bin->nt_headers) + return NULL; switch (bin->nt_headers->optional_header.Subsystem) { case PE_IMAGE_SUBSYSTEM_NATIVE: os = strdup("native"); @@ -863,23 +888,23 @@ char* PE_(r_bin_pe_get_os)(struct PE_(r_bin_pe_obj_t)* bin) { // TODO: make it const char* PE_(r_bin_pe_get_class)(struct PE_(r_bin_pe_obj_t)* bin) { char *class; - + if (!bin || !bin->nt_headers) + return NULL; switch (bin->nt_headers->optional_header.Magic) { case PE_IMAGE_FILE_TYPE_PE32: - class = strdup("PE32"); - break; + return strdup("PE32"); case PE_IMAGE_FILE_TYPE_PE32PLUS: - class = strdup("PE32+"); - break; + return strdup("PE32+"); default: - class = strdup("Unknown"); + return strdup("Unknown"); } - return class; + return NULL; } int PE_(r_bin_pe_get_bits)(struct PE_(r_bin_pe_obj_t)* bin) { int bits; - + if (!bin || !bin->nt_headers) + return 32; switch (bin->nt_headers->optional_header.Magic) { case PE_IMAGE_FILE_TYPE_PE32: bits = 32; @@ -894,14 +919,20 @@ int PE_(r_bin_pe_get_bits)(struct PE_(r_bin_pe_obj_t)* bin) { } int PE_(r_bin_pe_get_section_alignment)(struct PE_(r_bin_pe_obj_t)* bin) { + if (!bin || !bin->nt_headers) + return 0; return bin->nt_headers->optional_header.SectionAlignment; } struct r_bin_pe_section_t* PE_(r_bin_pe_get_sections)(struct PE_(r_bin_pe_obj_t)* bin) { struct r_bin_pe_section_t *sections = NULL; - PE_(image_section_header) *shdr = bin->section_header; - int i, sections_count = bin->nt_headers->file_header.NumberOfSections; + PE_(image_section_header) *shdr; + int i, sections_count; + if (!bin || !bin->nt_headers) + return 0; +shdr = bin->section_header; + sections_count = bin->nt_headers->file_header.NumberOfSections; if ((sections = malloc ((sections_count + 1) * sizeof (struct r_bin_pe_section_t))) == NULL) { perror ("malloc (sections)"); return NULL; @@ -922,7 +953,8 @@ struct r_bin_pe_section_t* PE_(r_bin_pe_get_sections)(struct PE_(r_bin_pe_obj_t) char* PE_(r_bin_pe_get_subsystem)(struct PE_(r_bin_pe_obj_t)* bin) { char *subsystem; - + if (!bin || !bin->nt_headers) + return NULL; switch (bin->nt_headers->optional_header.Subsystem) { case PE_IMAGE_SUBSYSTEM_NATIVE: subsystem = strdup("Native"); @@ -961,10 +993,14 @@ char* PE_(r_bin_pe_get_subsystem)(struct PE_(r_bin_pe_obj_t)* bin) { } int PE_(r_bin_pe_is_dll)(struct PE_(r_bin_pe_obj_t)* bin) { + if (!bin || !bin->nt_headers) + return 0; return bin->nt_headers->file_header.Characteristics & PE_IMAGE_FILE_DLL; } int PE_(r_bin_pe_is_pie)(struct PE_(r_bin_pe_obj_t)* bin) { + if (!bin || !bin->nt_headers) + return 0; return bin->nt_headers->optional_header.DllCharacteristics & IMAGE_DLLCHARACTERISTICS_DYNAMIC_BASE; #if 0 BOOL aslr = inh->OptionalHeader.DllCharacteristics & IMAGE_DLLCHARACTERISTICS_DYNAMIC_BASE; @@ -974,22 +1010,32 @@ int PE_(r_bin_pe_is_pie)(struct PE_(r_bin_pe_obj_t)* bin) { } int PE_(r_bin_pe_is_big_endian)(struct PE_(r_bin_pe_obj_t)* bin) { + if (!bin || !bin->nt_headers) + return 0; return bin->nt_headers->file_header.Characteristics & PE_IMAGE_FILE_BYTES_REVERSED_HI; } int PE_(r_bin_pe_is_stripped_relocs)(struct PE_(r_bin_pe_obj_t)* bin) { + if (!bin || !bin->nt_headers) + return 0; return bin->nt_headers->file_header.Characteristics & PE_IMAGE_FILE_RELOCS_STRIPPED; } int PE_(r_bin_pe_is_stripped_line_nums)(struct PE_(r_bin_pe_obj_t)* bin) { + if (!bin || !bin->nt_headers) + return 0; return bin->nt_headers->file_header.Characteristics & PE_IMAGE_FILE_LINE_NUMS_STRIPPED; } int PE_(r_bin_pe_is_stripped_local_syms)(struct PE_(r_bin_pe_obj_t)* bin) { + if (!bin || !bin->nt_headers) + return 0; return bin->nt_headers->file_header.Characteristics & PE_IMAGE_FILE_LOCAL_SYMS_STRIPPED; } int PE_(r_bin_pe_is_stripped_debug)(struct PE_(r_bin_pe_obj_t)* bin) { + if (!bin || !bin->nt_headers) + return 0; return bin->nt_headers->file_header.Characteristics & PE_IMAGE_FILE_DEBUG_STRIPPED; } diff --git a/libr/bin/p/bin_coff.c b/libr/bin/p/bin_coff.c index 1a73a6659e..ce602f1b35 100644 --- a/libr/bin/p/bin_coff.c +++ b/libr/bin/p/bin_coff.c @@ -129,8 +129,10 @@ static RList *symbols(RBinFile *arch) if (!(ptr = R_NEW0 (RBinSymbol))) break; - strncpy (ptr->name, obj->symbols[i].name, + if (obj->symbols[i].name) + strncpy (ptr->name, obj->symbols[i].name, R_BIN_SIZEOF_STRINGS); + else *ptr->name = 0; strncpy (ptr->forwarder, "NONE", R_BIN_SIZEOF_STRINGS); strncpy (ptr->bind, "", R_BIN_SIZEOF_STRINGS); diff --git a/libr/bin/p/bin_pe.c b/libr/bin/p/bin_pe.c index be7acf368f..778a5cc476 100644 --- a/libr/bin/p/bin_pe.c +++ b/libr/bin/p/bin_pe.c @@ -10,8 +10,9 @@ static int check(RBinFile *arch); static int check_bytes(const ut8 *buf, ut64 length); static Sdb* get_sdb (RBinObject *o) { - if (!o) return NULL; - struct PE_(r_bin_pe_obj_t) *bin = (struct PE_(r_bin_pe_obj_t) *) o->bin_obj; + struct PE_(r_bin_pe_obj_t) *bin; + if (!o || !o->bin_obj) return NULL; + bin = (struct PE_(r_bin_pe_obj_t) *) o->bin_obj; if (bin->kv) return bin->kv; return NULL; } @@ -163,6 +164,8 @@ static RList* imports(RBinFile *arch) { struct r_bin_pe_import_t *imports = NULL; int i; + if (!arch || !arch->o || !arch->o->bin_obj) + return NULL; if (!(ret = r_list_new ()) || !(relocs = r_list_new ())) return NULL; @@ -205,7 +208,9 @@ static RList* imports(RBinFile *arch) { } static RList* relocs(RBinFile *arch) { - return ((struct PE_(r_bin_pe_obj_t)*)arch->o->bin_obj)->relocs; + struct PE_(r_bin_pe_obj_t)* obj= arch->o->bin_obj; + if (obj) return obj->relocs; + return NULL; } static RList* libs(RBinFile *arch) {