void r_binfmt_elf32_load_symtab(r_binfmt_s *bin, r_binfmt_elf32_s *elf) { Elf32_Word i, sh_type, sh_size; Elf32_Off sh_offset; R_BINFMT_ASSERT(elf->ehdr != NULL); R_BINFMT_ASSERT(elf->shdr != NULL); for(i = 0; i < elf->shdr_entries; i++) { R_BINFMT_GET_INT(sh_type, elf->shdr[i].sh_type, bin->endian); if(sh_type == SHT_SYMTAB) { R_BINFMT_GET_INT(sh_size, elf->shdr[i].sh_size, bin->endian); R_BINFMT_ASSERT((sh_size % sizeof(Elf32_Sym)) == 0); R_BINFMT_GET_INT(sh_offset, elf->shdr[i].sh_offset, bin->endian); R_BINFMT_ASSERT(r_utils_add32(NULL, sh_offset, sh_size) && sh_offset + sh_size <= bin->mapped_size); elf->symtab = (Elf32_Sym*)(bin->mapped + sh_offset); elf->symtab_entries = sh_size / sizeof(Elf32_Sym); break; } } }
/* Fill bin->sections structure */ static void r_binfmt_elf32_load_sections(r_binfmt_s *bin, r_binfmt_elf32_s *elf) { r_binfmt_section_s *section; Elf32_Word sh_name, sh_size, i; Elf32_Off strndx_off; Elf32_Addr sh_addr; Elf32_Half e_shstrndx; R_BINFMT_ASSERT(elf->ehdr != NULL); R_BINFMT_ASSERT(elf->shdr != NULL); R_BINFMT_GET_INT(e_shstrndx, elf->ehdr->e_shstrndx, bin->endian); R_BINFMT_ASSERT(e_shstrndx < elf->shdr_entries); R_BINFMT_GET_INT(strndx_off, elf->shdr[e_shstrndx].sh_offset, bin->endian); for(i = 0; i < elf->shdr_entries; i++) { R_BINFMT_GET_INT(sh_addr, elf->shdr[i].sh_addr, bin->endian); R_BINFMT_GET_INT(sh_size, elf->shdr[i].sh_size, bin->endian); R_BINFMT_GET_INT(sh_name, elf->shdr[i].sh_name, bin->endian); R_BINFMT_ASSERT(r_utils_add32(NULL, strndx_off, sh_name) && strndx_off + sh_name <= bin->mapped_size); section = r_binfmt_section_new(); section->addr = sh_addr; section->size = sh_size; section->name = r_binfmt_elf32_get_name(bin, elf, e_shstrndx, sh_name); r_utils_linklist_push(&bin->sections, section); } }
/* Check evil or malformed files */ static int r_binfmt_macho64_check(r_binfmt_s *bin) { r_binfmt_macho64_header_s *hdr; r_binfmt_macho_cmd_s *cmd; u32 tmp, i, cmd_num, cmd_size, off, type; /* Already checked in r_binfmt_machoXX_is(), but if the check is removed in the future, the r_binfmt_machoXX_check() function must handle this case */ if(bin->mapped_size < sizeof(*hdr)) return 0; hdr = (r_binfmt_macho64_header_s*)(bin->mapped); cmd_num = r_binfmt_get_int32((byte_t*)&hdr->h_cmd_num, bin->endian); /* Check each command */ off = 0; for(i = 0; i < cmd_num; i++) { /* Check if off+sizeof(*hdr)+sizeof(*cmd) isn't greater than bin->mapped_size */ if(!r_utils_add32(&tmp, sizeof(*hdr)+sizeof(*cmd), off)) return 0; if(bin->mapped_size < tmp) return 0; cmd = (r_binfmt_macho_cmd_s*)(bin->mapped + off + sizeof(*hdr)); /* Now check command */ type = r_binfmt_get_int32((byte_t*)&cmd->type, bin->endian); if(type == R_BINFMT_MACHO_CMD_TYPE_SEGMENT64) { if(!r_binfmt_macho64_check_segment(bin, (r_binfmt_macho64_segment_s*)cmd)) return 0; } cmd_size = r_binfmt_get_int32((byte_t*)&cmd->size, bin->endian); if(!cmd_size) return 0; if(!r_utils_add32(&off, off, cmd_size)) return 0; } return 1; }
/* Check the fields of the machoXX segment */ static int r_binfmt_macho32_check_segment(r_binfmt_s *bin, r_binfmt_macho32_segment_s *seg) { u32 filesz, fileoff; u32 off; off = ((byte_t*)seg) - bin->mapped; if(!r_utils_add32(NULL, off, sizeof(*seg))) return 0; if(bin->mapped_size < off + sizeof(*seg)) return 0; R_BINFMT_GET_INT(filesz, seg->file_size, bin->endian); R_BINFMT_GET_INT(fileoff, seg->file_off, bin->endian); if(!r_utils_add32(&off, fileoff, filesz)) return 0; if(bin->mapped_size < off) return 0; return 1; }
static const char* r_binfmt_elf32_get_name(r_binfmt_s *bin, r_binfmt_elf32_s *elf, Elf32_Half section_id, Elf32_Word name) { Elf32_Off sh_offset; Elf32_Word sh_size; R_BINFMT_GET_INT(sh_offset, elf->shdr[section_id].sh_offset, bin->endian); R_BINFMT_GET_INT(sh_size, elf->shdr[section_id].sh_size, bin->endian); R_BINFMT_ASSERT_RET("", r_utils_add32(NULL, sh_offset, sh_size) && sh_offset + sh_size <= bin->mapped_size); R_BINFMT_ASSERT_RET("", name < sh_size); return (const char*)(bin->mapped + sh_offset + name); }
void r_binfmt_elf32_load_shdr(r_binfmt_s *bin, r_binfmt_elf32_s *elf) { Elf32_Off e_shoff; Elf32_Half e_shnum; R_BINFMT_ASSERT(elf->ehdr != NULL); R_BINFMT_GET_INT(e_shoff, elf->ehdr->e_shoff, bin->endian); R_BINFMT_ASSERT(e_shoff < bin->mapped_size); R_BINFMT_GET_INT(e_shnum, elf->ehdr->e_shnum, bin->endian); R_BINFMT_ASSERT(r_utils_add32(NULL, e_shnum*sizeof(Elf32_Shdr), e_shoff) && e_shnum*sizeof(Elf32_Shdr) + e_shoff <= bin->mapped_size); elf->shdr = (Elf32_Shdr*)(bin->mapped + e_shoff); elf->shdr_entries = e_shnum; }
/* Fill bin->segments structure */ static void r_binfmt_elf32_load_segments(r_binfmt_s *bin, r_binfmt_elf32_s *elf) { r_binfmt_segment_s *seg; Elf32_Word i, p_type, p_flags, p_filesz; Elf32_Off p_offset; Elf32_Addr p_vaddr; Elf32_Half e_phnum; R_BINFMT_ASSERT(elf->ehdr != NULL); R_BINFMT_ASSERT(elf->phdr != NULL); R_BINFMT_GET_INT(e_phnum, elf->ehdr->e_phnum, bin->endian); for(i = 0; i < e_phnum; i++) { R_BINFMT_GET_INT(p_type, elf->phdr[i].p_type, bin->endian); R_BINFMT_GET_INT(p_flags, elf->phdr[i].p_flags, bin->endian); R_BINFMT_GET_INT(p_vaddr, elf->phdr[i].p_vaddr, bin->endian); R_BINFMT_GET_INT(p_offset, elf->phdr[i].p_offset, bin->endian); R_BINFMT_GET_INT(p_filesz, elf->phdr[i].p_filesz, bin->endian); R_BINFMT_ASSERT(r_utils_add32(NULL, p_offset, p_filesz) && p_offset + p_filesz <= bin->mapped_size); if(p_type == PT_LOAD) { seg = r_binfmt_segment_new(); seg->flags = 0; if(p_flags & PF_X) seg->flags |= R_BINFMT_SEGMENT_FLAG_PROT_X; if(p_flags & PF_R) seg->flags |= R_BINFMT_SEGMENT_FLAG_PROT_R; if(p_flags & PF_W) seg->flags |= R_BINFMT_SEGMENT_FLAG_PROT_W; seg->addr = p_vaddr; seg->length = p_filesz; seg->start = bin->mapped + p_offset; r_utils_linklist_push(&bin->segments, seg); } } }
static void r_binfmt_elf32_load_syms_dyntab(r_binfmt_s *bin, r_binfmt_elf32_s *elf) { r_binfmt_sym_s *sym; Elf32_Half sh_link, st_name; Elf32_Off link_off; Elf32_Word i, sh_type; R_BINFMT_ASSERT(elf->ehdr != NULL); R_BINFMT_ASSERT(elf->shdr != NULL); R_BINFMT_ASSERT(elf->dynsym != NULL); sh_link = 0xFFFF; for(i = 0; i < elf->shdr_entries; i++) { R_BINFMT_GET_INT(sh_type, elf->shdr[i].sh_type, bin->endian); if(sh_type == SHT_DYNSYM) { R_BINFMT_GET_INT(sh_link, elf->shdr[i].sh_link, bin->endian); R_BINFMT_ASSERT(sh_link < elf->shdr_entries); break; } } if(sh_link == 0xFFFF) return; for(i = 0; i < elf->dynsym_entries; i++) { R_BINFMT_GET_INT(st_name, elf->dynsym[i].st_name, bin->endian); R_BINFMT_GET_INT(link_off, elf->shdr[sh_link].sh_offset, bin->endian); R_BINFMT_ASSERT(r_utils_add32(NULL, link_off, st_name) && link_off + st_name <= bin->mapped_size); sym = r_binfmt_sym_new(); sym->name = r_binfmt_elf32_get_name(bin, elf, sh_link, st_name); sym->addr = elf->dynsym[i].st_value; r_utils_arraylist_push(&bin->syms, sym); } }
static int r_binfmt_pe_check(r_binfmt_s *bin) { IMAGE_DOS_HEADER *dos; IMAGE_COFF_HEADER *coff; IMAGE_SECTION_HEADER *shdr; DWORD addr_optional, addr_sections, numberOfRvaAndSizes; WORD arch; size_t size_optional; u32 tmp, i; /********************/ /* Check DOS header */ /********************/ if(bin->mapped_size < sizeof(*dos)) return 0; dos = (IMAGE_DOS_HEADER*)(bin->mapped); /*********************/ /* Check COFF header */ /*********************/ if(bin->mapped_size < (DWORD)dos->e_lfanew) return 0; /* COFF+magic+arch */ if(!r_utils_add32(&tmp, 8+sizeof(*coff), dos->e_lfanew)) return 0; if(bin->mapped_size < tmp) return 0; coff = pe_get_coff(bin); /**************************/ /* Check optionnal header */ /**************************/ arch = pe_get_arch(bin); switch(arch) { case PE32: size_optional = sizeof(IMAGE_OPTIONAL_HEADER_32); break; case PE64: size_optional = sizeof(IMAGE_OPTIONAL_HEADER_64); break; default: return 0; } if(!r_utils_add32(&tmp, 4+sizeof(*coff)+dos->e_lfanew, size_optional)) return 0; if(bin->mapped_size < tmp) return 0; addr_optional = pe_get_addr_coff(bin) + sizeof(*coff); /******************/ /* Check sections */ /******************/ switch(arch) { case PE32: numberOfRvaAndSizes = ((IMAGE_OPTIONAL_HEADER_32*)(bin->mapped + addr_optional))->NumberOfRvaAndSizes; break; case PE64: numberOfRvaAndSizes = ((IMAGE_OPTIONAL_HEADER_32*)(bin->mapped + addr_optional))->NumberOfRvaAndSizes; break; default: return 0; } if(!r_utils_mul32(&addr_sections, numberOfRvaAndSizes, sizeof(IMAGE_DATA_DIRECTORY))) return 0; if(bin->mapped_size < addr_sections) return 0; if(!r_utils_mul32(&tmp, sizeof(IMAGE_SECTION_HEADER), coff->NumberOfSections)) return 0; if(!r_utils_add32(&tmp, tmp, addr_sections)) return 0; if(bin->mapped_size < tmp) return 0; shdr = (IMAGE_SECTION_HEADER*)(bin->mapped + pe_get_addr_sections(bin)); for(i = 0; i < coff->NumberOfSections; i++) { if(!r_utils_add32(&tmp, shdr[i].PointerToRawData, shdr[i].SizeOfRawData)) return 0; if(bin->mapped_size < tmp) return 0; } return 1; }