def readExports(self) -> None: """ Gets export symbols """ self.exports = [] # try to get exports by LC_DYLD_INFO dyldInfo = self.machoFile.getLoadCommand( (MachO.LoadCommands.LC_DYLD_INFO, MachO.LoadCommands.LC_DYLD_INFO_ONLY)) if dyldInfo: self.exports = MachO.TrieParser(dyldInfo.exportData).parse() else: # try to get exports by LC_DYLD_EXPORTS_TRIE exportsTrie = self.machoFile.getLoadCommand( MachO.LoadCommands.LC_DYLD_EXPORTS_TRIE) if exportsTrie: self.exports = MachO.TrieParser( exportsTrie.linkeditData).parse() else: logging.warning("Unable to get export data.") # remove any non ReExport symbols reExportDeps = [] deps = self.machoFile.getLoadCommand( (MachO.LoadCommands.LC_LOAD_DYLIB, MachO.LoadCommands.LC_LOAD_WEAK_DYLIB, MachO.LoadCommands.LC_REEXPORT_DYLIB, MachO.LoadCommands.LC_LOAD_UPWARD_DYLIB), multiple=True) if deps: depIndex = 0 for dep in deps: depIndex += 1 if dep.cmd == MachO.LoadCommands.LC_REEXPORT_DYLIB: reExportDeps.append(depIndex) def isReExport(entry: MachO.TrieEntry) -> bool: if (entry.flags & MachO.Export.EXPORT_SYMBOL_FLAGS_KIND_MASK ) != MachO.Export.EXPORT_SYMBOL_FLAGS_KIND_REGULAR: return True if (entry.flags & MachO.Export.EXPORT_SYMBOL_FLAGS_REEXPORT) == 0: return True if entry.other in reExportDeps: return True return False self.exports = [ export for export in self.exports if isReExport(export) ] pass
def lookupSymbol(self, addr: int) -> bytes: """ Given the VMAddress of an exported function, this method will return its symbol name. """ if addr in self.symbolCache: return self.symbolCache[addr] # find the image with the address and cache its exports. for image in self.imageCache: if image.containsAddr(addr): dyldInfo = image.getLoadCommand( (MachO.LoadCommands.LC_DYLD_INFO, MachO.LoadCommands.LC_DYLD_INFO_ONLY)) dyldInfo.loadData() imageTextSeg = image.getSegment(b"__TEXT\x00") exports = MachO.TrieParser(dyldInfo.exportData).parse() for export in exports: exportAddr = imageTextSeg.vmaddr + export.address self.symbolCache[exportAddr] = export.name break # look for the symbol again if addr in self.symbolCache: return self.symbolCache[addr] else: return None
def readExports(self) -> None: """ Gets export symbols """ exportData = self.machoFile.getLoadCommand( (MachO.LoadCommands.LC_DYLD_INFO, MachO.LoadCommands.LC_DYLD_INFO_ONLY)).exportData self.exports = MachO.TrieParser(exportData).parse() # remove any non ReExport symbols reExportDeps = [] deps = self.machoFile.getLoadCommand( (MachO.LoadCommands.LC_LOAD_DYLIB, MachO.LoadCommands.LC_LOAD_WEAK_DYLIB, MachO.LoadCommands.LC_REEXPORT_DYLIB, MachO.LoadCommands.LC_LOAD_UPWARD_DYLIB), multiple=True) if deps: depIndex = 0 for dep in deps: depIndex += 1 if dep.cmd == MachO.LoadCommands.LC_REEXPORT_DYLIB: reExportDeps.append(depIndex) def isReExport(entry: MachO.TrieEntry) -> bool: if (entry.flags & MachO.Export.EXPORT_SYMBOL_FLAGS_KIND_MASK ) != MachO.Export.EXPORT_SYMBOL_FLAGS_KIND_REGULAR: return True if (entry.flags & MachO.Export.EXPORT_SYMBOL_FLAGS_REEXPORT) == 0: return True if entry.other in reExportDeps: return True return False self.exports = [ export for export in self.exports if isReExport(export) ] pass