Exemplo n.º 1
0
def readClass(machO, vmaddr, protoRefsMap):
	"""Read a ``class_t`` at *vmaddr*, and returns a tuple of 
	:class:`~objc.class_.Class` and pointer (possibly relocated) to superclass,
	if any."""
	
	#	typedef struct class_t {
	#		struct class_t *isa;
	#		struct class_t *superclass;
	#		Cache cache;
	#		IMP *vtable;
	#		class_rw_t *data;
	#	} class_t;
	
	origin = machO.origin
	machO_fromVM = machO.fromVM
	
	classT = machO.makeStruct('5^')
	
	(metaPtr, superPtr, _, _, classRo) = peekStruct(machO.file, classT, position=machO_fromVM(vmaddr)+origin)
	
	cls = _readClassRO(machO, None, protoRefsMap, machO_fromVM(classRo)+origin)
	
	metaClassRo = peekStruct(machO.file, classT, position=machO_fromVM(metaPtr)+origin)[4]
	cls = _readClassRO(machO, cls, protoRefsMap, machO_fromVM(metaClassRo)+origin)
	
	# if the superclass is 0 but the class is not a root class, it is possible
	# that the superclass is an external class.
	if not superPtr and not cls.isRoot:
		superPtr = vmaddr + machO.pointerWidth
		
	return (cls, superPtr)
Exemplo n.º 2
0
def readClass(machO, vmaddr, protoRefsMap):
	"""Read a ``class_t`` at *vmaddr*, and returns a tuple of 
	:class:`~objc.class_.Class` and pointer (possibly relocated) to superclass,
	if any."""
	
	#	typedef struct class_t {
	#		struct class_t *isa;
	#		struct class_t *superclass;
	#		Cache cache;
	#		IMP *vtable;
	#		class_rw_t *data;
	#	} class_t;
	
	origin = machO.origin
	machO_fromVM = machO.fromVM
	
	classT = machO.makeStruct('5^')
	
	(metaPtr, superPtr, _, _, classRo) = peekStruct(machO.file, classT, position=machO_fromVM(vmaddr)+origin)
	
	cls = _readClassRO(machO, None, protoRefsMap, machO_fromVM(classRo)+origin)
	
	metaClassRo = peekStruct(machO.file, classT, position=machO_fromVM(metaPtr)+origin)[4]
	cls = _readClassRO(machO, cls, protoRefsMap, machO_fromVM(metaClassRo)+origin)
	
	# if the superclass is 0 but the class is not a root class, it is possible
	# that the superclass is an external class.
	if not superPtr and not cls.isRoot:
		superPtr = vmaddr + machO.pointerWidth
		
	return (cls, superPtr)
Exemplo n.º 3
0
def readClassName(machO, vmaddr):
	"Read the class name of the Objective-C class at *vmaddr*."
	
	origin = machO.origin
	machO_fromVM = machO.fromVM
	file = machO.file
	
	classT = machO.makeStruct('5^')
	classRoT = machO.makeStruct('3L~7^')
	
	classRo = peekStruct(file, classT, position=machO_fromVM(vmaddr)+origin)[4]
	namePtr = peekStruct(file, classRoT, position=machO_fromVM(classRo)+origin)[4]
	
	return machO.derefString(namePtr)
Exemplo n.º 4
0
def readClassName(machO, vmaddr):
	"Read the class name of the Objective-C class at *vmaddr*."
	
	origin = machO.origin
	machO_fromVM = machO.fromVM
	file = machO.file
	
	classT = machO.makeStruct('5^')
	classRoT = machO.makeStruct('3L~7^')
	
	classRo = peekStruct(file, classT, position=machO_fromVM(vmaddr)+origin)[4]
	namePtr = peekStruct(file, classRoT, position=machO_fromVM(classRo)+origin)[4]
	
	return machO.derefString(namePtr)
