예제 #1
0
    def parse_section(self):
        name = strip(self.f.read(16))
        segname = strip(self.f.read(16))
        addr = get_int(self.f) if self.macho.is_32_bit() else get_ll(self.f)
        size = get_int(self.f) if self.macho.is_32_bit() else get_ll(self.f)
        offset = get_int(self.f)
        align = get_int(self.f)
        reloff = get_int(self.f)
        nreloc = get_int(self.f)
        flags = get_int(self.f)
        self.f.read(8) if self.macho.is_32_bit() else self.f.read(12)

        if self.macho.is_little():
            addr = little(addr, 'I') if self.macho.is_32_bit() \
                else little(addr, 'Q')
            size = little(size, 'I') if self.macho.is_32_bit() \
                else little(size, 'Q')
            offset = little(offset, 'I')
            align = little(align, 'I')
            reloff = little(reloff, 'I')
            nreloc = little(nreloc, 'I')
            flags = little(flags, 'I')

        section = Section(name=name, segname=segname, addr=addr, offset=offset,
                          align=align, reloff=reloff, nreloc=nreloc, size=size)
        self.parse_section_flags(section, flags)

        return section
예제 #2
0
    def parse_section(self):
        name = strip(self.f.read(16))
        segname = strip(self.f.read(16))
        addr = get_int(self.f) if self.macho.is_32_bit() else get_ll(self.f)
        size = get_int(self.f) if self.macho.is_32_bit() else get_ll(self.f)
        offset = get_int(self.f)
        align = get_int(self.f)
        reloff = get_int(self.f)
        nreloc = get_int(self.f)
        flags = get_int(self.f)
        self.f.read(8) if self.macho.is_32_bit() else self.f.read(12)

        if self.macho.is_little():
            addr = little(addr, 'I') if self.macho.is_32_bit() \
                else little(addr, 'Q')
            size = little(size, 'I') if self.macho.is_32_bit() \
                else little(size, 'Q')
            offset = little(offset, 'I')
            align = little(align, 'I')
            reloff = little(reloff, 'I')
            nreloc = little(nreloc, 'I')
            flags = little(flags, 'I')

        section = Section(name=name,
                          segname=segname,
                          addr=addr,
                          offset=offset,
                          align=align,
                          reloff=reloff,
                          nreloc=nreloc,
                          size=size)
        self.parse_section_flags(section, flags)

        return section
예제 #3
0
    def parse_segment(self, lc):
        name = strip(self.f.read(16))
        vmaddr = get_int(self.f) if self.macho.is_32_bit() else get_ll(self.f)
        vmsize = get_int(self.f) if self.macho.is_32_bit() else get_ll(self.f)
        offset = get_int(self.f) if self.macho.is_32_bit() else get_ll(self.f)
        segsize = get_int(self.f) if self.macho.is_32_bit() else get_ll(self.f)
        maxprot = get_int(self.f)
        initprot = get_int(self.f)
        nsects = get_int(self.f)
        flags = get_int(self.f)

        if self.macho.is_little():
            vmaddr = little(vmaddr, 'I') if self.macho.is_32_bit() \
                else little(vmaddr, 'Q')
            vmsize = little(vmsize, 'I') if self.macho.is_32_bit() \
                else little(vmsize, 'Q')
            offset = little(offset, 'I') if self.macho.is_32_bit() \
                else little(offset, 'Q')
            segsize = little(segsize, 'I') if self.macho.is_32_bit() \
                else little(segsize, 'Q')
            maxprot = little(maxprot, 'I')
            initprot = little(initprot, 'I')
            nsects = little(nsects, 'I')
            flags = little(flags, 'I')

        maxprot = dictionary.protections[maxprot & 0b111]
        initprot = dictionary.protections[initprot & 0b111]

        entropy = self.get_segment_entropy(offset, segsize)

        segment = Segment(cmd=lc.cmd,
                          size=lc.size,
                          name=name,
                          vmaddr=vmaddr,
                          vmsize=vmsize,
                          offset=offset,
                          segsize=segsize,
                          maxprot=maxprot,
                          initprot=initprot,
                          nsects=nsects,
                          entropy=entropy)

        if self.macho.is_32_bit():
            sect_size = 68
        else:
            sect_size = 80
        for i in range(segment.nsects):
            if self.f.tell() + sect_size > self.file_size:
                data = {'offset': self.f.tell(), 'file_size': self.file_size}
                a = Abnormality(title='SECTION OUT OF BOUNDS', data=data)
                break
            sect = self.parse_section()
            segment.add_sect(sect)

        self.parse_segment_flags(segment, flags)
        self.macho.add_lc(segment)
