Exemplo n.º 1
0
    def copyExportedSymbols(self, newLinkedit: bytearray) -> None:
        self.statusBar.update("Copy Exported Symbols")

        self.newExportedSymbolsStartIndex = self.symbolCtx.symbolsSize
        self.newExportedSymbolCount = 0

        if not self.dynSymTabCmd:
            self.logger.warning("Unable to copy exported symbols.")
            return

        # Copy entries and symbols
        entriesStart = self.dynSymTabCmd.iextdefsym
        entriesEnd = entriesStart + self.dynSymTabCmd.nextdefsym

        symbolStrOff = self.symTabCmd.stroff

        for entryIndex in range(entriesStart, entriesEnd):
            entryOff = self.symTabCmd.symoff + (entryIndex * nlist_64.SIZE)
            entry = nlist_64(self.dyldCtx.file, entryOff)

            nameOff = symbolStrOff + entry.n_strx
            name = self.dyldCtx.readString(nameOff)

            # update variables and copy
            self.oldToNewSymbolIndexes[entryIndex] = self.symbolCtx.symbolsSize

            self.newExportedSymbolCount += 1
            self.symbolCtx.symbolsSize += 1

            entry.n_strx = self.symbolCtx.addString(name)
            newLinkedit.extend(entry)

            self.statusBar.update()
        pass
Exemplo n.º 2
0
    def copyLocalSymbols(self, newLinkedit: bytearray) -> None:
        self.statusBar.update(status="Copy Local Symbols")

        symbolsCache = self.dyldCtx.getSymbolsCache()
        localSymbolsInfo = dyld_cache_local_symbols_info(
            symbolsCache.file, symbolsCache.header.localSymbolsOffset)

        entryStruct = self.getLocalSymsEntryStruct(symbolsCache,
                                                   localSymbolsInfo)
        if not entryStruct:
            self.logger.error("Unable to get local symbol entries structure.")
            return

        dylibOffset = (self.machoCtx.segments[b"__TEXT"].seg.vmaddr -
                       self.dyldCtx.header.sharedRegionStart)

        localSymbolsEntriesInfo = None
        for i in range(localSymbolsInfo.entriesCount):
            entryOff = (i * entryStruct.SIZE)
            entryOff += localSymbolsInfo._fileOff_ + localSymbolsInfo.entriesOffset

            entry = entryStruct(symbolsCache.file, entryOff)
            if entry.dylibOffset == dylibOffset:
                localSymbolsEntriesInfo = entry
                break

        if not localSymbolsEntriesInfo:
            self.logger.warning("Unable to find local symbol entries.")
            return

        self.newLocalSymbolsStartIndex = self.symbolCtx.symbolsSize
        self.newLocalSymbolCount = 0

        # copy local symbols and their strings
        entriesStart = (
            localSymbolsInfo._fileOff_ + localSymbolsInfo.nlistOffset +
            (localSymbolsEntriesInfo.nlistStartIndex * nlist_64.SIZE))
        entriesEnd = (entriesStart +
                      (localSymbolsEntriesInfo.nlistCount * nlist_64.SIZE))

        symbolStrOff = localSymbolsInfo._fileOff_ + localSymbolsInfo.stringsOffset

        for offset in range(entriesStart, entriesEnd, nlist_64.SIZE):
            symbolEnt = nlist_64(symbolsCache.file, offset)
            name = symbolsCache.readString(symbolStrOff + symbolEnt.n_strx)

            # copy data
            self.newLocalSymbolCount += 1
            self.symbolCtx.symbolsSize += 1

            symbolEnt.n_strx = self.symbolCtx.addString(name)
            newLinkedit.extend(symbolEnt)

            self.statusBar.update()
        pass
