Beispiel #1
0
    def _loadSections(self, machO):
        segStruct = machO.makeStruct('16s4^2i2L')
        sectStruct = machO.makeStruct(Section.STRUCT_FORMAT)
        (segname, self.vmaddr, self._vmsize, self._fileoff, self._filesize,
         self.maxprot, self.initprot, nsects,
         _) = readStruct(machO.file, segStruct)

        self.segname = fromStringz(segname)

        machO_fileOrigin = machO._fileOrigin

        sectVals = peekStructs(machO.file, sectStruct,
                               count=nsects)  # get all section headers
        sectionsList = (Section.createSection(i) for i in sectVals
                        )  # convert all headers into Section objects
        sections = DataTable('className', 'sectname', 'ftype')
        for s in sectionsList:
            if s.offset < machO_fileOrigin:
                s.offset += machO_fileOrigin
            sections.append(s,
                            className=type(s).__name__,
                            sectname=s.sectname,
                            ftype=s.ftype)
        self.sections = sections
        self._hasAnalyzedSections = False
        self._shouldImportMappings = machO.mappings.mutable
    def __analyze(self):
        magic_string = peekFixedLengthString(self.file, 15, position=0)
        (magic, archname) = magic_string.split()
        if magic != 'dyld_v1':
            raise MachOError('Invalid magic "{0}"'.format(magic_string))

        self.arch = Arch(archname)
        if self.endian is None:
            self.endian = self.arch.endian
            if self.endian is None:
                raise MachOError(
                    'Cannot guess endian from architecture "{0}"'.format(
                        archname))

        (mappingOffset, mappingCount, imagesOffset, imagesCount, self.dyldBaseAddress) = \
            peekStruct(self.file, Struct(self.endian + '4LQ'), position=16)

        self.mappings = MappingSet(
            self.__analyzeMappings(mappingOffset, mappingCount))
        self.mappings.freeze()

        images = DataTable('!address', '!name', '!path')
        for image in self.__analyzeImages(imagesOffset, imagesCount):
            path = image.path
            bn = basename(path)
            while True:
                (stem, ext) = splitext(bn)
                if not ext:
                    break
                bn = stem

            images.append(image, address=image.address, name=bn, path=path)

        self.images = images
Beispiel #3
0
 def __analyze(self):
     magic_string = peekFixedLengthString(self.file, 15, position=0)
     (magic, archname) = magic_string.split()
     if magic != 'dyld_v1':
         raise MachOError('Invalid magic "{0}"'.format(magic_string))
     
     self.arch = Arch(archname)
     if self.endian is None:
         self.endian = self.arch.endian
         if self.endian is None:
             raise MachOError('Cannot guess endian from architecture "{0}"'.format(archname))
     
     (mappingOffset, mappingCount, imagesOffset, imagesCount, self.dyldBaseAddress) = \
         peekStruct(self.file, Struct(self.endian + '4LQ'), position=16)
         
     self.mappings = MappingSet(self.__analyzeMappings(mappingOffset, mappingCount))
     self.mappings.freeze()
     
     images = DataTable('!address', '!name', '!path')
     for image in self.__analyzeImages(imagesOffset, imagesCount):
         path = image.path
         bn = basename(path)
         while True:
             (stem, ext) = splitext(bn)
             if not ext:
                 break
             bn = stem
             
         images.append(image, address=image.address, name=bn, path=path)
         
     self.images = images
Beispiel #4
0
def analyzeClassList(machO, addressesAndClassTuples, protocols):
	"""Analyze a list of classes, and return a :class:`~data_table.DataTable` of
	:class:`~objc.class_.Class`\\s with the following column names:
	
	* ``'name'`` (unique, string, the name of the class)
	
	* ``'addr'`` (unique, integer, the VM address to the class)
	
	The parameter *addressesAndClassTuples* should be an iteratable of 2-tuples,
	which include the VM address of the class, and a 12-tuple representing an
	``old_class`` struct.
	"""

	classes = DataTable('!name', '!addr')
	supers = []
	for vmaddr, classTuple in addressesAndClassTuples:
		(cls, superPtr) = analyzeClass(machO, classTuple, protocols)
		supers.append(superPtr)
		classes.append(cls, name=cls.name, addr=vmaddr)
	
	for cls, superPtr in zip(classes, supers):
		if superPtr:
			supcls = classAt(machO, superPtr, classes)
			cls.superClass = classAt(machO, superPtr, classes)
	
	return classes
