Exemple #1
0
    def parseRequirements(self, signature, offset):
        prev = self._f.tell()
        true_offset = signature.getOffset() + offset
        self._f.seek(true_offset)
        magic = getInt(self._f)
        if magic != dictionary.signatures['REQUIREMENTS']:
            data = {
                'offset': true_offset,
                'magic': hex(magic),
                'expected': hex(dictionary.signatures['REQUIREMENTS'])
            }
            a = Abnormality(title='BAD MAGIC - REQUIREMENTS', data=data)
            self.addAbnormality(a)
            self._f.seek(prev)
            return
        # Skip size
        self._f.read(4)
        count = getInt(self._f)
        while count > 0:
            req_type = dictionary.requirements[getInt(self._f)]
            offset = getInt(self._f)
            requirement = Requirement(req_type=req_type, offset=offset)
            self.parseRequirement(requirement, true_offset)
            signature.addRequirement(requirement)
            count -= 1

        self._f.seek(prev)
Exemple #2
0
    def parseCerts(self, signature, offset):
        prev = self._f.tell()
        true_offset = signature.getOffset() + offset
        self._f.seek(true_offset)
        magic = getInt(self._f)
        if magic != dictionary.signatures['BLOBWRAPPER']:
            data = {
                'offset': true_offset,
                'magic': hex(magic),
                'expected': hex(dictionary.signatures['BLOBWRAPPER'])
            }
            a = Abnormality(title='BAD MAGIC - BLOBWRAPPER', data=data)
            self.addAbnormality(a)
            self._f.seek(prev)
            return
        size = getInt(self._f) - 8
        # out = open('cms', 'wb')
        # out.write(self._f.read(size))
        # out.close()
        # exit(0)
        if size > 0:
            signed_data = cms.CMS(self._f.read(size), format='DER')
            for cert in signed_data.certs:
                serial = cert.serial
                subject = {
                    'country': self.getCertNameData(cert.subject,
                                                    oid.Oid('C')),
                    'org': self.getCertNameData(cert.subject, oid.Oid('O')),
                    'org_unit': self.getCertNameData(cert.subject,
                                                     oid.Oid('OU')),
                    'common_name': self.getCertNameData(cert.subject,
                                                        oid.Oid('CN'))
                }
                issuer = {
                    'country': self.getCertNameData(cert.issuer, oid.Oid('C')),
                    'org': self.getCertNameData(cert.issuer, oid.Oid('O')),
                    'org_unit': self.getCertNameData(cert.issuer,
                                                     oid.Oid('OU')),
                    'common_name': self.getCertNameData(cert.issuer,
                                                        oid.Oid('CN'))
                }
                ca = cert.check_ca()
                cert = Certificate(serial=serial, subject=subject,
                                   issuer=issuer, ca=ca)
                signature.addCert(cert)
        else:
            data = {
                'offset': true_offset,
                'size': size
            }
            a = Abnormality(title='NON-POSITIVE CMS SIZE', data=data)
            self.addAbnormality(a)

        self._f.seek(prev)
Exemple #3
0
    def parseSig(self, macho):
        if not macho.hasLC('CODE_SIGNATURE'):
            return
        prev = self._f.tell()
        true_offset = (macho.getOffset() +
                       macho.getLC('CODE_SIGNATURE').getData()['offset'])
        if true_offset >= self._file.getSize():
            data = {
                'offset': true_offset,
                'file_size': self._file.getSize()
            }
            a = Abnormality(title='CODE_SIGNATURE OUT OF BOUNDS', data=data)
            self.addAbnormality(a)
            return
        self._f.seek(true_offset)
        magic = getInt(self._f)
        if magic != dictionary.signatures['EMBEDDED_SIGNATURE']:
            data = {
                'offset': true_offset,
                'magic': hex(magic),
                'expected': hex(dictionary.signatures['EMBEDDED_SIGNATURE'])
            }
            a = Abnormality(title='BAD MAGIC - EMBEDDED_SIGNATURE', data=data)
            self.addAbnormality(a)
            self._f.seek(prev)
            return
        size = getInt(self._f)
        count = getInt(self._f)
        signature = Signature(offset=true_offset, size=size, count=count)
        while count > 0:
            index_type = getInt(self._f)
            try:
                index_type = dictionary.indeces[index_type]
            except:
                data = {
                    'offset': self._f.tell() - 4,
                    'index_type': index_type
                }
                a = Abnormality(title='INVALID CODE_SIGNATURE INDEX_TYPE',
                                data=data)
                self.addAbnormality(a)
            offset = getInt(self._f)
            if index_type == 'SignatureSlot':
                self.parseCerts(signature, offset)
            elif index_type == 'CodeDirectorySlot':
                self.parseCodeDirectory(signature, offset)
            elif index_type == 'EntitlementSlot':
                self.parseEntitlement(signature, offset)
            elif index_type == 'RequirementsSlot':
                self.parseRequirements(signature, offset)
            count -= 1

        macho.setSignature(signature)
        self._f.seek(prev)
    def parseTwoLevelHints(self, lc):
        offset = getInt(self._f)
        nhints = getInt(self._f)

        if self._macho.isLittle():
            offset = little(offset, 'I')
            nhints = little(nhints, 'I')

        lc.addData('offset', offset)
        lc.addData('nhints', nhints)

        self._macho.addLC(lc)
    def parseTwoLevelHints(self, lc):
        offset = getInt(self._f)
        nhints = getInt(self._f)

        if self._macho.isLittle():
            offset = little(offset, 'I')
            nhints = little(nhints, 'I')

        lc.addData('offset', offset)
        lc.addData('nhints', nhints)

        self._macho.addLC(lc)
    def parseLinkedITData(self, lc):
        offset = getInt(self._f)
        size = getInt(self._f)

        if self._macho.isLittle():
            offset = little(offset, 'I')
            size = little(size, 'I')

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

        self._macho.addLC(lc)
    def parseLinkedITData(self, lc):
        offset = getInt(self._f)
        size = getInt(self._f)

        if self._macho.isLittle():
            offset = little(offset, 'I')
            size = little(size, 'I')

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

        self._macho.addLC(lc)
