def get_elf_entry_point_offset(path):
    physical_ep = None
    try:
        with open(path, "rb") as f:
            elf = ELFFile(f)
            physical_ep = elf._parse_elf_header().e_entry
            physical_ep -= elf.get_segment(0).header.p_vaddr
    except Exception as e:
        logger.error(e.__str__())
        physical_ep = None
    return physical_ep
Exemple #2
0
def get_object_code(file_name):
    with open(file_name, "rb") as f:
        if is_elf(file_name):
            file = ELFFile(f)

            is_32 = file.elfclass == 32

            entry_point = file._parse_elf_header().e_entry
            segment_load_address = get_elf_segment_load_address(file)
            entry_offset = entry_point - segment_load_address
            print(f"entry_point: {hex(entry_point)}", file=sys.stderr)
            print(f"segment_load_address: {hex(segment_load_address)}",
                  file=sys.stderr)
            print(f"entry_offset: {hex(entry_offset)}", file=sys.stderr)

            f.seek(entry_offset)
            buf = f.read()
        elif is_pe(file_name):
            file = pefile.PE(file_name)

            is_32 = file.OPTIONAL_HEADER.Magic == 0x10B or hasattr(
                file.OPTIONAL_HEADER, "BaseOfData")

            base_address = file.OPTIONAL_HEADER.ImageBase
            entry_point = file.OPTIONAL_HEADER.AddressOfEntryPoint
            entry_va = entry_point + file.OPTIONAL_HEADER.ImageBase
            print(f"base_address: {hex(base_address)}", file=sys.stderr)
            print(f"entry_point: {hex(entry_point)}", file=sys.stderr)
            print(f"entry_point (virtual address): {hex(entry_va)}",
                  file=sys.stderr)

            text_section = get_pe_text_section(file)
            virtual_address = text_section.VirtualAddress
            raw_offset = text_section.PointerToRawData
            entry_offset = entry_point - virtual_address + raw_offset
            print(f"virtual_address: {hex(virtual_address)}", file=sys.stderr)
            print(f"raw_offset: {hex(raw_offset)}", file=sys.stderr)
            print(
                f"entry_point (file offset): {hex(entry_offset)}",
                file=sys.stderr,
            )

            f.seek(entry_offset)
            raw_size = text_section.SizeOfRawData
            buf = f.read(raw_size)
        else:
            raise RuntimeError("Unsupported file format.")

    return buf, entry_point, is_32