Exemplo n.º 5
0
def readCategory(machO, vmaddr, classes, protoRefsMap):
	"""Read a ``category_t`` at *vmaddr*, and returns a tuple of 
	:class:`~objc.category.Category`, and the :class:`~objc.class_.Class` or
	:class:`~objc.class_.RemoteClass` it is patching."""

	#	typedef struct category_t {
	#		const char *name;
	#		struct class_t *cls;
	#		struct method_list_t *instanceMethods;
	#		struct method_list_t *classMethods;
	#		struct protocol_list_t *protocols;
	#		struct objc_property_list *instanceProperties;
	#	} category_t;
	
	pos = machO.fromVM(vmaddr) + machO.origin
	(namePtr, clsPtr, instMethodsPtr, classMethodsPtr, protosPtr, propsPtr) = peekStruct(machO.file, machO.makeStruct('6^'), position=pos)
		
	name = machO.derefString(namePtr)
	
	if not clsPtr:
		clsPtr = vmaddr + machO.pointerWidth
	cls = classAt(machO, clsPtr, classes)
	
	cat = Category(name, cls)
	cat.addClassMethods(readMethodListAt(machO, classMethodsPtr, optional=False))
	cat.addMethods(readMethodListAt(machO, instMethodsPtr, optional=False))
	cat.addProperties(readPropertyListAt(machO, propsPtr))
	
	protocolRefs = _readProtocolRefListAt(machO, protosPtr)
	connectProtocol(cat, protocolRefs, protoRefsMap)

	return cat
Exemplo n.º 6
0
    def analyze(self, machO):
        symtabStruct = machO.makeStruct('4L')
        nlistStruct = machO.makeStruct('LBBH^')

        (symoff, nsyms, stroff, _) = peekStruct(machO.file, symtabStruct)

        # Get all nlist structs
        origin = machO.origin
        nlists = peekStructs(machO.file,
                             nlistStruct,
                             count=nsyms,
                             position=symoff + origin)

        # Now analyze the nlist structs
        symbols = []
        for (ordinal, (idx, typ, sect, desc, value)) in enumerate(nlists):
            string = peekString(machO.file, position=stroff + idx + origin)
            libord = (desc >> 8) & 0xff  # GET_LIBRARY_ORDINAL
            extern = bool(typ & 1)  # N_EXT
            symtype = SYMTYPE_GENERIC if (typ & 0xe) else SYMTYPE_UNDEFINED
            isThumb = bool(desc & 8)  # N_ARM_THUMB_DEF
            if isThumb:
                value &= ~1
            symbol = Symbol(string, value, symtype, ordinal, libord, extern,
                            isThumb)
            symbols.append(symbol)

        # add those symbols back into the Mach-O.
        machO.addSymbols(symbols)
Exemplo n.º 7
0
def readCategory(machO, vmaddr, classes, protoRefsMap):
	"""Read a ``category_t`` at *vmaddr*, and returns a tuple of 
	:class:`~objc.category.Category`, and the :class:`~objc.class_.Class` or
	:class:`~objc.class_.RemoteClass` it is patching."""

	#	typedef struct category_t {
	#		const char *name;
	#		struct class_t *cls;
	#		struct method_list_t *instanceMethods;
	#		struct method_list_t *classMethods;
	#		struct protocol_list_t *protocols;
	#		struct objc_property_list *instanceProperties;
	#	} category_t;
	
	pos = machO.fromVM(vmaddr) + machO.origin
	(namePtr, clsPtr, instMethodsPtr, classMethodsPtr, protosPtr, propsPtr) = peekStruct(machO.file, machO.makeStruct('6^'), position=pos)
		
	name = machO.derefString(namePtr)
	
	if not clsPtr:
		clsPtr = vmaddr + machO.pointerWidth
	cls = classAt(machO, clsPtr, classes)
	
	cat = Category(name, cls)
	cat.addClassMethods(readMethodListAt(machO, classMethodsPtr, optional=False))
	cat.addMethods(readMethodListAt(machO, instMethodsPtr, optional=False))
	cat.addProperties(readPropertyListAt(machO, propsPtr))
	
	protocolRefs = _readProtocolRefListAt(machO, protosPtr)
	connectProtocol(cat, protocolRefs, protoRefsMap)

	return cat
Exemplo n.º 8
0
	def analyze(self, machO):
		symtabStruct = machO.makeStruct('4L')
		nlistStruct = machO.makeStruct('LBBH^')
		
		(symoff, nsyms, stroff, _) = peekStruct(machO.file, symtabStruct)
		
		# Get all nlist structs
		origin = machO.origin
		nlists = peekStructs(machO.file, nlistStruct, count=nsyms, position=symoff+origin)
		
		# Now analyze the nlist structs
		symbols = []
		for (ordinal, (idx, typ, sect, desc, value)) in enumerate(nlists):
			string = peekString(machO.file, position=stroff+idx+origin)
			libord = (desc >> 8) & 0xff  # GET_LIBRARY_ORDINAL
			extern = bool(typ & 1)       # N_EXT
			symtype = SYMTYPE_GENERIC if (typ & 0xe) else SYMTYPE_UNDEFINED
			isThumb = bool(desc & 8)	 # N_ARM_THUMB_DEF
			if isThumb:
				value &= ~1
			symbol = Symbol(string, value, symtype, ordinal, libord, extern, isThumb)
			symbols.append(symbol)
		
		# add those symbols back into the Mach-O.
		machO.addSymbols(symbols)