예제 #4
0
    def parse_main(self, lc):
        offset = get_ll(self.f)
        size = get_ll(self.f)

        if self.macho.is_little():
            offset = little(offset, 'Q')
            size = little(size, 'Q')

        lc.add_data('offset', offset)
        lc.add_data('size', size)

        self.macho.add_lc(lc)
예제 #5
0
    def parse_main(self, lc):
        offset = get_ll(self.f)
        size = get_ll(self.f)

        if self.macho.is_little():
            offset = little(offset, 'Q')
            size = little(size, 'Q')

        lc.add_data('offset', offset)
        lc.add_data('size', size)

        self.macho.add_lc(lc)
예제 #6
0
    def parse_segment(self, lc):
        name = strip(self.f.read(16))
        vmaddr = get_int(self.f) if self.macho.is_32_bit() else get_ll(self.f)
        vmsize = get_int(self.f) if self.macho.is_32_bit() else get_ll(self.f)
        offset = get_int(self.f) if self.macho.is_32_bit() else get_ll(self.f)
        segsize = get_int(self.f) if self.macho.is_32_bit() else get_ll(self.f)
        maxprot = get_int(self.f)
        initprot = get_int(self.f)
        nsects = get_int(self.f)
        flags = get_int(self.f)

        if self.macho.is_little():
            vmaddr = little(vmaddr, 'I') if self.macho.is_32_bit() \
                else little(vmaddr, 'Q')
            vmsize = little(vmsize, 'I') if self.macho.is_32_bit() \
                else little(vmsize, 'Q')
            offset = little(offset, 'I') if self.macho.is_32_bit() \
                else little(offset, 'Q')
            segsize = little(segsize, 'I') if self.macho.is_32_bit() \
                else little(segsize, 'Q')
            maxprot = little(maxprot, 'I')
            initprot = little(initprot, 'I') 
            nsects = little(nsects, 'I')
            flags = little(flags, 'I')

        maxprot = dictionary.protections[maxprot & 0b111]
        initprot = dictionary.protections[initprot & 0b111]        

        entropy = self.get_segment_entropy(offset, segsize)

        segment = Segment(cmd=lc.cmd, size=lc.size, name=name,
                          vmaddr=vmaddr, vmsize=vmsize, offset=offset,
                          segsize=segsize, maxprot=maxprot, initprot=initprot,
                          nsects=nsects, entropy=entropy)

        if self.macho.is_32_bit():
            sect_size = 68
        else:
            sect_size = 80
        for i in range(segment.nsects):
            if self.f.tell() + sect_size > self.file_size:
                data = {
                    'offset': self.f.tell(),
                    'file_size': self.file_size
                }
                a = Abnormality(title='SECTION OUT OF BOUNDS', data=data)
                break
            sect = self.parse_section()
            segment.add_sect(sect)

        self.parse_segment_flags(segment, flags)
        self.macho.add_lc(segment)
예제 #7
0
    def parse_routines(self, lc):
        if lc.cmd == 'ROUTINES':
            init_address = get_int(self.f)
            init_module = get_int(self.f)
            if self.macho.is_little():
                init_address = little(init_address, 'I')
                init_module = little(init_module, 'I')
            self.f.read(24)
        else:
            init_address = get_ll(self.f)
            init_module = get_ll(self.f)
            if self.macho.is_little():
                init_address = little(init_address, 'Q')
                init_module = little(init_module, 'Q')
            self.f.read(48)

        lc.add_data('init_address', init_address)
        lc.add_data('init_module', init_module)

        self.macho.add_lc(lc)
예제 #8
0
    def parse_routines(self, lc):
        if lc.cmd == 'ROUTINES':
            init_address = get_int(self.f)
            init_module = get_int(self.f)
            if self.macho.is_little():
                init_address = little(init_address, 'I')
                init_module = little(init_module, 'I')
            self.f.read(24)
        else:
            init_address = get_ll(self.f)
            init_module = get_ll(self.f)
            if self.macho.is_little():
                init_address = little(init_address, 'Q')
                init_module = little(init_module, 'Q')
            self.f.read(48)

        lc.add_data('init_address', init_address)
        lc.add_data('init_module', init_module)

        self.macho.add_lc(lc)
