示例#1
0
    def _find_dt(self, tag):
        """
        Find an entry in the DYNAMIC array.

        Arguments:
            tag(int): Single tag to find

        Returns:
            Pointer to the data described by the specified entry.
        """
        leak = self.leak
        base = self.libbase
        dynamic = self.dynamic
        name = next(k for k, v in ENUM_D_TAG.items() if v == tag)

        Dyn = {32: elf.Elf32_Dyn, 64: elf.Elf64_Dyn}[self.elfclass]

        # Found the _DYNAMIC program header, now find PLTGOT entry in it
        # An entry with a DT_NULL tag marks the end of the DYNAMIC array.
        while not leak.field_compare(dynamic, Dyn.d_tag, constants.DT_NULL):
            if leak.field_compare(dynamic, Dyn.d_tag, tag):
                break
            dynamic += sizeof(Dyn)
        else:
            self.failure("Could not find tag %s" % name)
            return None

        self.status("Found %s at %#x" % (name, dynamic))
        ptr = leak.field(dynamic, Dyn.d_ptr)

        ptr = self._make_absolute_ptr(ptr)

        return ptr
示例#2
0
    def _lookup(self, symb):
        """Performs the actual symbol lookup within one ELF file."""
        leak = self.leak
        Dyn  = {32: elf.Elf32_Dyn, 64: elf.Elf64_Dyn}[self.elfclass]
        name = lambda tag: next(k for k,v in ENUM_D_TAG.items() if v == tag)

        self.status('.gnu.hash/.hash, .strtab and .symtab offsets')

        #
        # We need all three of the hash, string table, and symbol table.
        #
        hshtab  = self._find_dt(constants.DT_GNU_HASH)
        strtab  = self._find_dt(constants.DT_STRTAB)
        symtab  = self._find_dt(constants.DT_SYMTAB)

        # Assume GNU hash will hit, since it is the default for GCC.
        if hshtab:
            hshtype = 'gnu'
        else:
            hshtab  = self._find_dt(constants.DT_HASH)
            hshtype = 'sysv'

        if not all([strtab, symtab, hshtab]):
            self.failure("Could not find all tables")

        strtab = self._make_absolute_ptr(strtab)
        symtab = self._make_absolute_ptr(symtab)
        hshtab = self._make_absolute_ptr(hshtab)

        #
        # Perform the hash lookup
        #
        routine = {'sysv': self._resolve_symbol_sysv,
                   'gnu':  self._resolve_symbol_gnu}[hshtype]
        return routine(self.libbase, symb, hshtab, strtab, symtab)
示例#3
0
    def _find_dt(self, tag):
        """
        Find an entry in the DYNAMIC array.

        Arguments:
            tag(int): Single tag to find

        Returns:
            Pointer to the data described by the specified entry.
        """
        leak    = self.leak
        base    = self.libbase
        dynamic = self.dynamic
        name    = next(k for k,v in ENUM_D_TAG.items() if v == tag)

        Dyn = {32: elf.Elf32_Dyn,    64: elf.Elf64_Dyn}     [self.elfclass]

        # Found the _DYNAMIC program header, now find PLTGOT entry in it
        # An entry with a DT_NULL tag marks the end of the DYNAMIC array.
        while not leak.field_compare(dynamic, Dyn.d_tag, constants.DT_NULL):
            if leak.field_compare(dynamic, Dyn.d_tag, tag):
                break
            dynamic += sizeof(Dyn)
        else:
            self.failure("Could not find tag %s" % name)
            return None

        self.status("Found %s at %#x" % (name, dynamic))
        ptr = leak.field(dynamic, Dyn.d_ptr)

        # Sometimes this is an offset rather than an actual pointer.
        if 0 < ptr < 0x400000:
            ptr += self.libbase

        return ptr
示例#4
0
    def _lookup(self, symb):
        """Performs the actual symbol lookup within one ELF file."""
        leak = self.leak
        Dyn  = {32: elf.Elf32_Dyn, 64: elf.Elf64_Dyn}[self.elfclass]
        name = lambda tag: next(k for k,v in ENUM_D_TAG.items() if v == tag)

        self.status('.gnu.hash/.hash, .strtab and .symtab offsets')

        #
        # We need all three of the hash, string table, and symbol table.
        #
        hshtab  = self._find_dt(constants.DT_GNU_HASH)
        strtab  = self._find_dt(constants.DT_STRTAB)
        symtab  = self._find_dt(constants.DT_SYMTAB)

        # Assume GNU hash will hit, since it is the default for GCC.
        if hshtab:
            hshtype = 'gnu'
        else:
            hshtab  = self._find_dt(constants.DT_HASH)
            hshtype = 'sysv'

        if not all([strtab, symtab, hshtab]):
            self.failure("Could not find all tables")

        strtab = self._make_absolute_ptr(strtab)
        symtab = self._make_absolute_ptr(symtab)
        hshtab = self._make_absolute_ptr(hshtab)

        #
        # Perform the hash lookup
        #
        routine = {'sysv': self._resolve_symbol_sysv,
                   'gnu':  self._resolve_symbol_gnu}[hshtype]
        return routine(self.libbase, symb, hshtab, strtab, symtab)