Exemplo n.º 9
0
    def analyze(self, machO):
        (rebaseOff, rebaseSize, bindOff, bindSize, weakBindOff, weakBindSize,
         lazyBindOff, lazyBindSize, exportOff,
         exportSize) = peekStruct(machO.file, machO.makeStruct('10L'))
        symbols = []

        if bindSize:
            machO.seek(bindOff)
            _bind(machO, bindSize, symbols)

        if weakBindSize:
            machO.seek(weakBindOff)
            _bind(machO, weakBindSize, symbols)

        if lazyBindSize:
            machO.seek(lazyBindOff)
            _bind(machO, lazyBindSize, symbols)

        if exportSize:
            exportOff += machO.origin
            _recursiveProcessExportTrieNode(machO.file, exportOff, exportOff,
                                            exportOff + exportSize, "",
                                            symbols, machO)

        machO.addSymbols(symbols)
Exemplo n.º 10
0
    def analyze(self, machO):
        # Make sure the SYMTAB command is ready.
        if not all(lc.isAnalyzed for lc in machO.loadCommands.all(
                'className', 'SymtabCommand')):
            return True

        (ilocalsym, nlocalsym, iextdefsym, nextdefsym, iundefsym, nundefsym,
         tocoff, ntoc, modtaboff, nmodtab, extrefsymoff, nextrefsyms,
         self.indirectsymoff, nindirectsyms, extreloff, nextrel, locreloff,
         nlocrel) = peekStruct(machO.file, machO.makeStruct('18L'))

        if nextrel:
            machO.provideAddresses(self._exrelIter(machO, extreloff, nextrel))
Exemplo n.º 11
0
	def f(machO, vmaddr):
		if not vmaddr:
			return []
	
		f = machO.file
		ms = machO.makeStruct
		pos = machO.fromVM(vmaddr) + machO.origin
		stru = ms(fmt1)
		count = peekStruct(f, stru, position=pos)[-1]						# use fmt1 to obtain the count
		tuples = peekStructs(f, ms(fmt2), count, position=pos+stru.size)	# use fmt2 to obtain the structures
		lst = [method(machO, s) for s in tuples]
		lst.reverse()
		return lst
Exemplo n.º 12
0
def _readClassRO(machO, cls, protoRefsMap, absfileoff):
	"""Peek a ``class_ro_t`` at *absfileoff*. If *cls* is ``None``, read the
	class as normal class. Otherwise, read as meta class and insert the class
	methods.
	"""

	#	typedef struct class_ro_t {
	#		uint32_t flags;
	#		uint32_t instanceStart;
	#		uint32_t instanceSize;
	#	#ifdef __LP64__
	#		uint32_t reserved;
	#	#endif
	#
	#		const uint8_t * ivarLayout;
	#		
	#		const char * name;
	#		const method_list_t * baseMethods;
	#		const protocol_list_t * baseProtocols;
	#		const ivar_list_t * ivars;
	#
	#		const uint8_t * weakIvarLayout;
	#		const struct objc_property_list *baseProperties;
	#	} class_ro_t;
	
	(flags, _, _, _, namePtr, methodsPtr, protosPtr, ivarsPtr, _, propsPtr) = peekStruct(machO.file, machO.makeStruct('3L~7^'), position=absfileoff)
	
	methods = readMethodListAt(machO, methodsPtr, optional=False)
	
	if cls is None:
		# not meta class.
		
		name = machO.derefString(namePtr)
		cls = Class(name, flags)
		
		cls.addMethods(methods)
		cls.addIvars(readIvarListAt(machO, ivarsPtr))
		cls.addProperties(readPropertyListAt(machO, propsPtr))
		
		protocolRefs = _readProtocolRefListAt(machO, protosPtr)
		
		connectProtocol(cls, protocolRefs, protoRefsMap)
		
	else:
		# is meta-class: prepend the class methods.
		cls.addClassMethods(methods)
	
	return cls