Exemple #8
0
 def identifyFile(self, offset):
     prev = self._f.tell()
     self._f.seek(offset)
     magic = getInt(self._f)
     self._f.seek(prev)
     if magic not in dictionary.machos:
         return magic
     return dictionary.machos[magic]
    def parseSection(self):
        name = strip(self._f.read(16))
        segname = strip(self._f.read(16))
        addr = getInt(self._f) if self._macho.is32Bit() else getLL(self._f)
        size = getInt(self._f) if self._macho.is32Bit() else getLL(self._f)
        offset = getInt(self._f)
        align = getInt(self._f)
        reloff = getInt(self._f)
        nreloc = getInt(self._f)
        flags = getInt(self._f)
        self._f.read(8) if self._macho.is32Bit() else self._f.read(12)

        if self._macho.isLittle():
            addr = little(addr, 'I') if self._macho.is32Bit() \
                else little(addr, 'Q')
            size = little(size, 'I') if self._macho.is32Bit() \
                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.parseSectionFlags(section, flags)

        return section
    def parseSection(self):
        name = strip(self._f.read(16))
        segname = strip(self._f.read(16))
        addr = getInt(self._f) if self._macho.is32Bit() else getLL(self._f)
        size = getInt(self._f) if self._macho.is32Bit() else getLL(self._f)
        offset = getInt(self._f)
        align = getInt(self._f)
        reloff = getInt(self._f)
        nreloc = getInt(self._f)
        flags = getInt(self._f)
        self._f.read(8) if self._macho.is32Bit() else self._f.read(12)

        if self._macho.isLittle():
            addr = little(addr, 'I') if self._macho.is32Bit() \
                else little(addr, 'Q')
            size = little(size, 'I') if self._macho.is32Bit() \
                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.parseSectionFlags(section, flags)

        return section
Exemple #11
0
    def parsePrebindCksum(self, lc):
        cksum = getInt(self._f)

        if self._macho.isLittle():
            cksum = little(cksum, 'I')

        lc.addData('cksum', cksum)

        self._macho.addLC(lc)
    def parsePrebindCksum(self, lc):
        cksum = getInt(self._f)

        if self._macho.isLittle():
            cksum = little(cksum, 'I')

        lc.addData('cksum', cksum)

        self._macho.addLC(lc)
Exemple #13
0
    def parseEncryptionInfo(self, lc):
        offset = getInt(self._f)
        size = getInt(self._f)
        id = getInt(self._f)

        if self._macho.isLittle():
            offset = little(offset, 'I')
            size = little(size, 'I')
            id = little(id, 'I')

        lc.addData('offset', offset)
        lc.addData('size', size)
        lc.addData('id', id)

        if lc.getCmd() == 'ENCRYPTION_INFO_64':
            # Skip padding
            self._f.read(4)

        self._macho.addLC(lc)
Exemple #14
0
    def parseSegment(self, lc):
        name = strip(self._f.read(16))
        vmaddr = getInt(self._f) if self._macho.is32Bit() else getLL(self._f)
        vmsize = getInt(self._f) if self._macho.is32Bit() else getLL(self._f)
        offset = getInt(self._f) if self._macho.is32Bit() else getLL(self._f)
        segsize = getInt(self._f) if self._macho.is32Bit() else getLL(self._f)
        maxprot = getInt(self._f)
        initprot = getInt(self._f)
        nsects = getInt(self._f)
        flags = getInt(self._f)

        if self._macho.isLittle():
            vmaddr = little(vmaddr, 'I') if self._macho.is32Bit() \
                else little(vmaddr, 'Q')
            vmsize = little(vmsize, 'I') if self._macho.is32Bit() \
                else little(vmsize, 'Q')
            offset = little(offset, 'I') if self._macho.is32Bit() \
                else little(offset, 'Q')
            segsize = little(segsize, 'I') if self._macho.is32Bit() \
                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]

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

        if self._macho.is32Bit():
            sect_size = 68
        else:
            sect_size = 80
        for i in range(segment.getNSects()):
            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.parseSection()
            segment.addSect(sect)

        self.parseSegmentFlags(segment, flags)
        self._macho.addLC(segment)
    def parseEncryptionInfo(self, lc):
        offset = getInt(self._f)
        size = getInt(self._f)
        id = getInt(self._f)

        if self._macho.isLittle():
            offset = little(offset, 'I')
            size = little(size, 'I')
            id = little(id, 'I')

        lc.addData('offset', offset)
        lc.addData('size', size)
        lc.addData('id', id)

        if lc.getCmd() == 'ENCRYPTION_INFO_64':
            # Skip padding
            self._f.read(4)

        self._macho.addLC(lc)
Exemple #16
0
 def parseEntitlement(self, signature, offset):
     prev = self._f.tell()
     true_offset = signature.getOffset() + offset
     self._f.seek(true_offset)
     magic = getInt(self._f)
     if magic != dictionary.signatures['ENTITLEMENT']:
         data = {
             'offset': true_offset,
             'magic': hex(magic),
             'expected': hex(dictionary.signatures['ENTITLEMENT'])
         }
         a = Abnormality(title='BAD MAGIC - ENTITLEMENT', data=data)
         self.addAbnormality(a)
         self._f.seek(prev)
         return
     size = getInt(self._f) - 8
     plist = plistlib.readPlistFromString(self._f.read(size))
     entitlement = Entitlement(size=size, plist=plist)
     signature.addEntitlement(entitlement)
     self._f.seek(prev)
Exemple #17
0
    def parseThread(self, lc):
        state = getInt(self._f)
        count = getInt(self._f)
        self._f.read(lc.getSize() - 16)

        if self._macho.isLittle():
            state = little(state, 'I')
            count = little(count, 'I')

        try:
            state = dictionary.thread_states[state]
        except:
            data = {'offset': self._f.tell() - lc.getSize(), 'state': state}
            a = Abnormality(title='INVALID THREAD STATE FLAVOR', data=data)
            self.addAbnormality(a)

        lc.addData('state', state)
        lc.addData('count', count)

        self._macho.addLC(lc)
