Пример #1
0
def diff(feeder1, feeder2):
    tmpdir = get_temporary_directory().name

    fifo1_path = os.path.join(tmpdir, 'fifo1')
    fifo2_path = os.path.join(tmpdir, 'fifo2')
    with FIFOFeeder(feeder1, fifo1_path) as fifo1, \
            FIFOFeeder(feeder2, fifo2_path) as fifo2:
        return run_diff(fifo1_path, fifo2_path, fifo1.end_nl_q, fifo2.end_nl_q)
Пример #2
0
    def ensure_unpacked(self):
        if hasattr(self, '_members'):
            return

        self._members = collections.OrderedDict()
        self._temp_dir = get_temporary_directory().name

        logger.debug("Extracting %s to %s", self.source.path, self._temp_dir)

        output = subprocess.check_output(
            (
                'unsquashfs',
                '-n',
                '-f',
                '-no',
                '-li',
                '-d',
                '.',
                self.source.path,
            ),
            stderr=subprocess.PIPE,
            cwd=self._temp_dir,
        )

        output = iter(output.decode('utf-8').rstrip('\n').split('\n'))

        # Skip headers
        for _ in iter(functools.partial(next, output), ''):
            pass

        for line in output:
            if not line:
                continue

            try:
                cls = self.MEMBER_CLASS[line[0]]
            except KeyError:
                logger.debug("Unknown squashfs entry: %s", line)
                continue

            try:
                kwargs = cls.parse(line)
            except SquashfsInvalidLineFormat:
                continue

            # Pop to avoid duplicating member name in the key and the value
            member_name = kwargs.pop('member_name')

            self._members[member_name] = (cls, kwargs)

        logger.debug(
            "Extracted %d entries from %s to %s",
            len(self._members),
            self.source.path,
            self._temp_dir,
        )
Пример #3
0
 def path(self):
     if self._path is None:
         logger.debug("Unpacking %s from %s", self._name,
                      self.container.source.name)
         assert self._temp_dir is None
         self._temp_dir = get_temporary_directory()
         with profile('container_extract', self.container):
             self._path = self.container.extract(self._name,
                                                 self._temp_dir.name)
     return self._path
Пример #4
0
def compare_rpm_headers(path1, path2):
    # compare headers
    with get_temporary_directory() as rpmdb_dir:
        rpm.addMacro("_dbpath", rpmdb_dir)
        ts = rpm.TransactionSet()
        ts.setVSFlags(-1)
        header1 = get_rpm_header(path1, ts)
        header2 = get_rpm_header(path2, ts)
    return Difference.from_text(header1,
                                header2,
                                path1,
                                path2,
                                source="header")
Пример #5
0
    def open_archive(self):
        self._members = []
        self._unpacked = os.path.join(
            get_temporary_directory().name,
            os.path.basename(self.source.name),
        )
        self._andmanifest = None
        self._andmanifest_orig = None

        logger.debug("Extracting %s to %s", self.source.name, self._unpacked)

        subprocess.check_call((
            'apktool', 'd', '-k', '-m', '-o', self._unpacked, self.source.path,
        ), shell=False, stderr=None, stdout=subprocess.PIPE)

        for root, _, files in os.walk(self._unpacked):
            current_dir = []

            for filename in files:
                abspath = os.path.join(root, filename)

                # apktool.yml is a file created by apktool and containing
                # metadata information. Rename it to clarify and always make it
                # appear at the beginning of the directory listing for
                # reproducibility.
                if filename == 'apktool.yml':
                    abspath = filter_apk_metadata(
                        abspath,
                        os.path.basename(self.source.name),
                    )
                    relpath = abspath[len(self._unpacked) + 1:]
                    current_dir.insert(0, relpath)
                    continue

                relpath = abspath[len(self._unpacked)+1:]

                if filename == 'AndroidManifest.xml':
                    containing_dir = root[len(self._unpacked)+1:]
                    if containing_dir == 'original':
                        self._andmanifest_orig = relpath
                    if containing_dir == '':
                        self._andmanifest = relpath
                    continue

                current_dir.append(relpath)

            self._members.extend(current_dir)

        return self
Пример #6
0
    def recognizes(cls, file):
        if binwalk is None:
            return False

        if not super().recognizes(file):
            return False

        # RPM files are .cpio, but let's always leave it to the RPM comparator.
        # This avoids the RpmFile > BinWalkFile > CpioFile > RpmFile circular
        # ordering dependency.
        if file.container and isinstance(file.container.source, RpmFile):
            return False

        # Don't recurse; binwalk has already found everything
        if isinstance(file.container, cls.CONTAINER_CLASS):
            return False

        unpacked = get_temporary_directory(prefix='binwalk')
        logger.debug("Extracting %s to %s", file.path, unpacked.name)

        binwalk.scan(
            file.path,
            dd='cpio:cpio',
            carve=True,
            quiet=True,
            signature=True,
            directory=unpacked.name,
        )

        members = {
            '{} file embedded at offset {}'.format(
                os.path.splitext(x)[1],
                os.path.basename(os.path.splitext(x)[0]),
            ): x
            for x in glob.glob(os.path.join(unpacked.name, '*/*'))
        }

        logger.debug("Found %d embedded member(s)", len(members))

        if not members:
            unpacked.cleanup()
            return False

        file._members = members
        file._unpacked = unpacked

        return True
Пример #7
0
    def open_archive(self):
        self._members = []
        self._unpacked = get_temporary_directory()

        logger.debug(
            "Extracting Android boot image to %s", self._unpacked.name
        )

        subprocess.check_call(
            ['abootimg', '-x', os.path.abspath(self.source.path)],
            cwd=self._unpacked.name,
            stdout=subprocess.PIPE,
        )

        self._members = sorted(os.listdir(self._unpacked.name))

        return self
Пример #8
0
    def ensure_unpacked(self):
        if hasattr(self, '_members'):
            return

        tmpdir = get_temporary_directory().name
        self._members = collections.OrderedDict()

        logger.debug("Extracting %s to %s", self.source.path, tmpdir)

        with libarchive.file_reader(self.source.path) as archive:
            for idx, entry in enumerate(archive):
                # Always skip directories
                if entry.isdir:
                    continue

                # Save extracting excluded files
                if any_excluded(entry.pathname):
                    continue

                # Keep directory sizes small. could be improved but should be
                # good enough for "ordinary" large archives.
                dst = os.path.join(tmpdir, str(idx // 4096), str(idx % 4096))
                root, ext = os.path.splitext(entry.pathname)
                dst += ext
                # Maintain a mapping of archive path to the extracted path,
                # avoiding the need to sanitise filenames.
                self._members[entry.pathname] = dst

                logger.debug("Extracting %s to %s", entry.pathname, dst)

                os.makedirs(os.path.dirname(dst), exist_ok=True)
                try:
                    with open(dst, 'wb') as f:
                        for block in entry.get_blocks():
                            f.write(block)
                except Exception as exc:
                    raise ContainerExtractionError(entry.pathname, exc)

        logger.debug(
            "Extracted %d entries from %s to %s",
            len(self._members),
            self.source.path,
            tmpdir,
        )
Пример #9
0
 def fn(self):
     if not hasattr(fn, '_temp_dir'):
         fn._temp_dir = get_temporary_directory('binwalk').name
     return fn._temp_dir