Exemplo n.º 1
0
    def load_header(self, hdr_off=None):
        """ Loads ELF header """

        if hdr_off == None:
            hdr_off = 0

        # eident can be loaded even if self.prop.arch is not the same
        # as machine or file's value
        e_ident = Eident(prop=self.prop, offset=hdr_off)

        # Now we set the files's value
        self.prop.arch = e_ident.getArch()
        self.prop.endian = e_ident.getEndian()

        self.header = ElfHeader(e_ident)
Exemplo n.º 2
0
    def load_header(self, hdr_off=None):
        """ Loads ELF header """

        if hdr_off == None:
            hdr_off = 0

        # eident can be loaded even if self.prop.arch is not the same 
        # as machine or file's value
        e_ident = Eident(prop=self.prop, offset=hdr_off)

        # Now we set the files's value 
        self.prop.arch = e_ident.getArch()
        self.prop.endian = e_ident.getEndian()

        self.header = ElfHeader(e_ident)
Exemplo n.º 3
0
class Elf( Chunk ):
    """ Elf class """
    def __init__(self, filename, access='r', load=True, backup=False):
        """ Constructor """

        self.access = access

        if self.access == 'w':
            mode = ACCESS_WRITE
        elif self.access == 'r':
            mode = ACCESS_READ
        else:
            mode = None

        size = getsize(filename)

        self.prop = Property(mode, backup, filename, size_src=size)

        self.header = None
        self.sections = []
        self.programs = []

        Chunk.__init__(self, prop=self.prop, load=load, offset=0, size=size)

    def load(self, offset=None, filemap=None):
        """ Loads the ELF file and all specific parts """

        self.load_binary(offset, filemap)
        self.load_header()
        self.load_programs()
        self.load_sections()
        self.load_sections_names()
        self.load_symbols_names()

        # Now, creating the chunks hierarchy
        chunks = self.chunks()
        chunks_sorted = sorted(chunks, key=cmp_to_key(compareChunks))
        orderChunks(chunks_sorted)

    def load_binary(self, filename=None, offset=None, filemap=None):
        """ Loads the ELF file into a memory mapped file """

        if filename == None:
            filename = self.prop.filename

        self.prop.file_src = open(filename, 'r+')
        self.prop.map_src = mmap(self.prop.file_src.fileno(),
                                 0, access=self.prop.mode)

        Chunk.load(self, offset, filemap)

    def load_header(self, hdr_off=None):
        """ Loads ELF header """

        if hdr_off == None:
            hdr_off = 0

        # eident can be loaded even if self.prop.arch is not the same 
        # as machine or file's value
        e_ident = Eident(prop=self.prop, offset=hdr_off)

        # Now we set the files's value 
        self.prop.arch = e_ident.getArch()
        self.prop.endian = e_ident.getEndian()

        self.header = ElfHeader(e_ident)

    def load_sections(self, shdr_off=None, num=None, ent_size=None):
        """ Loads ELF sections """

        if shdr_off == None:
            shdr_off = self.header.e_shoff

        # offset should be in file
        if shdr_off >= self.prop.size_src:
            return

        if num == None:
            num = self.header.e_shnum

        if ent_size == None:
            ent_size = self.header.e_shentsize

        if shdr_off == 0 or num <= 0:
            return

        off = shdr_off
        for ndx in range(0, num):
            shdr = SectionHeader(self.prop, off)

            section = Section(shdr)
            self.sections.append(section)

            off += shdr.size

    def load_programs(self, phdr_off=None, num=None, ent_size=None):
        """ Loads ELF programs """

        if phdr_off == None:
            phdr_off = self.header.e_phoff

        if num == None:
            num = self.header.e_phnum

        if ent_size == None:
            ent_size = self.header.e_phentsize

        if phdr_off == 0 or num <= 0:
            return

        off = phdr_off
        for ndx in range(0, num):
            phdr = ProgramHeader(self.prop, off)

            program = Program(phdr)
            self.programs.append(program)

            off += phdr.size

    def load_sections_names(self):
        """ Loads sections names from shstrtab if possible """

        # index should exists in section table
        if self.header.e_shstrndx >= len(self.sections):
            return

        if self.header.e_shstrndx <= 0:
            return

        # Then related section should be strtab type of
        shstrtab = self.sections[self.header.e_shstrndx]
        if shstrtab.header.sh_type != shdr_type['SHT_STRTAB']:
            return

        # Then trying to set a name if possible
        for sec in self.sections:
            sec.name = getNameFromStrTab(sec.header.sh_name, shstrtab.strtab)

    def load_symbols_names(self):
        """ Loads symbols names from symtab if possible """

        # let's proceed through all sections to find symtab or dynsym sections
        for sec in self.sections:
            if sec.header.sh_type != shdr_type['SHT_SYMTAB']:
                if sec.header.sh_type != shdr_type['SHT_DYNSYM']:
                    continue

            # if so: sh_link should point on an existing section
            # which should own strtab type of
            if sec.header.sh_link >= len(self.sections):
                continue

            s_strtab = self.sections[sec.header.sh_link]
            if s_strtab.header.sh_type != shdr_type['SHT_STRTAB']:
                continue

            # for each symbol entry then: a name should be found in strtab
            # or then for symbol entry describing section it should be 
            # set to related section's name.
            for s_entry in sec.symtab:
                s_entry.name = getNameFromStrTab(s_entry.st_name,
                                                 s_strtab.strtab)
                if s_entry.name == 'null':
                    if s_entry.st_type == symtab_type['STT_SECTION']:
                        s_entry.name = self.sections[s_entry.st_shndx].name

    def insert(self, chunk):
        """ Insert a new chunk """

        chunks = self.chunks()

        chunk.inserted = True
        chunks.append(chunk)

        chunks_sorted = sorted(chunks, cmp=compareChunks)
        orderChunks(chunks_sorted)

    def recompute(self, branch = None, move = 0, end = 0):
        """ Recompute all chunck offsets and ordering after changes """

        if branch == None:
            branch = self
        else:
            if branch.suppressed == True and (
                    branch.inside == self or branch.inside.suppressed == True):
                if len(branch.includes) > 0:
                    move -= branch.includes[0].offset_start - branch.offset_start
                else:
                    move -= branch.size
            else:
                if branch.inside == self and branch.offset_start + move > end:
                    move = -(branch.offset_start - end)

                if isinstance(branch, Program) == False:
                    branch.offset_start += move
                    branch.offset_end += move
                else:
                    move = 0

        if branch.inserted == True:
            move += branch.size
            branch.inserted = False

        includes = []
        includes.extend(branch.includes)

        for sub_b in includes:
            (move, end, b_incs) = self.recompute(sub_b, move, end)

            if len(b_incs) > 0:
                idx = branch.includes.index(sub_b) + 1
                for b_inc in b_incs:
                    branch.includes.insert(idx, b_inc)
                    idx += 1

            if sub_b.suppressed == True:
                branch.del_include(sub_b)

        ret_includes = []
        if branch.suppressed == True:
            ret_includes = branch.includes
        elif branch != self and end < branch.offset_end:
            end = branch.offset_end
        elif branch == self:
            branch.offset_end = end

        return (move, end, ret_includes)

    def count(self):
        """ Returns the current count of chunks this file is made of """

        return self.counter.count

    def chunks(self):
        """ Returns the list of all chunks including the current Elf instance """

        chunk_lst = [self]

        chunk_lst.extend(self.header.chunks())

        for chunk in self.sections:
            chunk_lst.extend(chunk.chunks())

        for chunk in self.programs:
            chunk_lst.extend(chunk.chunks())

        return chunk_lst

    def write(self):
        """ Writes the current ELF map into a file """

        filename = self.prop.filename
        if self.prop.backup:
            filename = self.prop.filename+'_mod'

        f_dst = open(filename, 'wb')
        f_dst.write('\0'*PAGESIZE)
        f_dst.close()
        self.prop.file_dst = open(filename, 'r+')
        self.prop.map_dst = mmap(self.prop.file_dst.fileno(),
                                 0, access=self.prop.mode)
        self.prop.map_dst.resize(self.size)

        ret_size = Chunk.write(self, self.prop.map_dst)

        self.prop.map_dst.close()
        self.prop.map_dst = None
        self.prop.file_dst.close()
        self.prop.file_dst = None

        return ret_size

    def finalize(self):
        """ Close map before deleting the object """

        if self.prop.map_dst != None:
            self.prop.map_dst.close()
            self.prop.file_dst.close()

        self.prop.map_src.close()
        self.prop.file_src.close()

        Chunk.finalize(self)