Exemple #18
0
    def parseRoutines(self, lc):
        if lc.getCmd() == 'ROUTINES':
            init_address = getInt(self._f)
            init_module = getInt(self._f)
            if self._macho.isLittle():
                init_address = little(init_address, 'I')
                init_module = little(init_module, 'I')
            self._f.read(24)
        else:
            init_address = getLL(self._f)
            init_module = getLL(self._f)
            if self._macho.isLittle():
                init_address = little(init_address, 'Q')
                init_module = little(init_module, 'Q')
            self._f.read(48)

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

        self._macho.addLC(lc)
    def parseRoutines(self, lc):
        if lc.getCmd() == 'ROUTINES':
            init_address = getInt(self._f)
            init_module = getInt(self._f)
            if self._macho.isLittle():
                init_address = little(init_address, 'I')
                init_module = little(init_module, 'I')
            self._f.read(24)
        else:
            init_address = getLL(self._f)
            init_module = getLL(self._f)
            if self._macho.isLittle():
                init_address = little(init_address, 'Q')
                init_module = little(init_module, 'Q')
            self._f.read(48)

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

        self._macho.addLC(lc)
Exemple #20
0
    def parseUniversal(self):
        self._f.seek(0)
        # skip magic
        self._f.read(4)
        nmachos = getInt(self._f)
        u = Universal(nmachos=nmachos)
        u_size = self.getFile().getSize()
        for i in range(u.getNMachOs()):
            # skip cputype, subtype
            self._f.read(8)
            offset = getInt(self._f)
            size = getInt(self._f)
            # Abnormality OUT_OF_BOUNDS check
            if offset + size > u_size:
                data = {
                    'offset': offset,
                    'size': size,
                    'file_size': u_size
                }
                a = Abnormality(title='MACH-O OUT OF BOUNDS', data=data)
                self.addAbnormality(a)
                continue
            # skip align
            self._f.read(4)
            identity = self.identifyFile(offset)
            # Abnormality BAD_MAGIC check
            if identity not in dictionary.machos.values():
                data = {
                    'offset': offset,
                    'magic': identity,
                }
                a = Abnormality(title='BAD MAGIC - MACH-O')
                self.addAbnormality(a)
                continue
            u.addMachO(MachO(archive=True, offset=offset, arch=identity[0],
                             endi=identity[1], size=size))

        for i in u.genMachOs():
            self.parseMachO(i)

        self._file.setContent(u)
    def parseDySymTab(self, lc):
        il = getInt(self._f)
        nl = getInt(self._f)
        ie = getInt(self._f)
        ne = getInt(self._f)
        iu = getInt(self._f)
        nu = getInt(self._f)
        self._f.read(lc.getSize() - 32)

        if self._macho.isLittle():
            il = little(il, 'I')
            nl = little(nl, 'I')
            ie = little(ie, 'I')
            ne = little(ne, 'I')
            iu = little(iu, 'I')
            nu = little(nu, 'I')

        self._macho.getSymTab().setIL(il)
        self._macho.getSymTab().setNL(nl)
        self._macho.getSymTab().setIE(ie)
        self._macho.getSymTab().setNE(ne)
        self._macho.getSymTab().setIU(iu)
        self._macho.getSymTab().setNU(nu)

        lc.addData('il', il)
        lc.addData('nl', nl)
        lc.addData('ie', ie)
        lc.addData('ne', ne)
        lc.addData('iu', iu)
        lc.addData('nu', nu)

        self._macho.addLC(lc)
    def parseSegment(self, lc):
        name = strip(self._f.read(16))
        vmaddr = getInt(self._f) if self._macho.is32Bit() else getLL(self._f)
        vmsize = getInt(self._f) if self._macho.is32Bit() else getLL(self._f)
        offset = getInt(self._f) if self._macho.is32Bit() else getLL(self._f)
        segsize = getInt(self._f) if self._macho.is32Bit() else getLL(self._f)
        maxprot = getInt(self._f)
        initprot = getInt(self._f)
        nsects = getInt(self._f)
        flags = getInt(self._f)

        if self._macho.isLittle():
            vmaddr = little(vmaddr, 'I') if self._macho.is32Bit() \
                else little(vmaddr, 'Q')
            vmsize = little(vmsize, 'I') if self._macho.is32Bit() \
                else little(vmsize, 'Q')
            offset = little(offset, 'I') if self._macho.is32Bit() \
                else little(offset, 'Q')
            segsize = little(segsize, 'I') if self._macho.is32Bit() \
                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]        

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

        if self._macho.is32Bit():
            sect_size = 68
        else:
            sect_size = 80
        for i in range(segment.getNSects()):
            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.parseSection()
            segment.addSect(sect)

        self.parseSegmentFlags(segment, flags)
        self._macho.addLC(segment)
Exemple #23
0
    def parseDySymTab(self, lc):
        il = getInt(self._f)
        nl = getInt(self._f)
        ie = getInt(self._f)
        ne = getInt(self._f)
        iu = getInt(self._f)
        nu = getInt(self._f)
        self._f.read(lc.getSize() - 32)

        if self._macho.isLittle():
            il = little(il, 'I')
            nl = little(nl, 'I')
            ie = little(ie, 'I')
            ne = little(ne, 'I')
            iu = little(iu, 'I')
            nu = little(nu, 'I')

        self._macho.getSymTab().setIL(il)
        self._macho.getSymTab().setNL(nl)
        self._macho.getSymTab().setIE(ie)
        self._macho.getSymTab().setNE(ne)
        self._macho.getSymTab().setIU(iu)
        self._macho.getSymTab().setNU(nu)

        lc.addData('il', il)
        lc.addData('nl', nl)
        lc.addData('ie', ie)
        lc.addData('ne', ne)
        lc.addData('iu', iu)
        lc.addData('nu', nu)

        self._macho.addLC(lc)
    def parseThread(self, lc):
        state = getInt(self._f)
        count = getInt(self._f)
        self._f.read(lc.getSize() - 16)

        if self._macho.isLittle():
            state = little(state, 'I')
            count = little(count, 'I')

        try:
            state = dictionary.thread_states[state]
        except:
            data = {
                'offset': self._f.tell() - lc.getSize(),
                'state': state
            }
            a = Abnormality(title='INVALID THREAD STATE FLAVOR', data=data)
            self.addAbnormality(a)

        lc.addData('state', state)
        lc.addData('count', count)

        self._macho.addLC(lc)
    def parseLoadDylib(self, lc):
        offset = getInt(self._f)

        if self._macho.isLittle():
            offset = little(offset, 'I')

        # skip to dylib
        self._f.read(offset - 12)
        dylib = strip(self._f.read(lc.getSize() - 24))
        self._macho.addDylib(dylib)

        lc.addData('dylib', dylib)

        self._macho.addLC(lc)
