Beispiel #1
0
    def load_module(self, filename):
        logger.debug("Loading module '%s'." % filename)

        with open(filename, 'rb') as fstream:
            elf = ELFFile(fstream)

            dynamic = elf.header.e_type == 'ET_DYN'

            if not dynamic:
                raise NotImplementedError(
                    "Only ET_DYN is supported at the moment.")

            # Parse program header (Execution view).

            # - LOAD (determinate what parts of the ELF file get mapped into memory)
            load_segments = [
                x for x in elf.iter_segments() if x.header.p_type == 'PT_LOAD'
            ]

            # Find bounds of the load segments.
            bound_low = 0
            bound_high = 0

            for segment in load_segments:
                if segment.header.p_memsz == 0:
                    continue

                if bound_low > segment.header.p_vaddr:
                    bound_low = segment.header.p_vaddr

                high = segment.header.p_vaddr + segment.header.p_memsz

                if bound_high < high:
                    bound_high = high

            # Retrieve a base address for this module.
            load_base = self.emu.memory.mem_reserve(bound_high - bound_low)

            for segment in load_segments:
                prot = get_segment_protection(segment.header.p_flags)
                prot = prot if prot is not 0 else UC_PROT_ALL

                self.emu.memory.mem_map(load_base + segment.header.p_vaddr,
                                        segment.header.p_memsz, prot)
                self.emu.memory.mem_write(load_base + segment.header.p_vaddr,
                                          segment.data())

            rel_section = None
            for section in elf.iter_sections():
                if not isinstance(section, RelocationSection):
                    continue
                rel_section = section
                break

            # Parse section header (Linking view).
            dynsym = elf.get_section_by_name(".dynsym")
            dynstr = elf.get_section_by_name(".dynstr")

            # Find init array.
            init_array_size = 0
            init_array_offset = 0
            init_array = []
            for x in elf.iter_segments():
                if x.header.p_type == "PT_DYNAMIC":
                    for tag in x.iter_tags():
                        if tag.entry.d_tag == "DT_INIT_ARRAYSZ":
                            init_array_size = tag.entry.d_val
                        elif tag.entry.d_tag == "DT_INIT_ARRAY":
                            init_array_offset = tag.entry.d_val

            for _ in range(int(init_array_size / 4)):
                # covert va to file offset
                for seg in load_segments:
                    if seg.header.p_vaddr <= init_array_offset < seg.header.p_vaddr + seg.header.p_memsz:
                        init_array_foffset = init_array_offset - seg.header.p_vaddr + seg.header.p_offset
                fstream.seek(init_array_foffset)
                data = fstream.read(4)
                fun_ptr = struct.unpack('I', data)[0]
                if fun_ptr != 0:
                    # fun_ptr += load_base
                    init_array.append(fun_ptr + load_base)
                    # print ("find init array for :%s %x" % (filename, fun_ptr))
                else:
                    # search in reloc
                    for rel in rel_section.iter_relocations():
                        rel_info_type = rel['r_info_type']
                        rel_addr = rel['r_offset']
                        if rel_info_type == arm.R_ARM_ABS32 and rel_addr == init_array_offset:
                            sym = dynsym.get_symbol(rel['r_info_sym'])
                            sym_value = sym['st_value']
                            init_array.append(load_base + sym_value)
                            # print ("find init array for :%s %x" % (filename, sym_value))
                            break
                init_array_offset += 4

            # Resolve all symbols.
            symbols_resolved = dict()

            for section in elf.iter_sections():
                if not isinstance(section, SymbolTableSection):
                    continue

                itersymbols = section.iter_symbols()
                next(itersymbols)  # Skip first symbol which is always NULL.
                for symbol in itersymbols:
                    symbol_address = self._elf_get_symval(
                        elf, load_base, symbol)
                    if symbol_address is not None:
                        symbols_resolved[symbol.name] = SymbolResolved(
                            symbol_address, symbol)

            # Relocate.
            for section in elf.iter_sections():
                if not isinstance(section, RelocationSection):
                    continue

                for rel in section.iter_relocations():
                    sym = dynsym.get_symbol(rel['r_info_sym'])
                    sym_value = sym['st_value']

                    rel_addr = load_base + rel[
                        'r_offset']  # Location where relocation should happen
                    rel_info_type = rel['r_info_type']

                    # Relocation table for ARM
                    if rel_info_type == arm.R_ARM_ABS32:
                        # Create the new value.
                        value = load_base + sym_value
                        # Write the new value
                        self.emu.mu.mem_write(
                            rel_addr, value.to_bytes(4, byteorder='little'))

                    elif rel_info_type == arm.R_ARM_GLOB_DAT or \
                            rel_info_type == arm.R_ARM_JUMP_SLOT or \
                            rel_info_type == arm.R_AARCH64_GLOB_DAT or \
                            rel_info_type == arm.R_AARCH64_JUMP_SLOT:
                        # Resolve the symbol.
                        if sym.name in symbols_resolved:
                            value = symbols_resolved[sym.name].address

                            # Write the new value
                            self.emu.mu.mem_write(
                                rel_addr, value.to_bytes(4,
                                                         byteorder='little'))
                    elif rel_info_type == arm.R_ARM_RELATIVE or \
                            rel_info_type == arm.R_AARCH64_RELATIVE:
                        if sym_value == 0:
                            # Load address at which it was linked originally.
                            value_orig_bytes = self.emu.mu.mem_read(
                                rel_addr, 4)
                            value_orig = int.from_bytes(value_orig_bytes,
                                                        byteorder='little')

                            # Create the new value
                            value = load_base + value_orig

                            # Write the new value
                            self.emu.mu.mem_write(
                                rel_addr, value.to_bytes(4,
                                                         byteorder='little'))
                        else:
                            raise NotImplementedError()
                    else:
                        logger.error("Unhandled relocation type %i." %
                                     rel_info_type)

            # Store information about loaded module.
            module = Module(filename, load_base, bound_high - bound_low,
                            symbols_resolved, init_array)
            self.modules.append(module)

            return module