Exemplo n.º 4
0
class Elf(Chunk):
    """ Elf class """
    def __init__(self, filename, access='r', load=True, backup=False):
        """ Constructor """

        self.access = access

        if self.access == 'w':
            mode = ACCESS_WRITE
        elif self.access == 'r':
            mode = ACCESS_READ
        else:
            mode = None

        size = getsize(filename)

        self.prop = Property(mode, backup, filename, size_src=size)

        self.header = None
        self.sections = []
        self.programs = []

        Chunk.__init__(self, prop=self.prop, load=load, offset=0, size=size)

    def load(self, offset=None, filemap=None):
        """ Loads the ELF file and all specific parts """

        self.load_binary(offset, filemap)
        self.load_header()
        self.load_programs()
        self.load_sections()
        self.load_sections_names()
        self.load_symbols_names()

        # Now, creating the chunks hierarchy
        chunks = self.chunks()
        chunks_sorted = sorted(chunks, key=cmp_to_key(compareChunks))
        orderChunks(chunks_sorted)

    def load_binary(self, filename=None, offset=None, filemap=None):
        """ Loads the ELF file into a memory mapped file """

        if filename == None:
            filename = self.prop.filename

        self.prop.file_src = open(filename, 'r+')
        self.prop.map_src = mmap(self.prop.file_src.fileno(),
                                 0,
                                 access=self.prop.mode)

        Chunk.load(self, offset, filemap)

    def load_header(self, hdr_off=None):
        """ Loads ELF header """

        if hdr_off == None:
            hdr_off = 0

        # eident can be loaded even if self.prop.arch is not the same
        # as machine or file's value
        e_ident = Eident(prop=self.prop, offset=hdr_off)

        # Now we set the files's value
        self.prop.arch = e_ident.getArch()
        self.prop.endian = e_ident.getEndian()

        self.header = ElfHeader(e_ident)

    def load_sections(self, shdr_off=None, num=None, ent_size=None):
        """ Loads ELF sections """

        if shdr_off == None:
            shdr_off = self.header.e_shoff

        # offset should be in file
        if shdr_off >= self.prop.size_src:
            return

        if num == None:
            num = self.header.e_shnum

        if ent_size == None:
            ent_size = self.header.e_shentsize

        if shdr_off == 0 or num <= 0:
            return

        off = shdr_off
        for ndx in range(0, num):
            shdr = SectionHeader(self.prop, off)

            section = Section(shdr)
            self.sections.append(section)

            off += shdr.size

    def load_programs(self, phdr_off=None, num=None, ent_size=None):
        """ Loads ELF programs """

        if phdr_off == None:
            phdr_off = self.header.e_phoff

        if num == None:
            num = self.header.e_phnum

        if ent_size == None:
            ent_size = self.header.e_phentsize

        if phdr_off == 0 or num <= 0:
            return

        off = phdr_off
        for ndx in range(0, num):
            phdr = ProgramHeader(self.prop, off)

            program = Program(phdr)
            self.programs.append(program)

            off += phdr.size

    def load_sections_names(self):
        """ Loads sections names from shstrtab if possible """

        # index should exists in section table
        if self.header.e_shstrndx >= len(self.sections):
            return

        if self.header.e_shstrndx <= 0:
            return

        # Then related section should be strtab type of
        shstrtab = self.sections[self.header.e_shstrndx]
        if shstrtab.header.sh_type != shdr_type['SHT_STRTAB']:
            return

        # Then trying to set a name if possible
        for sec in self.sections:
            sec.name = getNameFromStrTab(sec.header.sh_name, shstrtab.strtab)

    def load_symbols_names(self):
        """ Loads symbols names from symtab if possible """

        # let's proceed through all sections to find symtab or dynsym sections
        for sec in self.sections:
            if sec.header.sh_type != shdr_type['SHT_SYMTAB']:
                if sec.header.sh_type != shdr_type['SHT_DYNSYM']:
                    continue

            # if so: sh_link should point on an existing section
            # which should own strtab type of
            if sec.header.sh_link >= len(self.sections):
                continue

            s_strtab = self.sections[sec.header.sh_link]
            if s_strtab.header.sh_type != shdr_type['SHT_STRTAB']:
                continue

            # for each symbol entry then: a name should be found in strtab
            # or then for symbol entry describing section it should be
            # set to related section's name.
            for s_entry in sec.symtab:
                s_entry.name = getNameFromStrTab(s_entry.st_name,
                                                 s_strtab.strtab)
                if s_entry.name == 'null':
                    if s_entry.st_type == symtab_type['STT_SECTION']:
                        s_entry.name = self.sections[s_entry.st_shndx].name

    def insert(self, chunk):
        """ Insert a new chunk """

        chunks = self.chunks()

        chunk.inserted = True
        chunks.append(chunk)

        chunks_sorted = sorted(chunks, cmp=compareChunks)
        orderChunks(chunks_sorted)

    def recompute(self, branch=None, move=0, end=0):
        """ Recompute all chunck offsets and ordering after changes """

        if branch == None:
            branch = self
        else:
            if branch.suppressed == True and (
                    branch.inside == self or branch.inside.suppressed == True):
                if len(branch.includes) > 0:
                    move -= branch.includes[
                        0].offset_start - branch.offset_start
                else:
                    move -= branch.size
            else:
                if branch.inside == self and branch.offset_start + move > end:
                    move = -(branch.offset_start - end)

                if isinstance(branch, Program) == False:
                    branch.offset_start += move
                    branch.offset_end += move
                else:
                    move = 0

        if branch.inserted == True:
            move += branch.size
            branch.inserted = False

        includes = []
        includes.extend(branch.includes)

        for sub_b in includes:
            (move, end, b_incs) = self.recompute(sub_b, move, end)

            if len(b_incs) > 0:
                idx = branch.includes.index(sub_b) + 1
                for b_inc in b_incs:
                    branch.includes.insert(idx, b_inc)
                    idx += 1

            if sub_b.suppressed == True:
                branch.del_include(sub_b)

        ret_includes = []
        if branch.suppressed == True:
            ret_includes = branch.includes
        elif branch != self and end < branch.offset_end:
            end = branch.offset_end
        elif branch == self:
            branch.offset_end = end

        return (move, end, ret_includes)

    def count(self):
        """ Returns the current count of chunks this file is made of """

        return self.counter.count

    def chunks(self):
        """ Returns the list of all chunks including the current Elf instance """

        chunk_lst = [self]

        chunk_lst.extend(self.header.chunks())

        for chunk in self.sections:
            chunk_lst.extend(chunk.chunks())

        for chunk in self.programs:
            chunk_lst.extend(chunk.chunks())

        return chunk_lst

    def write(self):
        """ Writes the current ELF map into a file """

        filename = self.prop.filename
        if self.prop.backup:
            filename = self.prop.filename + '_mod'

        f_dst = open(filename, 'wb')
        f_dst.write('\0' * PAGESIZE)
        f_dst.close()
        self.prop.file_dst = open(filename, 'r+')
        self.prop.map_dst = mmap(self.prop.file_dst.fileno(),
                                 0,
                                 access=self.prop.mode)
        self.prop.map_dst.resize(self.size)

        ret_size = Chunk.write(self, self.prop.map_dst)

        self.prop.map_dst.close()
        self.prop.map_dst = None
        self.prop.file_dst.close()
        self.prop.file_dst = None

        return ret_size

    def finalize(self):
        """ Close map before deleting the object """

        if self.prop.map_dst != None:
            self.prop.map_dst.close()
            self.prop.file_dst.close()

        self.prop.map_src.close()
        self.prop.file_src.close()

        Chunk.finalize(self)