Exemplo n.º 13
0
def _readClassRO(machO, cls, protoRefsMap, absfileoff):
	"""Peek a ``class_ro_t`` at *absfileoff*. If *cls* is ``None``, read the
	class as normal class. Otherwise, read as meta class and insert the class
	methods.
	"""

	#	typedef struct class_ro_t {
	#		uint32_t flags;
	#		uint32_t instanceStart;
	#		uint32_t instanceSize;
	#	#ifdef __LP64__
	#		uint32_t reserved;
	#	#endif
	#
	#		const uint8_t * ivarLayout;
	#		
	#		const char * name;
	#		const method_list_t * baseMethods;
	#		const protocol_list_t * baseProtocols;
	#		const ivar_list_t * ivars;
	#
	#		const uint8_t * weakIvarLayout;
	#		const struct objc_property_list *baseProperties;
	#	} class_ro_t;
	
	(flags, _, _, _, namePtr, methodsPtr, protosPtr, ivarsPtr, _, propsPtr) = peekStruct(machO.file, machO.makeStruct('3L~7^'), position=absfileoff)
	
	methods = readMethodListAt(machO, methodsPtr, optional=False)
	
	if cls is None:
		# not meta class.
		
		name = machO.derefString(namePtr)
		cls = Class(name, flags)
		
		cls.addMethods(methods)
		cls.addIvars(readIvarListAt(machO, ivarsPtr))
		cls.addProperties(readPropertyListAt(machO, propsPtr))
		
		protocolRefs = _readProtocolRefListAt(machO, protosPtr)
		
		connectProtocol(cls, protocolRefs, protoRefsMap)
		
	else:
		# is meta-class: prepend the class methods.
		cls.addClassMethods(methods)
	
	return cls
Exemplo n.º 14
0
def prepareMethodDescriptionList(machO, vmaddr):
	"""Peek a ``objc_method_description_list`` struct at *vmaddr*, and return 
	the ``objc_method_description``\\s as an iterable of 2-tuples."""
	
	#	struct objc_method_description_list {
	#		int count;
	#		struct objc_method_description list[1];
	#	};

	if not vmaddr:
		return tuple()

	absfileoff = machO.fromVM(vmaddr) + machO.origin
	stru = machO.makeStruct('i')
	count = peekStruct(machO.file, stru, position=absfileoff)[0]	
	return peekStructs(machO.file, machO.makeStruct('2^'), count, position=absfileoff+stru.size)
Exemplo n.º 15
0
	def analyze(self, machO):
		# Make sure the SYMTAB command is ready.
		if not all(lc.isAnalyzed for lc in machO.loadCommands.all('className', 'SymtabCommand')):
			return True
	
		(     ilocalsym,      nlocalsym,
		      iextdefsym,     nextdefsym,
		      iundefsym,      nundefsym,
		      tocoff,         ntoc,
		      modtaboff,      nmodtab,
		      extrefsymoff,   nextrefsyms,
		 self.indirectsymoff, nindirectsyms,
		      extreloff,      nextrel,
		      locreloff,      nlocrel) = peekStruct(machO.file, machO.makeStruct('18L'))
		
		if nextrel:
			machO.provideAddresses(self._exrelIter(machO, extreloff, nextrel))
Exemplo n.º 16
0
def readLists(machO, vmaddr, method):
	"""Read a senital-terminated list at *vmaddr* using *method*, and
	concatenate the result.
	
	*method* should have signature::
	
		f(machO, vmaddr)

	and returns an iterable.
	"""

	#	struct old_method {
	#		SEL method_name;
	#		char *method_types;
	#		IMP method_imp;
	#	};
	#
	#	struct old_method_list {
	#		struct old_method_list *obsolete;
	#
	#		int method_count;
	#	#ifdef __LP64__
	#		int space;
	#	#endif
	#		/* variable length structure */
	#		struct old_method method_list[1];
	#	};
	
	retval = []
	
	if vmaddr:
		loc = machO.origin + machO.fromVM(vmaddr)
		stru = machO.makeStruct('^')
		ptrSize = stru.size
		f = machO.file
		while True:
			ptr = peekStruct(f, stru, position=loc)[0]
			if ptr > 0:
				retval.extend(method(machO, ptr))
			else:
				break
			loc += ptrSize
			
	return retval
