.. attribute:: cryptid The method of encryption. """ def analyze(self, machO): (self.cryptoff, self.cryptsize, self.cryptid) = machO.readFormatStruct('3L') def __str__(self): return "<EncryptionInfo {}/{:x}>".format(self.cryptid, self.cryptoff) def encrypted(self, offset): """Checks if the offset is encrypted.""" return self.cryptid != 0 and self.cryptoff <= offset < self.cryptoff + self.cryptsize LoadCommand.registerFactory(LC_ENCRYPTION_INFO, EncryptionInfoCommand) @patch class MachO_EncryptionPatches(MachO): """This patch defines a single convenient function :meth:`encrypted` which can check if a file offset is encrypted.""" def encrypted(self, fileoff): """Checks if the file offset is in any encrypted region.""" encCmds = self.loadCommands.all('className', 'EncryptionInfoCommand') return any(lc.encrypted(fileoff) for lc in encCmds)
""" 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) def __str__(self): return "<Dylib {!r}>".format(self.name) for i in (LC_LOAD_DYLIB, LC_ID_DYLIB, LC_LOAD_WEAK_DYLIB, LC_REEXPORT_DYLIB, LC_LAZY_LOAD_DYLIB, LC_LOAD_UPWARD_DYLIB): LoadCommand.registerFactory(i, DylibCommand) @patch class MachO_FromLibord(MachO): """This patch defines a single convenient function :meth:`dylibFromLibord` which can convert a library ordinal to a :class:`DylibCommand` object.""" def dylibFromLibord(self, libord): """Converts library ordinal to a :class:`DylibCommand` object. Returns ``None`` if the input is invalid.""" if libord < 0: return None lcs = self.loadCommands if not libord:
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)) def indirectSymbols(self, start, count, machO): '''Get symbol indices from the indirect symbol table, given the *start* index and the *count* of indices to retrieve.''' offset = self.indirectsymoff + start * 4 + machO.origin return peekPrimitives(machO.file, 'L', count, machO.endian, machO.is64bit, position=offset) LoadCommand.registerFactory(LC_DYSYMTAB, DySymtabCommand)
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) LoadCommand.registerFactory(LC_SYMTAB, SymtabCommand)
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) LoadCommand.registerFactory(LC_SYMTAB, SymtabCommand)
.. attribute:: minVersion The compatibility version of the dynamic library. """ 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) def __str__(self): return "<Dylib {!r}>".format(self.name) for i in (LC_LOAD_DYLIB, LC_ID_DYLIB, LC_LOAD_WEAK_DYLIB, LC_REEXPORT_DYLIB, LC_LAZY_LOAD_DYLIB, LC_LOAD_UPWARD_DYLIB): LoadCommand.registerFactory(i, DylibCommand) @patch class MachO_FromLibord(MachO): """This patch defines a single convenient function :meth:`dylibFromLibord` which can convert a library ordinal to a :class:`DylibCommand` object.""" def dylibFromLibord(self, libord): """Converts library ordinal to a :class:`DylibCommand` object. Returns ``None`` if the input is invalid.""" if libord < 0: return None lcs = self.loadCommands if not libord:
allSegments = machO.loadCommands.all('className', type(self).__name__) if not all(hasattr(seg, 'vmaddr') for seg in allSegments): return True # now analyze the sections. if not self._hasAnalyzedSections: self._analyzeSections(machO) def __str__(self): return "<Segment: {} [{}]>".format(self.segname, ', '.join(map(str, self._sections.values()))) LoadCommand.registerFactory(LC_SEGMENT, SegmentCommand) LoadCommand.registerFactory(LC_SEGMENT_64, SegmentCommand) @patch class MachO_SegmentCommandPatches(MachO): """This patch to the :class:`~macho.macho.MachO` class defines several methods that operate over all segments.""" def segment(self, segname): """Find a :class:`SegmentCommand` with the specified *segname*.""" for segment in self.loadCommands.all('className', 'SegmentCommand'): if segment.segname == segname: return segment return None
The size of this encryption region. .. attribute:: cryptid The method of encryption. """ def analyze(self, machO): (self.cryptoff, self.cryptsize, self.cryptid) = machO.readFormatStruct('3L') def __str__(self): return "<EncryptionInfo {}/{:x}>".format(self.cryptid, self.cryptoff) def encrypted(self, offset): """Checks if the offset is encrypted.""" return self.cryptid != 0 and self.cryptoff <= offset < self.cryptoff + self.cryptsize LoadCommand.registerFactory(LC_ENCRYPTION_INFO, EncryptionInfoCommand) @patch class MachO_EncryptionPatches(MachO): """This patch defines a single convenient function :meth:`encrypted` which can check if a file offset is encrypted.""" def encrypted(self, fileoff): """Checks if the file offset is in any encrypted region.""" encCmds = self.loadCommands.all('className', 'EncryptionInfoCommand') return any(lc.encrypted(fileoff) for lc in encCmds)
yield (r_symbolnum, r_address) 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)) def indirectSymbols(self, start, count, machO): '''Get symbol indices from the indirect symbol table, given the *start* index and the *count* of indices to retrieve.''' offset = self.indirectsymoff + start * 4 + machO.origin return peekPrimitives(machO.file, 'L', count, machO.endian, machO.is64bit, position=offset) LoadCommand.registerFactory(LC_DYSYMTAB, DySymtabCommand)
# make sure all segments are ready allSegments = machO.loadCommands.all('className', type(self).__name__) if not all(hasattr(seg, 'vmaddr') for seg in allSegments): return True # now analyze the sections. if not self._hasAnalyzedSections: self._analyzeSections(machO) def __str__(self): return "<Segment: {} [{}]>".format( self.segname, ', '.join(map(str, list(self._sections.values())))) LoadCommand.registerFactory(LC_SEGMENT, SegmentCommand) LoadCommand.registerFactory(LC_SEGMENT_64, SegmentCommand) @patch class MachO_SegmentCommandPatches(MachO): """This patch to the :class:`~macho.macho.MachO` class defines several methods that operate over all segments.""" def segment(self, segname): """Find a :class:`SegmentCommand` with the specified *segname*.""" for segment in self.loadCommands.all('className', 'SegmentCommand'): if segment.segname == segname: return segment return None def allSections(self, idtype, sectid):