示例#5
0
文件: static.py 项目: ptcNOP/cuckoo
 def _get_dynamic_tags(self):
     dynamic_tags = []
     for section in self.elf.iter_sections():
         if not isinstance(section, DynamicSection):
             continue
         for tag in section.iter_tags():
             dynamic_tags.append({
                 "tag": self._print_addr(
                     ENUM_D_TAG.get(tag.entry.d_tag, tag.entry.d_tag)
                 ),
                 "type": tag.entry.d_tag[3:],
                 "value": self._parse_tag(tag),
             })
     return dynamic_tags
示例#6
0
    def _get_dynamic_tags(self) -> List[Dict[str, str]]:
        dynamic_tags = []
        for section in self.elf.iter_sections():
            if not isinstance(section, DynamicSection):
                continue
            dynamic_tags.extend(
                {
                    "tag": self._print_addr(ENUM_D_TAG.get(tag.entry.d_tag, tag.entry.d_tag)),
                    "type": str(tag.entry.d_tag)[3:],
                    "value": self._parse_tag(tag),
                }
                for tag in section.iter_tags()
            )

        return dynamic_tags
示例#7
0
    def display_dynamic_tags(self):
        """ Display the dynamic tags contained in the file
        """
        has_dynamic_sections = False
        for section in self.elffile.iter_sections():
            if not isinstance(section, DynamicSection):
                continue

            has_dynamic_sections = True
            self._emitline("\nDynamic section at offset %s contains %s entries:" % (
                self._format_hex(section['sh_offset']),
                section.num_tags()))
            self._emitline("  Tag        Type                         Name/Value")

            padding = 20 + (8 if self.elffile.elfclass == 32 else 0)
            for tag in section.iter_tags():
                if tag.entry.d_tag == 'DT_NEEDED':
                    parsed = 'Shared library: [%s]' % bytes2str(tag.needed)
                elif tag.entry.d_tag == 'DT_RPATH':
                    parsed = 'Library rpath: [%s]' % bytes2str(tag.rpath)
                elif tag.entry.d_tag == 'DT_RUNPATH':
                    parsed = 'Library runpath: [%s]' % bytes2str(tag.runpath)
                elif tag.entry.d_tag == 'DT_SONAME':
                    parsed = 'Library soname: [%s]' % bytes2str(tag.soname)
                elif (tag.entry.d_tag.endswith('SZ') or
                      tag.entry.d_tag.endswith('ENT')):
                    parsed = '%i (bytes)' % tag['d_val']
                elif (tag.entry.d_tag.endswith('NUM') or
                      tag.entry.d_tag.endswith('COUNT')):
                    parsed = '%i' % tag['d_val']
                elif tag.entry.d_tag == 'DT_PLTREL':
                    s = describe_dyn_tag(tag.entry.d_val)
                    if s.startswith('DT_'):
                        s = s[3:]
                    parsed = '%s' % s
                else:
                    parsed = '%#x' % tag['d_val']

                self._emitline(" %s %-*s %s" % (
                    self._format_hex(ENUM_D_TAG.get(tag.entry.d_tag, tag.entry.d_tag),
                        fullhex=True, lead0x=True),
                    padding,
                    '(%s)' % (tag.entry.d_tag[3:],),
                    parsed))
        if not has_dynamic_sections:
            # readelf only prints this if there is at least one segment
            if self.elffile.num_segments():
                self._emitline("\nThere is no dynamic section in this file.")
示例#8
0
 def _get_dynamic_tags(self):
     dynamic_tags = []
     for section in self.elf.iter_sections():
         if not isinstance(section, DynamicSection):
             continue
         for tag in section.iter_tags():
             dynamic_tags.append({
                 "tag":
                 self._print_addr(
                     ENUM_D_TAG.get(tag.entry.d_tag, tag.entry.d_tag)),
                 "type":
                 tag.entry.d_tag[3:],
                 "value":
                 self._parse_tag(tag),
             })
     return dynamic_tags