Exemplo n.º 17
0
	def analyze(self, machO):
		(rebaseOff, rebaseSize, bindOff, bindSize, weakBindOff, weakBindSize, 
			lazyBindOff, lazyBindSize, exportOff, exportSize) = peekStruct(machO.file, machO.makeStruct('10L'))
		symbols = []
		
		if bindSize:
			machO.seek(bindOff)
			_bind(machO, bindSize, symbols)
		
		if weakBindSize:
			machO.seek(weakBindOff)
			_bind(machO, weakBindSize, symbols)
		
		if lazyBindSize:
			machO.seek(lazyBindOff)
			_bind(machO, lazyBindSize, symbols)
		
		if exportSize:
			exportOff += machO.origin
			_recursiveProcessExportTrieNode(machO.file, exportOff, exportOff, exportOff + exportSize, "", symbols)
		
		machO.addSymbols(symbols)
Exemplo n.º 18
0
	def analyze(self, machO):
		(offset, self.timestamp, self.version, self.minVersion) = peekStruct(machO.file, machO.makeStruct('4L'))
		self.name = peekString(machO.file, position=offset + machO.origin + self.offset - 8)
Exemplo n.º 19
0
 def analyze(self, machO):
     (offset, self.timestamp, self.version,
      self.minVersion) = peekStruct(machO.file, machO.makeStruct('4L'))
     self.name = peekString(machO.file,
                            position=offset + machO.origin + self.offset -
                            8)
Exemplo n.º 20
0
def readProtocol(machO, vmaddr):
	"""Peek a ``protocol_t`` at *offset*. Returns a tuple of
	:class:`~objc.protocol.Protocol` and an iterable of protocol addresses it is
	adopting."""

	#	typedef struct protocol_t {
	#		id isa;
	#		const char *name;
	#		struct protocol_list_t *protocols;
	#		method_list_t *instanceMethods;
	#		method_list_t *classMethods;
	#		method_list_t *optionalInstanceMethods;
	#		method_list_t *optionalClassMethods;
	#		struct objc_property_list *instanceProperties;
	#	} protocol_t;
	
	pos = machO.fromVM(vmaddr) + machO.origin
	(_, namePtr, protocolListPtr, instMethodsPtr, classMethodsPtr, optInstMethodsPtr, optClassMethodsPtr, propsPtr) = peekStruct(machO.file, machO.makeStruct('8^'), position=pos)
	
	name = machO.derefString(namePtr)
	protocolRefs = _readProtocolRefListAt(machO, protocolListPtr)
	
	proto = Protocol(name)
	proto.addClassMethods(readMethodListAt(machO, classMethodsPtr, optional=False))
	proto.addClassMethods(readMethodListAt(machO, optClassMethodsPtr, optional=True))
	proto.addMethods(readMethodListAt(machO, instMethodsPtr, optional=False))
	proto.addMethods(readMethodListAt(machO, optInstMethodsPtr, optional=True))

	proto.addProperties(readPropertyListAt(machO, propsPtr))

	return (proto, protocolRefs)
Exemplo n.º 21
0
def readProtocol(machO, vmaddr):
	"""Peek a ``protocol_t`` at *offset*. Returns a tuple of
	:class:`~objc.protocol.Protocol` and an iterable of protocol addresses it is
	adopting."""

	#	typedef struct protocol_t {
	#		id isa;
	#		const char *name;
	#		struct protocol_list_t *protocols;
	#		method_list_t *instanceMethods;
	#		method_list_t *classMethods;
	#		method_list_t *optionalInstanceMethods;
	#		method_list_t *optionalClassMethods;
	#		struct objc_property_list *instanceProperties;
	#	} protocol_t;
	
	pos = machO.fromVM(vmaddr) + machO.origin
	(_, namePtr, protocolListPtr, instMethodsPtr, classMethodsPtr, optInstMethodsPtr, optClassMethodsPtr, propsPtr) = peekStruct(machO.file, machO.makeStruct('8^'), position=pos)
	
	name = machO.derefString(namePtr)
	protocolRefs = _readProtocolRefListAt(machO, protocolListPtr)
	
	proto = Protocol(name)
	proto.addClassMethods(readMethodListAt(machO, classMethodsPtr, optional=False))
	proto.addClassMethods(readMethodListAt(machO, optClassMethodsPtr, optional=True))
	proto.addMethods(readMethodListAt(machO, instMethodsPtr, optional=False))
	proto.addMethods(readMethodListAt(machO, optInstMethodsPtr, optional=True))

	proto.addProperties(readPropertyListAt(machO, propsPtr))

	return (proto, protocolRefs)