Beispiel #5
0
def readCategoryList(machO, addresses, classes, protoRefsMap):
	"""Read categories from an iterable of *addresses*, and return a
	:class:`~data_table.DataTable` of :class:`~objc.category.Category`\\s with
	the following column names:
	
	* ``'name'`` (string, the name of the category)
	* ``'base'`` (string, the name of the class the category is patching)
	"""
	
	cats = DataTable('name', 'base')
	for vmaddr in addresses:
		cat = readCategory(machO, vmaddr, classes, protoRefsMap)
		cats.append(cat, name=cat.name, base=cat.class_.name)
	
	return cats
Beispiel #6
0
def readCategoryList(machO, addresses, classes, protoRefsMap):
	"""Read categories from an iterable of *addresses*, and return a
	:class:`~data_table.DataTable` of :class:`~objc.category.Category`\\s with
	the following column names:
	
	* ``'name'`` (string, the name of the category)
	* ``'base'`` (string, the name of the class the category is patching)
	"""
	
	cats = DataTable('name', 'base')
	for vmaddr in addresses:
		cat = readCategory(machO, vmaddr, classes, protoRefsMap)
		cats.append(cat, name=cat.name, base=cat.class_.name)
	
	return cats
Beispiel #7
0
def analyzeProtocolList(machO, addressesAndProtoTuples):
	"""Analyze a list of protocols, and return a :class:`~data_table.DataTable`
	of :class:`~objc.protocol.Protocol`\\s with
	the following column names:
	
	* ``'name'`` (string, the name of the protocol)
	
	* ``'addr'`` (unique, integer, the VM address to the protocol)
	
	The parameter *addressesAndProtoTuples* should be an iteratable of 2-tuples,
	which include the VM address of the protocol, and a 5-tuple representing an
	``old_protocol`` struct.
	"""
	
	# associate each unique protocol to a list of vmaddrs.
	protoDict = {}
	protoListDict = {}
	for vmaddr, protoTuple in addressesAndProtoTuples:
		(preped, protoListPtr) = _prepareProtocol(machO, protoTuple)
		if preped in protoDict:
			protoDict[preped].append(vmaddr)
		else:
			protoDict[preped] = [vmaddr]
		if protoListPtr:
			if preped in protoListDict:
				protoListDict[preped].append(protoListPtr)
			else:
				protoListDict[preped] = [protoListPtr]
	
	# now do the actual analysis.
	protos = DataTable('name', '!addr')	# there can be multiple protocols with the same name in ABI 1.0
	refs = []
	d = machO.derefString
	analyzer = methodDescriptionAnalyzer(d)
	for preped, vmaddrs in protoDict.items():
		protoListPtrs = protoListDict[preped] if preped in protoListDict else []
		(proto, protoRefs) = _analyzeProtocol(machO, d, analyzer, preped, protoListPtrs)
		protos.append(proto, name=proto.name)
		protos.associate(proto, 'addr', vmaddrs)
		refs.append(protoRefs)

	# connect the protocols.
	for proto, protocolRefs in zip(protos, refs):
		connectProtocol(proto, protocolRefs, protos)
		
	return protos
Beispiel #8
0
def analyzeCategoryList(machO, catTuples, classes, protocols):
	"""Analyze a list of classes, and return a :class:`~data_table.DataTable` of
	:class:`~objc.class_.Class`\\s with the following column names:
	
	* ``'name'`` (string, the name of the category)
	
	* ``'base'`` (string, the name of the class the category is patching)
	
	The parameter *catTuples* should be an iteratable of 7-tuples representing
	the ``old_category`` structs.
	"""

	cats = DataTable('name', 'base')
	for catTuple in catTuples:
		cat = analyzeCategory(machO, catTuple, classes, protocols)
		cats.append(cat, name=cat.name, base=cat.class_.name)
	
	return cats