Exemplo n.º 3
0
    def copyLocalSymbols(self, newLinkedit: bytearray) -> None:
        self.statusBar.update(status="Copy Local Symbols")

        localSymbolsInfo = dyld_cache_local_symbols_info(
            self.dyldCtx.file, self.dyldCtx.header.localSymbolsOffset)

        localSymbolsEntriesInfo = None
        for i in range(localSymbolsInfo.entriesCount):
            entryOff = (i * dyld_cache_local_symbols_entry.SIZE)
            entryOff += localSymbolsInfo._fileOff_ + localSymbolsInfo.entriesOffset

            entry = dyld_cache_local_symbols_entry(self.dyldCtx.file, entryOff)
            if entry.dylibOffset == self.machoCtx.fileOffset:
                localSymbolsEntriesInfo = entry
                break

        if not localSymbolsEntriesInfo:
            self.logger.warning("Unable to find local symbol entries.")
            return

        self.newLocalSymbolsStartIndex = self.symbolCtx.symbolsSize
        self.newLocalSymbolCount = 0

        # copy local symbols and their strings
        entriesStart = (
            localSymbolsInfo._fileOff_ + localSymbolsInfo.nlistOffset +
            (localSymbolsEntriesInfo.nlistStartIndex * nlist_64.SIZE))
        entriesEnd = (entriesStart +
                      (localSymbolsEntriesInfo.nlistCount * nlist_64.SIZE))

        symbolStrOff = localSymbolsInfo._fileOff_ + localSymbolsInfo.stringsOffset

        for offset in range(entriesStart, entriesEnd, nlist_64.SIZE):
            symbolEnt = nlist_64(self.dyldCtx.file, offset)
            name = self.dyldCtx.readString(symbolStrOff + symbolEnt.n_strx)

            # copy data
            self.newLocalSymbolCount += 1
            self.symbolCtx.symbolsSize += 1

            symbolEnt.n_strx = self.symbolCtx.addString(name)
            newLinkedit.extend(symbolEnt)

            self.statusBar.update()
        pass
Exemplo n.º 4
0
    def copyImportedSymbols(self, newLinkedit: bytearray) -> None:
        self.statusBar.update(status="Copy Imported Symbols")

        self.newImportedSymbolsStartIndex = self.symbolCtx.symbolsSize
        self.newImportedSymbolCount = 0

        if not self.dynSymTabCmd:
            self.logger.warning("Unable to copy imported symbols")
            return

        # Copy entries and symbols
        entriesStart = self.dynSymTabCmd.iundefsym
        entriesEnd = entriesStart + self.dynSymTabCmd.nundefsym

        symbolStrOff = self.symTabCmd.stroff

        for entryIndex in range(entriesStart, entriesEnd):
            entryOff = self.symTabCmd.symoff + (entryIndex * nlist_64.SIZE)
            entry = nlist_64(self.dyldCtx.file, entryOff)

            nameOff = symbolStrOff + entry.n_strx
            name = self.dyldCtx.readString(nameOff)

            # update variables and copy
            self.oldToNewSymbolIndexes[entryIndex] = self.symbolCtx.symbolsSize

            self.newImportedSymbolCount += 1
            self.symbolCtx.symbolsSize += 1

            entry.n_strx = self.symbolCtx.addString(name)
            newLinkedit.extend(entry)

            self.statusBar.update()

        # make room for the indirect symbol entries that may
        # be fixed in stub_fixer
        if self.redactedSymbolCount:
            newLinkedit.extend(b"\x00" *
                               (self.redactedSymbolCount * nlist_64.SIZE))
        pass
Exemplo n.º 5
0
    def addRedactedSymbol(self, newLinkedit: bytearray) -> None:
        """Adds a redacted symbol entry if needed.

			Some images have indirect symbols that point to the zeroth
		symbol entry. This is probaby a stripped symbol and is basically
		unrecoverable.

		This provides a "redacted" entry for those special cases so that
		some disassemblers don't name functions incorrectly.
		"""

        self.statusBar.update(status="Search Redacted Symbols")

        self.redactedSymbolCount = 0

        indirectStart = self.dynSymTabCmd.indirectsymoff
        indirectEnd = indirectStart + (self.dynSymTabCmd.nindirectsyms * 4)
        for offset in range(indirectStart, indirectEnd, 4):
            symbolIndex = self.dyldCtx.getBytes(offset, 4)
            if symbolIndex == b"\x00\x00\x00\x00":
                self.redactedSymbolCount += 1

            self.statusBar.update()
            pass

        if self.redactedSymbolCount:
            stringIndex = self.symbolCtx.addString(b"<redacted>\x00")
            self.symbolCtx.symbolsSize += 1

            symbolEntry = nlist_64()
            symbolEntry.n_strx = stringIndex
            symbolEntry.n_type = 1
            newLinkedit.extend(symbolEntry)

            self.extractionCtx.hasRedactedIndirect = True
        pass