Ejemplo n.º 1
0
def _extractImage(dyldFile: BufferedReader, dyldCtx: DyldContext,
                  image: dyld_cache_image_info, outputPath: str) -> None:
    """Extract an image and save it.

	The order of converters is essentally a reverse of Apple's SharedCacheBuilder
	"""

    logger = logging.getLogger()

    # get a a writable copy of the MachOContext
    machoFile = mmap.mmap(dyldFile.fileno(), 0, access=mmap.ACCESS_COPY)
    machoCtx = MachOContext(machoFile, dyldCtx.convertAddr(image.address))

    statusBar = progressbar.ProgressBar(
        prefix="{variables.unit} >> {variables.status} :: [",
        variables={
            "unit": "--",
            "status": "--"
        },
        widgets=[progressbar.widgets.AnimatedMarker(), "]"],
        redirect_stdout=True)

    extractionCtx = ExtractionContext(dyldCtx, machoCtx, statusBar, logger)

    slide_info.processSlideInfo(extractionCtx)
    linkedit_optimizer.optimizeLinkedit(extractionCtx)
    stub_fixer.fixStubs(extractionCtx)
    objc_fixer.fixObjC(extractionCtx)

    macho_offset.optimizeOffsets(extractionCtx)

    # Write the MachO file
    with open(outputPath, "wb") as outFile:
        statusBar.update(unit="Extractor", status="Writing file")

        newMachoCtx = extractionCtx.machoCtx

        # get the size of the file
        linkEditSeg = newMachoCtx.segments[b"__LINKEDIT"].seg
        fileSize = linkEditSeg.fileoff + linkEditSeg.filesize

        newMachoCtx.file.seek(0)
        outFile.write(newMachoCtx.file.read(fileSize))

    statusBar.update(unit="Extractor", status="Done")
def _imageRunner(dyldPath: str, imageIndex: int) -> None:
    level = logging.DEBUG
    loggingStream = io.StringIO()

    # setup logging
    logger = logging.getLogger(f"Worker: {imageIndex}")
    handler = logging.StreamHandler(loggingStream)
    formatter = logging.Formatter(
        fmt=
        "{asctime}:{msecs:03.0f} [{levelname:^9}] {filename}:{lineno:d} : {message}",  # noqa
        datefmt="%H:%M:%S",
        style="{",
    )

    handler.setFormatter(formatter)
    logger.addHandler(handler)
    logger.setLevel(level)

    # process the image
    with open(dyldPath, "rb") as f:
        dyldFile = mmap.mmap(f.fileno(), 0, access=mmap.ACCESS_READ)
        dyldCtx = DyldContext(dyldFile)
        imageOffset = dyldCtx.convertAddr(dyldCtx.images[imageIndex].address)

        machoFile = mmap.mmap(f.fileno(), 0, access=mmap.ACCESS_COPY)
        machoCtx = MachOContext(machoFile, imageOffset)

        extractionCtx = ExtractionContext(dyldCtx, machoCtx,
                                          _DummyProgressBar(), logger)

        try:
            linkedit_optimizer.optimizeLinkedit(extractionCtx)
            stub_fixer.fixStubs(extractionCtx)
            objc_fixer.fixObjC(extractionCtx)
        except Exception as e:
            logger.exception(e)
        pass

    # cleanup
    handler.close()
    return loggingStream.getvalue()
Ejemplo n.º 3
0
def runForAllImages(dyldFile: BufferedReader,
                    dyldCtx: DyldContext,
                    statusBar: progressbar.ProgressBar,
                    logger: logging.Logger,
                    startIndex: int = 0,
                    stopIndex: int = -1) -> None:
    total = dyldCtx.header.imagesCount

    for index, imageData in enumerate(dyldCtx.images[startIndex:], startIndex):
        if index == stopIndex:
            break

        # TODO: Imp sub caches
        imageOffset = dyldCtx.convertAddr(imageData.address)
        imagePath = dyldCtx.readString(imageData.pathFileOffset)[0:-1]
        imagePath = imagePath.decode("utf-8")
        imageName = imagePath.split("/")[-1]

        # Make a writable copy of the dyld file
        machoFile = mmap.mmap(dyldFile.fileno(), 0, access=mmap.ACCESS_COPY)
        machoCtx = MachOContext(machoFile, imageOffset)

        extractionCtx = ExtractionContext(dyldCtx, machoCtx, statusBar, logger)

        # Test space start

        slide_info.processSlideInfo(extractionCtx)
        linkedit_optimizer.optimizeLinkedit(extractionCtx)
        stub_fixer.fixStubs(extractionCtx)
        objc_fixer.fixObjC(extractionCtx)
        macho_offset.optimizeOffsets(extractionCtx)

        # Test space end

        logger.info(f"processed: ({index + 1}/{total}): {imageName}")
        pass

    statusBar.update(unit="Extractor", status="Done")
    pass
Ejemplo n.º 4
0
def _imageRunner(dyldPath: str, imageIndex: int) -> None:
    level = logging.DEBUG
    loggingStream = io.StringIO()

    # setup logging
    logger = logging.getLogger(f"Worker: {imageIndex}")
    handler = logging.StreamHandler(loggingStream)
    formatter = logging.Formatter(
        fmt=
        "{asctime}:{msecs:03.0f} [{levelname:^9}] {filename}:{lineno:d} : {message}",  # noqa
        datefmt="%H:%M:%S",
        style="{",
    )

    handler.setFormatter(formatter)
    logger.addHandler(handler)
    logger.setLevel(level)

    # process the image
    with open(dyldPath, "rb") as f:
        dyldCtx = DyldContext(f)

        subCacheFiles: List[BinaryIO] = []
        try:
            # add sub caches if there are any
            if dyldCtx.hasSubCaches():
                subCacheFileCtxs, subCacheFiles = _openSubCaches(
                    dyldPath, dyldCtx.header.numSubCaches)
                dyldCtx.addSubCaches(subCacheFileCtxs)
                pass

            machoOffset, context = dyldCtx.convertAddr(
                dyldCtx.images[imageIndex].address)
            machoCtx = MachOContext(context.fileObject, machoOffset, True)

            # Add sub caches if necessary
            if dyldCtx.hasSubCaches():
                mappings = dyldCtx.mappings
                mainFileMap = next((mapping[0] for mapping in mappings
                                    if mapping[1] == context))
                machoCtx.addSubfiles(mainFileMap,
                                     ((m, ctx.makeCopy(copyMode=True))
                                      for m, ctx in mappings))
                pass

            extractionCtx = ExtractionContext(dyldCtx, machoCtx,
                                              _DummyProgressBar(), logger)

            # TODO: implement a way to select convertors
            slide_info.processSlideInfo(extractionCtx)
            linkedit_optimizer.optimizeLinkedit(extractionCtx)
            stub_fixer.fixStubs(extractionCtx)
            objc_fixer.fixObjC(extractionCtx)
            macho_offset.optimizeOffsets(extractionCtx)

        except Exception as e:
            logger.exception(e)
            pass

        finally:
            for file in subCacheFiles:
                file.close()
                pass
            pass
        pass

    # cleanup
    handler.close()
    return loggingStream.getvalue()