Beispiel #9
0
	def _loadSections(self, machO):
		segStruct = machO.makeStruct('16s4^2i2L')
		sectStruct = machO.makeStruct(Section.STRUCT_FORMAT)
		(segname, self.vmaddr, self._vmsize, self._fileoff, self._filesize, self.maxprot, self.initprot, nsects, _) = readStruct(machO.file, segStruct)
		
		self.segname = fromStringz(segname)
		
		machO_fileOrigin = machO._fileOrigin
			
		sectVals = peekStructs(machO.file, sectStruct, count=nsects)	# get all section headers
		sectionsList = (Section.createSection(i) for i in sectVals)	# convert all headers into Section objects
		sections = DataTable('className', 'sectname', 'ftype')
		for s in sectionsList:
			if s.offset < machO_fileOrigin:
				s.offset += machO_fileOrigin
			sections.append(s, className=type(s).__name__, sectname=s.sectname, ftype=s.ftype)
		self.sections = sections
		self._hasAnalyzedSections = False
		self._shouldImportMappings = machO.mappings.mutable
Beispiel #10
0
def readProtocolList(machO, addresses):
	"""Read protocols from an iterable of *addresses*, and return a
	:class:`~data_table.DataTable` of :class:`~objc.protocol.Protocol`\\s with
	the following column names:
	
	* ``'name'`` (unique, string, the name of the protocol)
	* ``'addr'`` (unique, integer, the VM address to the protocol)
	"""
	
	# read protocols from the Mach-O binary.
	protos = DataTable('!name', '!addr')
	refs = []
	for vmaddr in addresses:
		(proto, protocolRefs) = readProtocol(machO, vmaddr)
		protos.append(proto, name=proto.name, addr=vmaddr)
		refs.append(protocolRefs)
	
	# connect the protocols.
	for proto, protocolRefs in zip(protos, refs):
		connectProtocol(proto, protocolRefs, protos)
		
	return protos
Beispiel #11
0
def readProtocolList(machO, addresses):
	"""Read protocols from an iterable of *addresses*, and return a
	:class:`~data_table.DataTable` of :class:`~objc.protocol.Protocol`\\s with
	the following column names:
	
	* ``'name'`` (unique, string, the name of the protocol)
	* ``'addr'`` (unique, integer, the VM address to the protocol)
	"""
	
	# read protocols from the Mach-O binary.
	protos = DataTable('!name', '!addr')
	refs = []
	for vmaddr in addresses:
		(proto, protocolRefs) = readProtocol(machO, vmaddr)
		protos.append(proto, name=proto.name, addr=vmaddr)
		refs.append(protocolRefs)
	
	# connect the protocols.
	for proto, protocolRefs in zip(protos, refs):
		connectProtocol(proto, protocolRefs, protos)
		
	return protos
Beispiel #12
0
def readClassList(machO, addresses, protoRefsMap):
	"""Read classes from an iterable of *addresses*, and return a
	:class:`~data_table.DataTable` of :class:`~objc.class_.Class`\\s with
	the following column names:
	
	* ``'name'`` (unique, string, the name of the class)
	
	* ``'addr'`` (unique, integer, the VM address to the class)
	
	"""
		
	classes = DataTable('!name', '!addr')
	supers = []
	for vmaddr in addresses:
		(cls, superPtr) = readClass(machO, vmaddr, protoRefsMap)
		supers.append(superPtr)
		classes.append(cls, name=cls.name, addr=vmaddr)
	
	for cls, superPtr in zip(classes, supers):
		if not cls.isRoot:
			cls.superClass = classAt(machO, superPtr, classes)
	
	return classes
Beispiel #13
0
def readClassList(machO, addresses, protoRefsMap):
	"""Read classes from an iterable of *addresses*, and return a
	:class:`~data_table.DataTable` of :class:`~objc.class_.Class`\\s with
	the following column names:
	
	* ``'name'`` (unique, string, the name of the class)
	
	* ``'addr'`` (unique, integer, the VM address to the class)
	
	"""
		
	classes = DataTable('!name', '!addr')
	supers = []
	for vmaddr in addresses:
		(cls, superPtr) = readClass(machO, vmaddr, protoRefsMap)
		supers.append(superPtr)
		classes.append(cls, name=cls.name, addr=vmaddr)
	
	for cls, superPtr in zip(classes, supers):
		if not cls.isRoot:
			cls.superClass = classAt(machO, superPtr, classes)
	
	return classes