int main(int argc, char *argv[]) { size_t filesize; FILE *infile; uint64_t first_asm; int bin_type = 0; int arch_type = 0; int c; /* Parse args */ while ((c = getopt(argc, argv, "b:m:v")) != -1) { switch(c) { case 'b': if( strcmp(optarg, "elf") == 0 ) { bin_type = BINARY_ELF; } else if ( strcmp(optarg, "raw") == 0 ) { bin_type = BINARY_RAW; } else { abort(); } break; case 'm': if( strcmp(optarg, "x86-64") == 0) { arch_type = ARCH_IA64; } else if( strcmp(optarg, "x86") == 0) { arch_type = ARCH_IA32; } break; case 'v': verbose = 1; break; default: abort(); break; } } if( optind < argc) { infile = fopen(argv[optind], "rb"); } else { printf("Error: No input file\n"); abort(); } fseek(infile, 0, SEEK_END); filesize = ftell(infile); rewind(infile); if( bin_type == BINARY_ELF || bin_type == 0) { struct elf_header eheader = getElfHeader(infile); struct elf64 eheader64 = getElfHeader64(infile); first_asm = eheader64.header_size + (eheader64.entry_size_program * eheader64.num_entries_program); // The first assembly instruction } else if( bin_type == BINARY_RAW ) { first_asm = 0x0; } if(verbose) printf("asm start: %lx\n", first_asm); char *ch = malloc(sizeof(char)); uint16_t u16; uint32_t u32; uint64_t u64; if( arch_type == ARCH_IA64 || arch_type == 0) { //disasm(first_asm, infile); ia64_disasm(first_asm, first_asm+1000, infile); } else if( arch_type == ARCH_IA32) { printf("Arch x86 is not supported\n"); abort(); } fclose(infile); printf("\n"); return 0; }
bool ElfProgram::validateHeader() { //Validate ELF header //Note: this code assumes a little endian elf and a little endian ARM CPU if(size<sizeof(Elf32_Ehdr)) return false; const Elf32_Ehdr *ehdr=getElfHeader(); static const char magic[EI_NIDENT]={0x7f,'E','L','F',1,1,1}; if(memcmp(ehdr->e_ident,magic,EI_NIDENT)) throw runtime_error("Unrecognized format"); if(ehdr->e_type!=ET_EXEC) throw runtime_error("Not an executable"); if(ehdr->e_machine!=EM_ARM) throw runtime_error("Wrong CPU arch"); if(ehdr->e_version!=EV_CURRENT) return false; if(ehdr->e_entry>=size) return false; if(ehdr->e_phoff>=size-sizeof(Elf32_Phdr)) return false; if(ehdr->e_flags!=(EF_ARM_EABI_MASK | EF_HAS_ENTRY_POINT)) return false; if(ehdr->e_ehsize!=sizeof(Elf32_Ehdr)) return false; if(ehdr->e_phentsize!=sizeof(Elf32_Phdr)) return false; //This to avoid that the next condition could pass due to 32bit wraparound //20 is an arbitrary number, could be increased if required if(ehdr->e_phnum>20) throw runtime_error("Too many segments"); if(ehdr->e_phoff+(ehdr->e_phnum*sizeof(Elf32_Phdr))>size) return false; //Validate program header table bool codeSegmentPresent=false; bool dataSegmentPresent=false; bool dynamicSegmentPresent=false; int dataSegmentSize=0; const Elf32_Phdr *phdr=getProgramHeaderTable(); for(int i=0;i<getNumOfProgramHeaderEntries();i++,phdr++) { //The third condition does not imply the other due to 32bit wraparound if(phdr->p_offset>=size) return false; if(phdr->p_filesz>=size) return false; if(phdr->p_offset+phdr->p_filesz>size) return false; if(phdr->p_align>8) throw runtime_error("Segment alignment too strict"); switch(phdr->p_type) { case PT_LOAD: if(phdr->p_flags & ~(PF_R | PF_W | PF_X)) return false; if(!(phdr->p_flags & PF_R)) return false; if((phdr->p_flags & PF_W) && (phdr->p_flags & PF_X)) throw runtime_error("File violates W^X"); if(phdr->p_flags & PF_X) { if(codeSegmentPresent) return false; //Can't apper twice codeSegmentPresent=true; if(ehdr->e_entry<phdr->p_offset || ehdr->e_entry>phdr->p_offset+phdr->p_filesz || phdr->p_filesz!=phdr->p_memsz) return false; } if((phdr->p_flags & PF_W) && !(phdr->p_flags & PF_X)) { if(dataSegmentPresent) return false; //Two data segments? dataSegmentPresent=true; if(phdr->p_memsz<phdr->p_filesz) return false; unsigned int maxSize=MAX_PROCESS_IMAGE_SIZE- MIN_PROCESS_STACK_SIZE; if(phdr->p_memsz>=maxSize) throw runtime_error("Data segment too big"); dataSegmentSize=phdr->p_memsz; } break; case PT_DYNAMIC: if(dynamicSegmentPresent) return false; //Two dynamic segments? dynamicSegmentPresent=true; //DYNAMIC segment *must* come after data segment if(dataSegmentPresent==false) return false; if(validateDynamicSegment(phdr,dataSegmentSize)==false) return false; break; default: //Ignoring other segments break; } } if(codeSegmentPresent==false) return false; //Can't not have code segment return true; }