示例#9
0
    def _find_dt(self, tags):
        """
        Find an entry in the DYNAMIC array.

        Arguments:
            tags(int, tuple): Single tag, or list of tags to search for

        Returns:
            Pointer to the data described by the specified entry.
        """
        if not isinstance(tags, (list, tuple)):
            tags = [tags]

        leak    = self.leak
        base    = self.libbase
        dynamic = self.dynamic
        name    = lambda tag: next(k for k,v in ENUM_D_TAG.items() if v == tag)

        Dyn = {32: elf.Elf32_Dyn,    64: elf.Elf64_Dyn}     [self.elfclass]

        # Found the _DYNAMIC program header, now find PLTGOT entry in it
        # An entry with a DT_NULL tag marks the end of the DYNAMIC array.
        while True:
            d_tag = leak.field(dynamic, Dyn.d_tag)

            if d_tag == constants.DT_NULL:
                return None
            elif d_tag in tags:
                break

            #Skip to next
            dynamic += sizeof(Dyn)
        else:
            self.failure("Could not find any of: " % map(name, tags))
            return None

        self.status("Found %s at %#x" % (name(d_tag), dynamic))
        ptr = leak.field(dynamic, Dyn.d_ptr)

        # Sometimes this is an offset rather than an actual pointer.
        if 0 < ptr < 0x400000:
            ptr += self.libbase

        return ptr
示例#10
0
    def _find_dt(self, tags):
        """
        Find an entry in the DYNAMIC array.

        Arguments:
            tags(int, tuple): Single tag, or list of tags to search for

        Returns:
            Pointer to the data described by the specified entry.
        """
        if not isinstance(tags, (list, tuple)):
            tags = [tags]

        leak = self.leak
        base = self.libbase
        dynamic = self.dynamic
        name = lambda tag: next(k for k, v in ENUM_D_TAG.items() if v == tag)

        Dyn = {32: elf.Elf32_Dyn, 64: elf.Elf64_Dyn}[self.elfclass]

        # Found the _DYNAMIC program header, now find PLTGOT entry in it
        # An entry with a DT_NULL tag marks the end of the DYNAMIC array.
        while True:
            d_tag = leak.field(dynamic, Dyn.d_tag)

            if d_tag == constants.DT_NULL:
                return None
            elif d_tag in tags:
                break

            #Skip to next
            dynamic += sizeof(Dyn)
        else:
            self.failure("Could not find any of: " % map(name, tags))
            return None

        self.status("Found %s at %#x" % (name(d_tag), dynamic))
        ptr = leak.field(dynamic, Dyn.d_ptr)

        # Sometimes this is an offset rather than an actual pointer.
        if 0 < ptr < 0x400000:
            ptr += self.libbase

        return ptr
示例#11
0
    def _lookup(self, symb):
        """Performs the actual symbol lookup within one ELF file."""
        leak = self.leak
        Dyn = {32: elf.Elf32_Dyn, 64: elf.Elf64_Dyn}[self.elfclass]
        name = lambda tag: next(k for k, v in ENUM_D_TAG.items() if v == tag)

        self.status(".gnu.hash/.hash, .strtab and .symtab offsets")

        #
        # We need all three of the hash, string table, and symbol table.
        #
        hshtab = self._find_dt(constants.DT_GNU_HASH)
        strtab = self._find_dt(constants.DT_STRTAB)
        symtab = self._find_dt(constants.DT_SYMTAB)

        # Assume GNU hash will hit, since it is the default for GCC.
        if hshtab:
            hshtype = "gnu"
        else:
            hshtab = self._find_dt(constants.DT_HASH)
            hshtype = "sysv"

        if not all([strtab, symtab, hshtab]):
            self.failure("Could not find all tables")

        # glibc pointers are relocated but uclibc are not
        if 0 < strtab < 0x400000:
            strtab += self.libbase
            symtab += self.libbase
            hshtab += self.libbase

        #
        # Perform the hash lookup
        #
        routine = {"sysv": self._resolve_symbol_sysv, "gnu": self._resolve_symbol_gnu}[hshtype]
        return routine(self.libbase, symb, hshtab, strtab, symtab)