Beispiel #2
0
    def load_module(self, filename):
        logger.debug("Loading module '%s'." % filename)

        with open(filename, 'rb') as fstream:
            elf = ELFFile(fstream)

            dynamic = elf.header.e_type == 'ET_DYN'

            if not dynamic:
                raise NotImplementedError(
                    "Only ET_DYN is supported at the moment.")

            # Parse program header (Execution view).

            # - LOAD (determinate what parts of the ELF file get mapped into memory)
            load_segments = [
                x for x in elf.iter_segments() if x.header.p_type == 'PT_LOAD'
            ]

            # Find bounds of the load segments.
            bound_low = 0
            bound_high = 0

            for segment in load_segments:
                if segment.header.p_memsz == 0:
                    continue

                if bound_low > segment.header.p_vaddr:
                    bound_low = segment.header.p_vaddr

                high = segment.header.p_vaddr + segment.header.p_memsz

                if bound_high < high:
                    bound_high = high

            # Retrieve a base address for this module.
            load_base = self.emu.memory.mem_reserve(bound_high - bound_low)

            for segment in load_segments:
                prot = get_segment_protection(segment.header.p_flags)
                prot = prot if prot is not 0 else UC_PROT_ALL

                self.emu.memory.mem_map(load_base + segment.header.p_vaddr,
                                        segment.header.p_memsz, prot)
                self.emu.memory.mem_write(load_base + segment.header.p_vaddr,
                                          segment.data())

            # Parse section header (Linking view).
            dynsym = elf.get_section_by_name(".dynsym")
            dynstr = elf.get_section_by_name(".dynstr")

            # Resolve all symbols.
            symbols_resolved = dict()

            for section in elf.iter_sections():
                if not isinstance(section, SymbolTableSection):
                    continue

                itersymbols = section.iter_symbols()
                next(itersymbols)  # Skip first symbol which is always NULL.
                for symbol in itersymbols:
                    symbol_address = self._elf_get_symval(
                        elf, load_base, symbol)
                    if symbol_address is not None:
                        symbols_resolved[symbol.name] = SymbolResolved(
                            symbol_address, symbol)

            # Relocate.
            for section in elf.iter_sections():
                if not isinstance(section, RelocationSection):
                    continue

                for rel in section.iter_relocations():
                    sym = dynsym.get_symbol(rel['r_info_sym'])
                    sym_value = sym['st_value']

                    rel_addr = load_base + rel[
                        'r_offset']  # Location where relocation should happen
                    rel_info_type = rel['r_info_type']

                    # Relocation table for ARM
                    if rel_info_type == arm.R_ARM_ABS32:
                        # Create the new value.
                        value = load_base + sym_value

                        # Write the new value
                        self.emu.mu.mem_write(
                            rel_addr, value.to_bytes(4, byteorder='little'))
                    elif rel_info_type == arm.R_ARM_GLOB_DAT or rel_info_type == arm.R_ARM_JUMP_SLOT:
                        # Resolve the symbol.
                        if sym.name in symbols_resolved:
                            value = symbols_resolved[sym.name].address

                            # Write the new value
                            self.emu.mu.mem_write(
                                rel_addr, value.to_bytes(4,
                                                         byteorder='little'))
                    elif rel_info_type == arm.R_ARM_RELATIVE:
                        if sym_value == 0:
                            # Load address at which it was linked originally.
                            value_orig_bytes = self.emu.mu.mem_read(
                                rel_addr, 4)
                            value_orig = int.from_bytes(value_orig_bytes,
                                                        byteorder='little')

                            # Create the new value
                            value = load_base + value_orig

                            # Write the new value
                            self.emu.mu.mem_write(
                                rel_addr, value.to_bytes(4,
                                                         byteorder='little'))
                        else:
                            raise NotImplementedError()
                    else:
                        logger.error("Unhandled relocation type %i." %
                                     rel_info_type)

            # Store information about loaded module.
            module = Module(filename, load_base, bound_high - bound_low,
                            symbols_resolved)
            self.modules.append(module)
            return module
Beispiel #3
0
    # for x in elffile.iter_segments():
    #     # print(x.header.p_type)
    #     if x.header.p_type == "PT_DYNAMIC":
    #         print(x.header.p_type)
    #         for tag in x.iter_tags():
    #             print(tag.entry.d_tag)
    #             if tag.entry.d_tag == "DT_INIT_ARRAYSZ":
    #                 init_array_size = tag.entry.d_val
    #                 print(init_array_size)
    #             elif tag.entry.d_tag == "DT_INIT_ARRAY":
    #                 init_array_offset = tag.entry.d_val
    #                 print(init_array_offset)

    for segment in load_segments:
        prot = get_segment_protection(segment.header.p_flags)
        print(prot)
        print(segment.header.p_vaddr)
        print(segment.header.p_memsz)

    rel_section = None
    for section in elffile.iter_sections():
        if not isinstance(section, RelocationSection):
            continue
        rel_section = section
        break

    print(rel_section)

    # Find init array.
    init_array_size = 0