Beispiel #1
0
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;
}