예제 #9
0
    def parse_source_version(self, lc):
        version = get_ll(self.f)
        if self.macho.is_little():
            version = little(version, 'Q')

        a = str((version >> 40) & 0xffffff)
        b = str((version >> 30) & 0x3ff)
        c = str((version >> 20) & 0x3ff)
        d = str((version >> 10) & 0x3ff)
        e = str(version & 0x3ff)

        # TODO: fix source version.
        version = a + '.' + b + '.' + c + '.' + d + '.' + e

        lc.add_data('version', version)

        self.macho.add_lc(lc)
예제 #10
0
    def parse_source_version(self, lc):
        version = get_ll(self.f)
        if self.macho.is_little():
            version = little(version, 'Q')

        a = str((version >> 40) & 0xffffff)
        b = str((version >> 30) & 0x3ff)
        c = str((version >> 20) & 0x3ff)
        d = str((version >> 10) & 0x3ff)
        e = str(version & 0x3ff)

        # TODO: fix source version.
        version = a + '.' + b + '.' + c + '.' + d + '.' + e

        lc.add_data('version', version)

        self.macho.add_lc(lc)
예제 #11
0
    def parse_syms(self, macho):
        prev = self.f.tell()
        true_offset = macho.offset + macho.symtab.offset
        if macho.is_64_bit():
            symbol_size = 60
        else:
            symbol_size = 56
        if (true_offset < macho.offset + macho.size and
                true_offset < self.file.size):
            self.f.seek(true_offset)
            for i in range(macho.symtab.nsyms):
                if ((self.f.tell() + symbol_size > macho.offset +
                     macho.size) or (self.f.tell() + symbol_size >
                                          self.file.size)):
                    data = {
                        'offset': self.f.tell(),
                        'mach-o_size': macho.size,
                        'mach-o_offset': macho.offset,
                        'file_size': self.file.size
                    }
                    a = Abnormality(title='REMAINING SYMBOLS OUT OF BOUNDS',
                                    data=data)
                    self.add_abnormality(a)
                    self.f.seek(prev)
                    return
                else:
                    index = get_int(self.f)
                    sym_type = int(self.f.read(1).encode('hex'), 16)
                    sect = int(self.f.read(1).encode('hex'), 16)
                    desc = int(self.f.read(2).encode('hex'), 16)
                    value = None
                    if macho.is_64_bit():
                        if macho.is_little():
                            value = little(get_ll(self.f), 'Q')
                        else:
                            value = get_ll(self.f)
                    else:
                        if macho.is_little():
                            value = little(get_int(self.f), 'I')
                        else:
                            value = get_int(self.f)

                if macho.is_little():
                    index = little(index, 'I')

                if sym_type >= 32:
                    if sym_type in dictionary.stabs:
                        stab = dictionary.stabs[sym_type]
                    else:
                        offset = self.f.tell() - symbol_size
                        data = {
                            'offset': offset,
                            'index': index,
                            'sym_type': sym_type,
                            'sect': sect,
                            'desc': desc,
                            'value': value
                        }
                        a = Abnormality(title='UNKNOWN STAB', data=data)
                        self.add_abnormality(a)
                        continue
                    sym = Symbol(index=index, stab=stab, sect=sect,
                                 value=value)
                    macho.symtab.add_sym(sym)
                else:
                    pext = sym_type & 0x10
                    if sym_type & 0x0e in dictionary.n_types:
                        n_type = dictionary.n_types[sym_type & 0x0e]
                    else:
                        offset = self.f.tell() - symbol_size
                        data = {
                            'offset': offset,
                            'index': index,
                            'pext': pext,
                            'n_type': sym_type & 0x0e,
                            'sect': sect,
                            'desc': desc,
                            'value': value
                        }
                        a = Abnormality(title='UNKNOWN N_TYPE', data=data)
                        self.add_abnormality(a)
                    ext = sym_type & 0x01

                    if macho.is_little():
                        dylib = desc & 0x0f
                        ref = (desc >> 8) & 0xff
                    else:
                        dylib = (desc >> 8) & 0xff
                        ref = desc & 0x0f

                    sym = Symbol(index=index, pext=pext, sym_type=n_type,
                                 ext=ext, sect=sect, dylib=dylib, ref=ref,
                                 value=value)
                    macho.symtab.add_sym(sym)

        else:
            data = {
                'offset': true_offset,
                'mach-o_size': macho.size,
                'mach-o_offset': macho.offset,
                'file_size': self.file.size
            }
            a = Abnormality(title='SYMBOL TABLE OUT OF BOUNDS', data=data)
            self.add_abnormality(a)

        self.f.seek(prev)