Exemple #3
0
class ELFParser:
    """  Class to help ELF parsing """
    def __init__(self, filename):
        self.fn = filename
        self.f = open(self.fn, 'rb')
        self.bin = self.f.read()
        self.elf = ELFFile(self.f)

        self.struct_elf = {
            'e_type': "Object File Type",
            'e_machine': "Architecture",
            'e_entry': "Entry Point VA",
            'e_phoff': "Program header table file offset",
            'e_shoff': "Section header table file offset",
            'e_ehsize': "ELF header size in bytes",
            'e_phentsize': "Program header table entry size",
            'e_phnum': "Program header table entry count",
            'e_shentsize': "Section header table entry size",
            'e_shnum': "Section header table entry count",
            'e_shstrndx': "Section header string table index"
        }

        self.struct_section = {
            'sh_type': "Section Type",
            'sh_addralign': "Section Address Align",
            'sh_offset': "Section Offset",
            'sh_entsize': "Section Entry Size",
            'sh_name': "Section Name",
            'sh_flags': "Section Flags",
            'sh_size': "Section Size",
            'sh_addr': "Section VA",
            'sh_link': "Section Link",
            'sh_info': "Section Info"
        }

        # Relocation Types: Value, Name, Field and Calculation from linux64-ABI
        self.struct_relocation = {
            0: "R_X86_64_NONE",  # none, none
            1: "R_X86_64_64",  # word64, S + A
            2: "R_X86_64_PC32",  # word32, S + A - P
            3: "R_X86_64_GOT32",  # word32, G + A
            4: "R_X86_64_PLT32",  # word32, L + A - P
            5: "R_X86_64_COPY",  # none, none
            6: "R_X86_64_GLOB_DAT",  # wordclass, S
            7: "R_X86_64_JUMP_SLOT",  # wordclass, S
            8: "R_X86_64_RELATIVE",  # wordclass, B + A
            9: "R_X86_64_GOTPCREL",  # word32, G + GOT + A - P
            10: "R_X86_64_32",  # word32, S + A
            11: "R_X86_64_32S",  # word32, S + A
            12: "R_X86_64_16",  # word16, S + A
            13: "R_X86_64_PC16",  # word16, S + A - P
            14: "R_X86_64_8",  # word8, S + A
            15: "R_X86_64_PC8",  # word8, S + A - P
            16: "R_X86_64_DTPMOD64",  # word64
            17: "R_X86_64_DTPOFF64",  # word64
            18: "R_X86_64_TPOFF64",  # word64
            19: "R_X86_64_TLSGD",  # word32
            20: "R_X86_64_TLSLD",  # word32
            21: "R_X86_64_DTPOFF32",  # word32
            22: "R_X86_64_GOTTPOFF",  # word32
            23: "R_X86_64_TPOFF32",  # word32
            24: "R_X86_64_PC64",  # word64, S + A - P (only for LP64)
            25: "R_X86_64_GOTOFF64",  # word64, S + A - GOT (only for LP64)
            26: "R_X86_64_GOTPC32",  # word32, GOT + A - P
            32: "R_X86_64_SIZE32",  # word32, Z + A
            33: "R_X86_64_SIZE64",  # word64, Z + A (only for LP64)
            34: "R_X86_64_GOTPC32_TLSDESC",  # word32
            35: "R_X86_64_TLSDESC_CALL",  # none
            36: "R_X86_64_TLSDESC",  # word64 * 2
            37: "R_X86_64_IRELATIVE",  # wordclass, indirect (B + A)
            38:
            "R_X86_64_RELATIVE64"  # word64, B + A (only for ILP32 executable or shared objects)
        }

        self.section_ranges = {}
        self.extractSectionVAs()

    def readElfHdr(self):
        print 'ELF Header (%s)' % self.fn
        elf_info = self.elf._parse_elf_header()

        for i in sorted(self.struct_elf.keys()):
            elf_decr = self.struct_elf[i].ljust(35)
            if isinstance(elf_info[i], int):
                val = '(' + hex(elf_info[i]) + ')'
                print "  %s: %s%s" % (elf_decr, elf_info[i], val.rjust(15))
            else:
                print "  %s: %s" % (elf_decr, elf_info[i])

    def readRelocations(self):
        """
        Read the relocation sections in a given ELF binary
        :return:
        """
        # There are several different sections for relocation:
        # '.rela.plt', '.rela.dyn', '.rel.plt', '.rel.dyn'
        # The postfix .dyn represents the table for dynamic linker
        reloc_section_names = [
            '.rela.plt', '.rela.dyn', '.rel.plt', '.rel.dyn'
        ]

        for reloc_name in reloc_section_names:
            rel = self.elf.get_section_by_name(reloc_name)
            if isinstance(rel, RelocationSection):
                print 'Relocation Section: %s (%d)' % (reloc_name,
                                                       rel.num_relocations())
                # Lookup all entry attributes
                for i, r in enumerate(rel.iter_relocations()):
                    print '\t[%3d] Offset + Addend: %s +' % (
                        i + 1, hex(r['r_offset'])),
                    if 'rela' in reloc_name:
                        print r['r_addend'],
                    print '\tInfo (Type, Symbol): %s (%s, %s)' \
                          % (hex(r['r_info']), self.struct_relocation[r['r_info_type']],r['r_info_sym'])

    def readSections(self):
        """ Read all sections in a given ELF binary """
        def sectionInfo(s):
            section = self.elf.get_section(s)

            # A section type is in its header, but the name was decoded and placed in a public attribute.
            print '  [%2d] Section %s' % (s, section.name)
            for s in sorted(self.struct_section.keys()):
                sec_desc = self.struct_section[s].ljust(25)
                print '\t%s : %s' % (sec_desc, section[s])

            # Case: a section table contains a symbol table section
            if isinstance(section, SymbolTableSection):
                for sym_no in range(section.num_symbols()):
                    symbol = section.get_symbol(sym_no)
                    print "      [%2d] Symbol: %s (Ty=%-7s, Bind=%-6s, Sym_Other=%-7s, Shndx=%4s, Val=0x%x, Sz=0x%x)" % \
                          (sym_no, symbol.name, symbol['st_info']['type'], symbol['st_info']['bind'],
                           symbol['st_other']['visibility'], symbol['st_shndx'], symbol['st_value'], symbol['st_size'])

        sec_cnt = self.elf.num_sections()
        print 'Found %s sections' % sec_cnt
        for s in range(sec_cnt):
            sectionInfo(s)

    def extractSectionVAs(self):
        for s in range(1, self.elf.num_sections()):
            sec = self.elf.get_section(s)
            va = sec['sh_addr']
            if va > 0:
                self.section_ranges[sec.name] = ((va, va + sec['sh_size']))

    def getSectionVA(self, sn):
        return self.section_ranges[sn][0]

    def getSectionByVA(self, va):
        secNames = self.section_ranges.keys()
        for sn in secNames:
            s, e = self.section_ranges[sn]
            if s <= va < e:
                return sn

    def isVAinSection(self, kind, va):
        for s, e in self.section_ranges[kind]:
            if s <= va < e:
                return True

        return False