示例#12
0
    def get_sections(self):
        sections = []
        for nsec, section in enumerate(self._elf.iter_sections()):
            result = {}
            result['nsec'] = nsec
            result['name'] = section.name
            result['sh_type'] = describe_sh_type(section['sh_type'])
            if self._elf.elfclass == 32:
                result['sh_addr'] = section['sh_addr']
                result['shoffset'] = section['sh_offset']
                result['sh_size'] = section['sh_size']
                result['sh_entsize'] = section['sh_entsize']
                result['sh_flags'] = describe_sh_flags(section['sh_flags'])
                result['sh_link'] = section['sh_link']
                result['sh_info'] = section['sh_info']
                result['sh_addralign'] = section['sh_addralign']
            else:  # 64
                result['sh_addr'] = section['sh_addr']
                result['sh_offset'] = section['sh_offset']
                result['sh_size'] = section['sh_size']
                result['sh_entsize'] = section['sh_entsize']
                result['sh_flags'] = describe_sh_flags(section['sh_flags'])
                result['sh_link'] = section['sh_link'], section['sh_info']
                result['sh_addralign'] = section['sh_addralign']

            # Dynamic Section
            if isinstance(section, DynamicSection):
                result['special_type'] = 'dynamic'
                result['dynamic'] = []
                has_dynamic_sections = True
                for tag in section.iter_tags():
                    dynamic = {}
                    if tag.entry.d_tag == 'DT_NEEDED':
                        parsed = 'Shared library: [%s]' % tag.needed
                    elif tag.entry.d_tag == 'DT_RPATH':
                        parsed = 'Library rpath: [%s]' % tag.rpath
                    elif tag.entry.d_tag == 'DT_RUNPATH':
                        parsed = 'Library runpath: [%s]' % tag.runpath
                    elif tag.entry.d_tag == 'DT_SONAME':
                        parsed = 'Library soname: [%s]' % tag.soname
                    elif tag.entry.d_tag.endswith(('SZ', 'ENT')):
                        parsed = '%i (bytes)' % tag['d_val']
                    elif tag.entry.d_tag.endswith(('NUM', 'COUNT')):
                        parsed = '%i' % tag['d_val']
                    elif tag.entry.d_tag == 'DT_PLTREL':
                        s = describe_dyn_tag(tag.entry.d_val)
                        if s.startswith('DT_'):
                            s = s[3:]
                        parsed = '%s' % s
                    else:
                        parsed = '%#x' % tag['d_val']
                        dynamic['tag'] = ENUM_D_TAG.get(
                            tag.entry.d_tag, tag.entry.d_tag)
                        dynamic['tag_type'] = tag.entry.d_tag[3:]
                        dynamic['tag_value'] = parsed
                    result['dynamic'].append(dynamic)

            #Relocation Section
            if isinstance(section, RelocationSection):
                result['special_type'] = 'relocation'
                result['relocation'] = []
                has_relocation_sections = True
                # The symbol table section pointed to in sh_link
                symtable = self._elf.get_section(section['sh_link'])

                for rel in section.iter_relocations():
                    relocation = {}
                    relocation['r_offset'] = rel['r_offset']
                    relocation['r_info'] = rel['r_info']
                    relocation['r_info_type'] = describe_reloc_type(
                        rel['r_info_type'], self._elf)

                    if rel['r_info_sym'] == 0:
                        continue

                    symbol = symtable.get_symbol(rel['r_info_sym'])
                    # Some symbols have zero 'st_name', so instead what's used is
                    # the name of the section they point at
                    if symbol['st_name'] == 0:
                        symsec = self._elf.get_section(symbol['st_shndx'])
                        relocation['symbol_name'] = symbol_name = symsec.name
                    else:
                        symbol_name = symbol.name
                        relocation['st_value'] = symbol['st_value']
                        relocation['symbol_name'] = symbol_name
                    if section.is_RELA():
                        relocation['r_addend'] = rel['r_addend']
                    result['relocation'].append(relocation)

            #Symbol Section
            if isinstance(section, SymbolTableSection):
                self._init_versioninfo()

                if section['sh_entsize'] == 0:
                    continue
                result['special_type'] = 'symbol'
                result['symbol'] = []
                for nsym, symbol in enumerate(section.iter_symbols()):
                    sym_dic = {}
                    version_info = ''
                    # readelf doesn't display version info for Solaris versioning
                    if (section['sh_type'] == 'SHT_DYNSYM'
                            and self._versioninfo['type'] == 'GNU'):
                        version = self._symbol_version(nsym)
                        if (version['name'] != symbol.name and version['index']
                                not in ('VER_NDX_LOCAL', 'VER_NDX_GLOBAL')):
                            if version['filename']:
                                # external symbol
                                version_info = '@%(name)s (%(index)i)' % version
                            else:
                                # internal symbol
                                if version['hidden']:
                                    version_info = '@%(name)s' % version
                                else:
                                    version_info = '@@%(name)s' % version

                        # symbol names are truncated to 25 chars, similarly to readelf
                        sym_dic['nsym'] = nsym
                        sym_dic['st_value'] = symbol['st_value']
                        sym_dic['st_size'] = symbol['st_size']
                        sym_dic['st_type'] = describe_symbol_type(
                            symbol['st_info']['type'])
                        sym_dic['bind'] = describe_symbol_bind(
                            symbol['st_info']['bind'])
                        sym_dic['vis'] = describe_symbol_visibility(
                            symbol['st_other']['visibility'])
                        sym_dic['ndx'] = describe_symbol_shndx(
                            symbol['st_shndx'])
                        sym_dic['name'] = symbol.name
                        sym_dic['version'] = version_info
                        result['symbol'].append(sym_dic)
            sections.append(result)
        return sections