Exemple #26
0
    def parseVersionMinOS(self, lc):
        version = getInt(self._f)
        sdk = getInt(self._f)

        if self._macho.isLittle():
            version = little(version, 'I')
            sdk = little(sdk, 'I')

        vx = version >> 16
        vy = (version >> 8) & 0xff
        vz = version & 0xff
        version = OSVersion(vx=vx, vy=vy, vz=vz)

        sx = str(sdk >> 16)
        sy = str((sdk >> 8) & 0xff)
        sz = str(sdk & 0xff)
        sdk = sx + '.' + sy + '.' + sz

        lc.addData('version', version.getVersion())
        lc.addData('sdk', sdk)

        self._macho.setMinOS(version)
        self._macho.addLC(lc)
    def parseVersionMinOS(self, lc):
        version = getInt(self._f)
        sdk = getInt(self._f)

        if self._macho.isLittle():
            version = little(version, 'I')
            sdk = little(sdk, 'I')

        vx = version >> 16
        vy = (version >> 8) & 0xff
        vz = version & 0xff
        version = OSVersion(vx=vx, vy=vy, vz=vz)

        sx = str(sdk >> 16)
        sy = str((sdk >> 8) & 0xff)
        sz = str(sdk & 0xff)
        sdk = sx + '.' + sy + '.' + sz

        lc.addData('version', version.getVersion())
        lc.addData('sdk', sdk)

        self._macho.setMinOS(version)
        self._macho.addLC(lc)
Exemple #28
0
    def parseLoadDylib(self, lc):
        offset = getInt(self._f)

        if self._macho.isLittle():
            offset = little(offset, 'I')

        # skip to dylib
        self._f.read(offset - 12)
        dylib = strip(self._f.read(lc.getSize() - 24))
        self._macho.addDylib(dylib)

        lc.addData('dylib', dylib)

        self._macho.addLC(lc)
    def parseSymTab(self, lc):
        symoff = getInt(self._f)
        nsyms = getInt(self._f)
        stroff = getInt(self._f)
        strsize = getInt(self._f)

        if self._macho.isLittle():
            symoff = little(symoff, 'I')
            nsyms = little(nsyms, 'I')
            stroff = little(stroff, 'I')
            strsize = little(strsize, 'I')

        symtab = SymbolTable(offset=symoff, nsyms=nsyms)
        strtab = StringTable(offset=stroff, size=strsize)

        self._macho.setSymTab(symtab)
        self._macho.setStrTab(strtab)

        lc.addData('symoff', symoff)
        lc.addData('nsyms', nsyms)
        lc.addData('stroff', stroff)
        lc.addData('strsize', strsize)

        self._macho.addLC(lc)
    def parseDyldInfo(self, lc):
        rebase_off = getInt(self._f)
        rebase_size = getInt(self._f)
        bind_off = getInt(self._f)
        bind_size = getInt(self._f)
        weak_bind_off = getInt(self._f)
        weak_bind_size = getInt(self._f)
        lazy_bind_off = getInt(self._f)
        lazy_bind_size = getInt(self._f)
        export_off = getInt(self._f)
        export_size = getInt(self._f)

        if self._macho.isLittle():
            rebase_off = little(rebase_off, 'I')
            rebase_size = little(rebase_size, 'I')
            bind_off = little(bind_off, 'I')
            bind_size = little(bind_size, 'I')
            weak_bind_off = little(weak_bind_off, 'I')
            weak_bind_size = little(weak_bind_size, 'I')
            lazy_bind_off = little(lazy_bind_off, 'I')
            lazy_bind_size = little(lazy_bind_size, 'I')
            export_off = little(export_off, 'I')
            export_size = little(export_size, 'I')

        lc.addData('rebase_off', rebase_off)
        lc.addData('rebase_size', rebase_size)
        lc.addData('bind_off', bind_off)
        lc.addData('bind_size', bind_size)
        lc.addData('weak_bind_off', weak_bind_off)
        lc.addData('weak_bind_size', weak_bind_size)
        lc.addData('lazy_bind_off', lazy_bind_off)
        lc.addData('lazy_bind_size', lazy_bind_size)
        lc.addData('export_off', export_off)
        lc.addData('export_size', export_size)

        self._macho.addLC(lc)
Exemple #31
0
    def parseSymTab(self, lc):
        symoff = getInt(self._f)
        nsyms = getInt(self._f)
        stroff = getInt(self._f)
        strsize = getInt(self._f)

        if self._macho.isLittle():
            symoff = little(symoff, 'I')
            nsyms = little(nsyms, 'I')
            stroff = little(stroff, 'I')
            strsize = little(strsize, 'I')

        symtab = SymbolTable(offset=symoff, nsyms=nsyms)
        strtab = StringTable(offset=stroff, size=strsize)

        self._macho.setSymTab(symtab)
        self._macho.setStrTab(strtab)

        lc.addData('symoff', symoff)
        lc.addData('nsyms', nsyms)
        lc.addData('stroff', stroff)
        lc.addData('strsize', strsize)

        self._macho.addLC(lc)
