class Section64(IndexedHeader): ENDIAN = None FIELDS = ( NullTerminatedStringField('sectname', '16s'), NullTerminatedStringField('segname', '16s'), HexField('addr', 'Q'), Field('size', 'Q'), Field('offset', 'I'), Field('align', 'I'), Field('reloff', 'I'), Field('nreloc', 'I'), HexField('flags', 'I'), Field('reserved1', 'I'), Field('reserved2', 'I'), Field('reserved3', 'I'), ) NEXT_INDEX = 1 def __init__(self, bytes_=None, **kwargs): self.sectname = None self.segname = None self.addr = None self.size = None self.offset = None self.align = None self.reloff = None self.nreloc = None self.flags = None self.reserved1 = None self.reserved2 = None super(Section64, self).__init__('section_64', bytes_, **kwargs)
def symbol(self, matched_idx): assert 0 <= matched_idx < self.num_matched table_idx = 0 section_desc = '' for mapping in self._filter_mappings: mapping_size = len(mapping) if matched_idx >= mapping_size: matched_idx -= mapping_size table_idx += 1 continue (index, n_strx, n_type, n_sect, n_desc, n_value, symbol_name) = \ self._symbol_tables[table_idx].symbols[mapping[matched_idx]] nlist = Nlist64(index=index, n_strx=n_strx, n_type=n_type, n_sect=n_sect, n_desc=n_desc, n_value=n_value) if nlist.n_sect != 0: this_section = self._sections[nlist.n_sect] section_desc = '%s, %s' % \ (NullTerminatedStringField.get_string(this_section.segname), NullTerminatedStringField.get_string(this_section.sectname)) return nlist, symbol_name, section_desc assert False # should never get here
def __init__(self, seg_name, sect_name, bytes_): self.seg_name = None self.sect_name = None seg_name = NullTerminatedStringField.get_string(seg_name) sect_name = NullTerminatedStringField.get_string(sect_name) super(SectionBlock, self).__init__('Section: %s %s' % (seg_name, sect_name), seg_name=seg_name, sect_name=sect_name) self.parse_bytes(bytes_)
def parse(self, section_desc): section = section_desc.section self.initialize(section.offset, section.size) # Get the segment and section names seg_name = NullTerminatedStringField.get_string(section.segname) sect_name = NullTerminatedStringField.get_string(section.sectname) bytes_ = self.get_bytes() if seg_name == '__TEXT': data_section = TextSection(sect_name, bytes_) elif seg_name == '__DATA': data_section = DataSection(sect_name, bytes_) else: data_section = SectionBlock(seg_name, sect_name, bytes_) # If the section is inside a encrypted region (specificed by LC_ENCRYPTION_INFO), # we cannot parse it because we don't have the decryption key. So, we just # create a block without trying to parse its content. if self.mach_o.is_section_encrypted(section): data_section.name += ' [ENCRYPTED]' self.add_subrange(data_section, section.size) return if section.offset == 0: # .bss and .common sections only exist in VM but not in the file. So, they have an offset of 0 # which aliases with the mach header. We do not add any subrange for these sections since # there is no data to parse / display. # TODO - in some iOS binraries, offset is set to 0 for many sections that should have data # Need to study them more to determine if offset is just not set proerly and we can # compute the offset from the first data section and the VM address. return elif section_desc.is_cstring(): data_section = CstringSection(bytes_) cstring_br = self.add_subrange(data_section, section.size) for (offset, string) in data_section.items(): unescaped_string = Unescape.convert(string) cstring_br.add_subrange(offset, len(string) + 1, data=Cstring(unescaped_string)) elif section_desc.is_objc_methname(): data_section = ObjCMethodNameSection(bytes_) obj_methname_br = self.add_subrange(data_section, section.size) for (offset, string) in data_section.items(): unescaped_string = Unescape.convert(string) obj_methname_br.add_subrange( offset, len(string) + 1, data=ObjCMethodName(unescaped_string)) else: self.add_subrange(data_section, section.size)
class SegmentCommand(LoadCommandHeader): ENDIAN = None FIELDS = ( MagicField('cmd', 'I', {LoadCommandCommand.COMMANDS['LC_SEGMENT']: 'LC_SEGMENT'}), Field('cmdsize', 'I'), NullTerminatedStringField('segname', '16s'), HexField('vmaddr', 'I'), Field('vmsize', 'I'), Field('fileoff', 'I'), Field('filesize', 'I'), Field('maxprot', 'I'), Field('initprot', 'I'), Field('nsects', 'I'), HexField('flags', 'I'), ) def __init__(self, bytes_=None, **kwargs): self.segname = None self.vmaddr = None self.vmsize = None self.fileoff = None self.filesize = None self.maxprot = None self.initprot = None self.nsects = None self.flags = None super(SegmentCommand, self).__init__('segment_command', bytes_, **kwargs)
def __init__(self, sect_name, bytes_): sect_name = NullTerminatedStringField.get_string(sect_name) super(TextSection, self).__init__('__TEXT', sect_name, bytes_) self.name = 'TextSection: %s' % sect_name
def __init__(self, sect_name, bytes_): sect_name = NullTerminatedStringField.get_string(sect_name) super(DataSection, self).__init__('__DATA', sect_name, bytes_) self.name = 'DataSection: %s' % sect_name
def __init__(self, seg_name): self.seg_name = None seg_name = NullTerminatedStringField.get_string(seg_name) super(SegmentBlock, self).__init__('Segment: %s' % seg_name, color='cyan', bold=True, seg_name=seg_name)