Exemple #32
0
    def parseDyldInfo(self, lc):
        rebase_off = getInt(self._f)
        rebase_size = getInt(self._f)
        bind_off = getInt(self._f)
        bind_size = getInt(self._f)
        weak_bind_off = getInt(self._f)
        weak_bind_size = getInt(self._f)
        lazy_bind_off = getInt(self._f)
        lazy_bind_size = getInt(self._f)
        export_off = getInt(self._f)
        export_size = getInt(self._f)

        if self._macho.isLittle():
            rebase_off = little(rebase_off, 'I')
            rebase_size = little(rebase_size, 'I')
            bind_off = little(bind_off, 'I')
            bind_size = little(bind_size, 'I')
            weak_bind_off = little(weak_bind_off, 'I')
            weak_bind_size = little(weak_bind_size, 'I')
            lazy_bind_off = little(lazy_bind_off, 'I')
            lazy_bind_size = little(lazy_bind_size, 'I')
            export_off = little(export_off, 'I')
            export_size = little(export_size, 'I')

        lc.addData('rebase_off', rebase_off)
        lc.addData('rebase_size', rebase_size)
        lc.addData('bind_off', bind_off)
        lc.addData('bind_size', bind_size)
        lc.addData('weak_bind_off', weak_bind_off)
        lc.addData('weak_bind_size', weak_bind_size)
        lc.addData('lazy_bind_off', lazy_bind_off)
        lc.addData('lazy_bind_size', lazy_bind_size)
        lc.addData('export_off', export_off)
        lc.addData('export_size', export_size)

        self._macho.addLC(lc)
    def parseLinkerOption(self, lc):
        count = getInt(self._f)
        if self._macho.isLittle():
            count = little(count, 'I')
        linker_options = []
        start = self._f.tell()
        for i in range(count):
            linker_option = readstring(self._f)
            linker_options.append(linker_option)

        length = self._f.tell() - start
        self._f.read(lc.getSize() - length - 12)

        lc.addData('count', count)
        lc.addData('linker_options', linker_options)

        self._macho.addLC(lc)
Exemple #34
0
    def parseLinkerOption(self, lc):
        count = getInt(self._f)
        if self._macho.isLittle():
            count = little(count, 'I')
        linker_options = []
        start = self._f.tell()
        for i in range(count):
            linker_option = readstring(self._f)
            linker_options.append(linker_option)

        length = self._f.tell() - start
        self._f.read(lc.getSize() - length - 12)

        lc.addData('count', count)
        lc.addData('linker_options', linker_options)

        self._macho.addLC(lc)
Exemple #35
0
    def parseRequirement(self, requirement, offset):
        prev = self._f.tell()
        true_offset = offset + requirement.getOffset()
        self._f.seek(true_offset)
        magic = getInt(self._f)
        if magic != dictionary.signatures['REQUIREMENT']:
            data = {
                'offset': true_offset,
                'magic': hex(magic),
                'expected': hex(dictionary.signatures['REQUIREMENT'])
            }
            a = Abnormality(title='BAD MAGIC - REQUIREMENT', data=data)
            self.addAbnormality(a)
            self._f.seek(prev)
            return
        # Skip size and kind
        self._f.read(8)
        requirement.setExpression(self.parseExpression(False))

        self._f.seek(prev)
Exemple #36
0
 def parseMatch(self):
     match_type = getInt(self._f)
     if match_type in dictionary.matches:
         match_type = dictionary.matches[match_type]
     if match_type == 'matchExists':
         return ' /* exists */'
     elif match_type == 'matchEqual':
         return ' = "' + str(self.parseData()) + '"'
     elif match_type == 'matchContains':
         return ' ~ "' + str(self.parseData()) + '"'
     elif match_type == 'matchBeginsWith':
         return ' = "' + str(self.parseData()) + '*"'
     elif match_type == 'matchEndsWith':
         return ' = "*' + str(self.parseData()) + '"'
     elif match_type == 'matchLessThan':
         return ' < ' + str(int(self.parseData().encode('hex'), 16))
     elif match_type == 'matchGreaterThan':
         return ' > ' + str(int(self.parseData().encode('hex'), 16))
     elif match_type == 'matchLessEqual':
         return ' <= ' + str(int(self.parseData().encode('hex'), 16))
     elif match_type == 'matchGreaterEqual':
         return ' >= ' + str(int(self.parseData().encode('hex'), 16))
     else:
         return ' UNKNOWN MATCH TYPE (' + str(match_type) + ')'
Exemple #37
0
    def parseExpression(self, in_or):
        # Zero out flags in high byte
        operator = dictionary.operators[getInt(self._f) & 0xfff]
        expression = ''
        if operator == 'False':
            expression += 'never'
        elif operator == 'True':
            expression += 'always'
        elif operator == 'Ident':
            expression += 'identity "' + str(self.parseData()) + '"'
        elif operator == 'AppleAnchor':
            expression += 'anchor apple'
        elif operator == 'AppleGenericAnchor':
            expression += 'anchor apple generic'
        elif operator == 'AnchorHash':
            cert_slot = getInt(self._f)
            if cert_slot in dictionary.cert_slots:
                cert_slot = dictionary.cert_slots[cert_slot]
            else:
                cert_slot = str(cert_slot)
            expression += ('certificate ' + cert_slot + ' = ' +
                           str(self.parseData().encode('hex')))
        elif operator == 'InfoKeyValue':
            expression += ('info[' + str(self.parseData()) + '] = "' +
                           str(self.parseData()) + '"')
        elif operator == 'And':
            if in_or:
                expression += ('(' + self.parseExpression(False) + ' and ' +
                               self.parseExpression(False) + ')')
            else:
                expression += (self.parseExpression(False) + ' and ' +
                               self.parseExpression(False))
        elif operator == 'Or':
            if in_or:
                expression += ('(' + self.parseExpression(True) + ' or ' +
                               self.parseExpression(True) + ')')
            else:
                expression += (self.parseExpression(True) + ' or ' +
                               self.parseExpression(True))
        elif operator == 'Not':
            expression += '! ' + self.parseExpression(False)
        elif operator == 'CDHash':
            expression += 'cdhash ' + str(self.parseData().encode('hex'))
        elif operator == 'InfoKeyField':
            expression += ('info[' + str(self.parseData()) + ']' +
                           self.parseMatch())
        elif operator == 'EntitlementField':
            expression += ('entitlement[' + str(self.parseData()) +
                           ']' + self.parseMatch())
        elif operator == 'CertField':
            cert_slot = getInt(self._f)
            if cert_slot in dictionary.cert_slots:
                cert_slot = dictionary.cert_slots[cert_slot]
            else:
                cert_slot = str(cert_slot)
            expression += ('certificate ' + cert_slot + '[' +
                           str(self.parseData()) + ']' + self.parseMatch())
        elif operator == 'CertGeneric':
            cert_slot = getInt(self._f)
            if cert_slot in dictionary.cert_slots:
                cert_slot = dictionary.cert_slots[cert_slot]
            else:
                cert_slot = str(cert_slot)
            length = getInt(self._f)
            expression += ('certificate ' + cert_slot + '[field.' +
                           self.toOID(length) + ']' + self.parseMatch())
        elif operator == 'CertPolicy':
            cert_slot = getInt(self._f)
            if cert_slot in dictionary.cert_slots:
                cert_slot = dictionary.cert_slots[cert_slot]
            else:
                cert_slot = str(cert_slot)
            expression += ('certificate ' + cert_slot + '[policy.' +
                           str(self.parseData()) + ']' + self.parseMatch())
        elif operator == 'TrustedCert':
            cert_slot = getInt(self._f)
            if cert_slot in dictionary.cert_slots:
                cert_slot = dictionary.cert_slots[cert_slot]
            else:
                cert_slot = str(cert_slot)
            expression += 'certificate ' + cert_slot + ' trusted'
        elif operator == 'TrustedCerts':
            expression += 'anchor trusted'
        elif operator == 'NamedAnchor':
            expression += 'anchor apple ' + str(self.parseData())
        elif operator == 'NamedCode':
            expression += '(' + str(self.parseData()) + ')'
        elif operator == 'Platform':
            expression += 'platform = ' + str(getInt(self._f))

        if isinstance(expression, unicode):
            return expression
        else:
            return unicode(expression, errors='replace')
Exemple #38
0
    def parseLCs(self):
        for i in range(self._macho.getNLCs()):
            cmd = getInt(self._f)
            size = getInt(self._f)

            if self._macho.getEndi() == 'little':
                cmd = little(cmd, 'I')
                size = little(size, 'I')

            # print ('(offset, cmd, size): (' + str(self._f.tell() - 8) + ', ' +
            #       str(cmd) + ', ' + str(size) + ')')

            try:
                cmd = dictionary.loadcommands[cmd]
            except:
                data = {'offset': self._f.tell() - 8, 'cmd': cmd}
                a = Abnormality(title='UNKNOWN LOADCOMMAND', data=data)
                self.addAbnormality(a)
                lc = LoadCommand(cmd=cmd, size=size)
                self._macho.addLC(lc)
                self._f.read(size - 8)
                continue

            lc = LoadCommand(cmd=cmd, size=size)

            if cmd == 'SEGMENT' or cmd == 'SEGMENT_64':
                self.parseSegment(lc)
            elif cmd == 'SYMTAB':
                self.parseSymTab(lc)
            elif cmd == 'SYMSEG':
                self.parseSymSeg(lc)
            elif cmd == 'THREAD' or cmd == 'UNIXTHREAD':
                self.parseThread(lc)
            elif cmd == 'LOADFVMLIB' or cmd == 'IDFVMLIB':
                self.parseFVMLib(lc)
            elif cmd == 'IDENT':
                self.parseIdent(lc)
            elif cmd == 'FVMFILE':
                self.parseFVMFile(lc)
            elif cmd == 'PREPAGE':
                self.parsePrePage(lc)
            elif cmd == 'DYSYMTAB':
                self.parseDySymTab(lc)
            elif (cmd == 'LOAD_DYLIB' or cmd == 'ID_DYLIB'
                  or cmd == 'LAZY_LOAD_DYLIB' or cmd == 'LOAD_WEAK_DYLIB'
                  or cmd == 'REEXPORT_DYLIB' or cmd == 'LOAD_UPWARD_DYLIB'):
                self.parseLoadDylib(lc)
            elif (cmd == 'LOAD_DYLINKER' or cmd == 'ID_DYLINKER'
                  or cmd == 'DYLD_ENVIRONMENT'):
                self.parseLoadDylinker(lc)
            elif cmd == 'PREBOUND_DYLIB':
                self.parsePreboundDylib(lc)
            elif cmd == 'ROUTINES' or cmd == 'ROUTINES_64':
                self.parseRoutines(lc)
            elif (cmd == 'SUB_FRAMEWORK' or cmd == 'SUB_UMBRELLA'
                  or cmd == 'SUB_CLIENT' or cmd == 'SUB_LIBRARY'):
                self.parseSubStuff(lc)
            elif cmd == 'TWOLEVEL_HINTS':
                self.parseTwoLevelHints(lc)
            elif cmd == 'PREBIND_CKSUM':
                self.parsePrebindCksum(lc)
            elif cmd == 'UUID':
                self.parseUUID(lc)
            elif (cmd == 'CODE_SIGNATURE' or cmd == 'SEGMENT_SPLIT_INFO'
                  or cmd == 'FUNCTION_STARTS' or cmd == 'DATA_IN_CODE'
                  or cmd == 'DYLIB_CODE_SIGN_DRS'
                  or cmd == 'LINKER_OPTIMIZATION_HINT'):
                self.parseLinkedITData(lc)
            elif cmd == 'ENCRYPTION_INFO' or cmd == 'ENCRYPTION_INFO_64':
                self.parseEncryptionInfo(lc)
            elif cmd == 'DYLD_INFO' or cmd == 'DYLD_INFO_ONLY':
                self.parseDyldInfo(lc)
            elif (cmd == 'VERSION_MIN_MACOSX' or cmd == 'VERSION_MIN_IPHONEOS'
                  or cmd == 'VERSION_MIN_WATCHOS'):
                self.parseVersionMinOS(lc)
            elif cmd == 'SOURCE_VERSION':
                self.parseSourceVersion(lc)
            elif cmd == 'LINKER_OPTION':
                self.parseLinkerOption(lc)
            elif cmd == 'RPATH':
                self.parseRPath(lc)
            elif cmd == 'MAIN':
                self.parseMain(lc)
Exemple #39
0
 def parseData(self):
     length = getInt(self._f)
     data = self._f.read(length)
     # Skip padding
     self._f.read(-length & 3)
     return data
Exemple #40
0
    def parseMachO(self, macho):
        self._f.seek(macho.getOffset())
        # skip magic
        self._f.read(4)
        cputype = getInt(self._f)
        # print 'cputype: ' + str(cputype)
        # print 'offset: ' + str(self._f.tell())
        subtype = getInt(self._f)
        filetype = getInt(self._f)
        nlcs = getInt(self._f)
        slcs = getInt(self._f)
        flags = getInt(self._f)

        if macho.is64Bit():
            # skip padding
            self._f.read(4)

        if macho.isLittle():
            cputype = little(cputype, 'I')
            subtype = little(subtype, 'I')
            filetype = little(filetype, 'I')
            nlcs = little(nlcs, 'I')
            slcs = little(slcs, 'I')
            flags = little(flags, 'I')

        try:
            cpu = dictionary.cputypes[cputype][-2]
        except:
            cpu = cputype
            data = {
                'offset': macho.getOffset() + 4,
                'cputype': cputype
            }
            a = Abnormality(title='UNKNOWN CPUTYPE', data=data)
            self.addAbnormality(a)
        try:
            subtype = dictionary.cputypes[cputype][subtype]
        except:
            data = {
                'offset': macho.getOffset() + 8,
                'cputype': cputype,
                'subtype': subtype
            }
            a = Abnormality(title='UNKNOWN SUBTYPE', data=data)
            self.addAbnormality(a)
        try:
            filetype = dictionary.filetypes[filetype]
        except:
            data = {
                'offset': macho.getOffset() + 12,
                'filetype': filetype
            }
            a = Abnormality(title='UNKNOWN FILETYPE', data=data)
            self.addAbnormality(a)
        flags = self.listMachOFlags(flags)

        macho.setCPUType(cpu)
        macho.setSubType(subtype)
        macho.setFileType(filetype)
        macho.setNLCs(nlcs)
        macho.setSLCs(slcs)
        macho.setFlags(flags)

        lc = LoadCommander(f=self._f, macho=macho, file_size=self._file.getSize())
        lc.parseLCs()
        self._abnormalities += lc.getAbnormalities()

        # Need to investigate whether the presence of a
        # symbol/string table is expected and whether the
        # abscence is indicative of shenanigans.
        if macho.hasLC('SYMTAB'):
            self.parseSyms(macho)
            self.parseImportsAndStrings(macho)

        if macho.hasLC('CODE_SIGNATURE'):
            self.parseSig(macho)

        if not macho.isArchive():
            self._file.setContent(macho)
Exemple #41
0
    def parseCodeDirectory(self, signature, offset):
        prev = self._f.tell()
        true_offset = signature.getOffset() + offset
        self._f.seek(true_offset)
        magic = getInt(self._f)
        if magic != dictionary.signatures['CODEDIRECTORY']:
            data = {
                'offset': true_offset,
                'magic': hex(magic),
                'expected': hex(dictionary.signatures['CODEDIRECTORY'])
            }
            a = Abnormality(title='BAD MAGIC - CODEDIRECTORY', data=data)
            self.addAbnormality(a)
            self._f.seek(prev)
            return
        # Skip size
        self._f.read(4)
        version = getInt(self._f)
        # Not sure how to parse flags yet...
        flags = getInt(self._f)
        hash_offset = getInt(self._f)
        ident_offset = getInt(self._f)
        n_special_slots = getInt(self._f)
        n_code_slots = getInt(self._f)
        code_limit = getInt(self._f)
        hash_size = int(self._f.read(1).encode('hex'), 16)
        hash_type = dictionary.hashes[int(self._f.read(1).encode('hex'), 16)]
        if version >= 0x20200:
            platform = int(self._f.read(1).encode('hex'), 16)
        else:
            # Skip spare1
            self._f.read(1)
        page_size = int(round(exp(int(self._f.read(1).encode('hex'),
                                      16) * log(2))))
        # Skip spare2
        self._f.read(4)
        if version >= 0x20100:
            scatter_offset = getInt(self._f)
        if version >= 0x20200:
            team_id_offset = getInt(self._f)
            self._f.seek(true_offset + team_id_offset)
            team_id = readstring(self._f)
        self._f.seek(true_offset + ident_offset)
        identity = readstring(self._f)
        codedirectory = CodeDirectory(version=version, flags=flags,
                                      hash_offset=hash_offset,
                                      n_special_slots=n_special_slots,
                                      n_code_slots=n_code_slots,
                                      code_limit=code_limit,
                                      hash_size=hash_size, hash_type=hash_type,
                                      page_size=page_size, identity=identity)
        if version >= 0x20100:
            codedirectory.setScatterOffset(scatter_offset)
        if version >= 0x20200:
            codedirectory.setPlatform(platform)
            codedirectory.setTeamIDOffset(team_id_offset)
            codedirectory.setTeamID(team_id)
        self._f.seek(true_offset + hash_offset - n_special_slots * hash_size)
        count = n_special_slots + n_code_slots
        while count > 0:
            hash = self._f.read(hash_size).encode('hex')
            codedirectory.addHash(hash)
            count -= 1

        signature.setCodeDirectory(codedirectory)
        self._f.seek(prev)
Exemple #42
0
    def parseSyms(self, macho):
        prev = self._f.tell()
        true_offset = macho.getOffset() + macho.getSymTab().getOffset()
        if macho.is64Bit():
            symbol_size = 60
        else:
            symbol_size = 56
        # print 'to:', true_offset
        # print macho.getOffset(), macho.getSize()
        if (true_offset < macho.getOffset() + macho.getSize() and
                true_offset < self._file.getSize()):
            self._f.seek(true_offset)
            for i in range(macho.getSymTab().getNSyms()):
                # print self._f.tell()
                if ((self._f.tell() + symbol_size > macho.getOffset() +
                     macho.getSize()) or (self._f.tell() + symbol_size >
                                          self._file.getSize())):
                    data = {
                        'offset': self._f.tell(),
                        'mach-o_size': macho.getSize(),
                        'mach-o_offset': macho.getOffset(),
                        'file_size': self._file.getSize()
                    }
                    a = Abnormality(title='REMAINING SYMBOLS OUT OF BOUNDS',
                                    data=data)
                    self.addAbnormality(a)
                    self._f.seek(prev)
                    return
                else:
                    index = getInt(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.is64Bit():
                        if macho.isLittle():
                            value = little(getLL(self._f), 'Q')
                        else:
                            value = getLL(self._f)
                    else:
                        if macho.isLittle():
                            value = little(getInt(self._f), 'I')
                        else:
                            value = getInt(self._f)

                if macho.isLittle():
                    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.addAbnormality(a)
                        continue
                    sym = Symbol(index=index, stab=stab, sect=sect,
                                 value=value)
                    macho.getSymTab().addSym(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.addAbnormality(a)
                    ext = sym_type & 0x01

                    if macho.isLittle():
                        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.getSymTab().addSym(sym)

                # print self._f.tell()
                # print sym.getIndex(), sym.getValue()
        else:
            data = {
                'offset': true_offset,
                'mach-o_size': macho.getSize(),
                'mach-o_offset': macho.getOffset(),
                'file_size': self._file.getSize()
            }
            a = Abnormality(title='SYMBOL TABLE OUT OF BOUNDS', data=data)
            self.addAbnormality(a)

        self._f.seek(prev)
    def parseLCs(self):
        for i in range(self._macho.getNLCs()):
            cmd = getInt(self._f)
            size = getInt(self._f)

            if self._macho.getEndi() == 'little':
                cmd = little(cmd, 'I')
                size = little(size, 'I')

            # print ('(offset, cmd, size): (' + str(self._f.tell() - 8) + ', ' +
            #       str(cmd) + ', ' + str(size) + ')')

            try:
                cmd = dictionary.loadcommands[cmd]
            except:
                data = {
                    'offset': self._f.tell() - 8,
                    'cmd': cmd
                }
                a = Abnormality(title='UNKNOWN LOADCOMMAND', data=data)
                self.addAbnormality(a)
                lc = LoadCommand(cmd=cmd, size=size)
                self._macho.addLC(lc)
                self._f.read(size - 8)
                continue

            lc = LoadCommand(cmd=cmd, size=size)

            if cmd == 'SEGMENT' or cmd == 'SEGMENT_64':
                self.parseSegment(lc)
            elif cmd == 'SYMTAB':
                self.parseSymTab(lc)
            elif cmd == 'SYMSEG':
                self.parseSymSeg(lc)
            elif cmd == 'THREAD' or cmd == 'UNIXTHREAD':
                self.parseThread(lc)
            elif cmd == 'LOADFVMLIB' or cmd == 'IDFVMLIB':
                self.parseFVMLib(lc)
            elif cmd == 'IDENT':
                self.parseIdent(lc)
            elif cmd == 'FVMFILE':
                self.parseFVMFile(lc)
            elif cmd == 'PREPAGE':
                self.parsePrePage(lc)
            elif cmd == 'DYSYMTAB':
                self.parseDySymTab(lc)
            elif (cmd == 'LOAD_DYLIB' or cmd == 'ID_DYLIB' or
                  cmd == 'LAZY_LOAD_DYLIB' or cmd == 'LOAD_WEAK_DYLIB' or
                  cmd == 'REEXPORT_DYLIB' or cmd == 'LOAD_UPWARD_DYLIB'):
                self.parseLoadDylib(lc)
            elif (cmd == 'LOAD_DYLINKER' or cmd == 'ID_DYLINKER' or
                  cmd == 'DYLD_ENVIRONMENT'):
                self.parseLoadDylinker(lc)
            elif cmd == 'PREBOUND_DYLIB':
                self.parsePreboundDylib(lc)
            elif cmd == 'ROUTINES' or cmd == 'ROUTINES_64':
                self.parseRoutines(lc)
            elif (cmd == 'SUB_FRAMEWORK' or cmd == 'SUB_UMBRELLA' or
                  cmd == 'SUB_CLIENT' or cmd == 'SUB_LIBRARY'):
                self.parseSubStuff(lc)
            elif cmd == 'TWOLEVEL_HINTS':
                self.parseTwoLevelHints(lc)
            elif cmd == 'PREBIND_CKSUM':
                self.parsePrebindCksum(lc)
            elif cmd == 'UUID':
                self.parseUUID(lc)
            elif (cmd == 'CODE_SIGNATURE' or cmd == 'SEGMENT_SPLIT_INFO' or
                  cmd == 'FUNCTION_STARTS' or cmd == 'DATA_IN_CODE' or
                  cmd == 'DYLIB_CODE_SIGN_DRS' or
                  cmd == 'LINKER_OPTIMIZATION_HINT'):
                self.parseLinkedITData(lc)
            elif cmd == 'ENCRYPTION_INFO' or cmd == 'ENCRYPTION_INFO_64':
                self.parseEncryptionInfo(lc)
            elif cmd == 'DYLD_INFO' or cmd == 'DYLD_INFO_ONLY':
                self.parseDyldInfo(lc)
            elif (cmd == 'VERSION_MIN_MACOSX' or
                  cmd == 'VERSION_MIN_IPHONEOS' or
                  cmd == 'VERSION_MIN_WATCHOS'):
                self.parseVersionMinOS(lc)
            elif cmd == 'SOURCE_VERSION':
                self.parseSourceVersion(lc)
            elif cmd == 'LINKER_OPTION':
                self.parseLinkerOption(lc)
            elif cmd == 'RPATH':
                self.parseRPath(lc)
            elif cmd == 'MAIN':
                self.parseMain(lc)