Exemplo n.º 1
0
    def parse(self, blob):

        # sanity check
        nt = namedtuple('PfsHeaderTuple', ['tag', 'hdr_ver', 'payload_size'])
        try:
            pfs_hdr = nt._make(
                struct.unpack_from(PfsFile.PFS_HEADER, blob, 0x0))
        except struct.error as e:
            raise RuntimeError(str(e))
        if pfs_hdr.tag != b'PFS.HDR.':
            raise RuntimeError('Not a PFS header')
        if pfs_hdr.hdr_ver != 1:
            raise RuntimeError('PFS header version %i unsupported' %
                               pfs_hdr.hdr_ver)

        # parse sections
        offset = struct.calcsize(PfsFile.PFS_HEADER)
        while offset < len(blob) - struct.calcsize(PfsFile.PFS_FOOTER):

            # parse the section
            nt = namedtuple('PfsHeaderSection', [
                'guid', 'hdr_ver', 'ver_type', 'version', 'reserved',
                'data_sz', 'data_sig_sz', 'metadata_sz', 'metadata_sig_sz'
            ])
            try:
                pfs_sect = nt._make(
                    struct.unpack_from(PfsFile.PFS_SECTION, blob, offset))
            except struct.error as e:
                raise RuntimeError(str(e))
            if pfs_sect.hdr_ver != 1:
                raise RuntimeError('PFS section version %i unsupported' %
                                   pfs_hdr.hdr_ver)
            offset += struct.calcsize(PfsFile.PFS_SECTION)

            # parse the data and ignore the rest
            shard = ComponentShard()
            shard.set_blob(blob[offset:offset + pfs_sect.data_sz])
            shard.guid = str(uuid.UUID(bytes_le=pfs_sect.guid))
            if shard.guid == 'fd041960-0dc8-4b9f-8225-bba9e37c71e0':
                self._parse_info(shard.blob)
            elif shard.guid == '233ae3fb-da68-4fd4-92cb-a6229a611d6f':
                self._parse_model(shard.blob)
            else:
                self.shards.append(shard)

            # advance to the next section
            offset += pfs_sect.data_sz
            offset += pfs_sect.data_sig_sz
            offset += pfs_sect.metadata_sz
            offset += pfs_sect.metadata_sig_sz

        # the INFO structure is typically last, so fix up added shards
        for shard in self.shards:
            if shard.guid in self._names:
                shard.name = 'com.dell.' + self._names[shard.guid].replace(
                    ' ', '')
            else:
                shard.name = 'com.dell.' + shard.guid
    def _run_uefi_extract_on_md(self, test, md):

        # remove any old shards we added
        for shard in md.shards:
            if shard.plugin_id == self.id:
                db.session.delete(shard)
        db.session.commit()

        # is this a AMI BIOS with PFAT sections
        if md.blob[8:16] == b'_AMIPFAT':
            pfat = PfatFile(md.blob)
            shards = []
            for shard in pfat.shards:
                shards.append(shard)
                if shard.name == 'com.ami.BIOS_FV_BB.bin':
                    continue
                shards.extend(self._get_shards_for_blob(shard.blob))
            test.add_pass('Found PFAT blob')

        # try with the plain blob (possibly with a capsule header) and
        # then look for a Zlib section (with an optional PFS-prefixed) blob
        else:
            shards = self._get_shards_for_blob(md.blob)
            if not shards:
                for blob in self._find_zlib_sections(md.blob):
                    try:
                        pfs = PfsFile(blob)
                        for shard in pfs.shards:
                            shards.append(shard)
                            shards.extend(self._get_shards_for_blob(
                                shard.blob))
                        test.add_pass('Found PFS in Zlib compressed blob')
                    except RuntimeError as _:
                        shard = ComponentShard(plugin_id=self.id)
                        shard.set_blob(blob)
                        shard.name = 'Zlib'
                        shard.guid = '68b8cc0e-4664-5c7a-9ce3-8ed9b4ffbffb'
                        shards.append(shard)
                        shards.extend(self._get_shards_for_blob(shard.blob))
                        test.add_pass('Found Zlib compressed blob')
            if not shards:
                test.add_pass('No firmware volumes found in {}'.format(
                    md.filename_contents))
                return

        # add shard to component
        for shard in shards:
            shard.plugin_id = self.id
            shard.component_id = md.component_id
            if self.get_setting_bool('uefi_extract_write_shards'):
                shard.save()
            md.shards.append(shard)
Exemplo n.º 3
0
    def _run_chipsec_on_md(self, test, md):

        # remove any old shards we added
        for shard in md.shards:
            if shard.plugin_id == self.id:
                for result in shard.yara_query_results:
                    db.session.delete(result)
                db.session.delete(shard)
        db.session.commit()

        # try first with the plain blob (possibly with a capsule header) and
        # then look for a Zlib section (with an optional PFS-prefixed) blob
        shards = self._get_shards_for_blob(md.blob)
        if not shards:
            for blob in self._find_zlib_sections(md.blob):
                try:
                    pfs = PfsFile(blob)
                    for shard in pfs.shards:
                        shards.append(shard)
                        shards.extend(self._get_shards_for_blob(shard.blob))
                    test.add_pass('Found PFS in Zlib compressed blob')
                except RuntimeError as _:
                    shard = ComponentShard(plugin_id=self.id)
                    shard.set_blob(blob)
                    shard.name = 'Zlib'
                    shard.guid = '68b8cc0e-4664-5c7a-9ce3-8ed9b4ffbffb'
                    shards.append(shard)
                    shards.extend(self._get_shards_for_blob(shard.blob))
                    test.add_pass('Found Zlib compressed blob')
        if not shards:
            test.add_pass('No firmware volumes found in {}'.format(
                md.filename_contents))
            return

        # add shard to component
        for shard in shards:
            shard.plugin_id = self.id
            shard.component_id = md.component_id
            if self.get_setting_bool('chipsec_write_shards'):
                shard.save()
            md.shards.append(shard)
    def parse(self, blob):

        # sanity check
        PfatHeader = namedtuple('PfatHeader', ['size', 'csum', 'tag', 'ctrl'])
        try:
            pfat_hdr = PfatHeader._make(
                struct.unpack_from(PfatFile.PFAT_HEADER, blob, 0x0))
        except struct.error as e:
            raise RuntimeError from e
        if pfat_hdr.tag != b'_AMIPFAT':
            raise RuntimeError('Not a PFAT header')

        # parse the header data which seems to be of the form:
        # "1 /B 4 ;BIOS_FV_BB.bin" where the blockcount is 4 in this example
        section_data = (blob[struct.calcsize(PfatFile.PFAT_HEADER):pfat_hdr.
                             size].decode('utf-8').splitlines())
        PfatSection = namedtuple('PfatSection',
                                 ['flash', 'param', 'blockcnt', 'filename'])
        sections = []
        for entry in section_data[1:]:
            entry_data = entry.split(' ')
            sections.append(
                PfatSection(
                    flash=int(entry_data[0]),
                    param=entry_data[1],
                    blockcnt=int(entry_data[2]),
                    filename=entry_data[3][1:],
                ))

        # parse sections
        offset = pfat_hdr.size
        for section in sections:
            data = b''
            for _ in range(section.blockcnt):
                PfatBlockHeader = namedtuple(
                    'PfatBlockHeader',
                    [
                        'revision',
                        'platform',
                        'unknown0',
                        'unknown1',
                        'flagsz',
                        'datasz',
                        'unknown2',
                        'unknown3',
                        'unknown4',
                    ],
                )
                block_hdr = PfatBlockHeader._make(
                    struct.unpack_from(PfatFile.PFAT_BLOCK_HEADER, blob,
                                       offset))
                block_data_start = (
                    offset + struct.calcsize(PfatFile.PFAT_BLOCK_HEADER) +
                    block_hdr.flagsz)
                data += blob[block_data_start:block_data_start +
                             block_hdr.datasz]
                offset += (struct.calcsize(PfatFile.PFAT_BLOCK_HEADER) +
                           block_hdr.flagsz + block_hdr.datasz +
                           struct.calcsize(PfatFile.PFAT_BLOCK_SIGN))

            # add shard blob
            shard = ComponentShard()
            shard.set_blob(data)
            shard.name = 'com.ami.' + section.filename
            shard.guid = uuid.uuid3(uuid.NAMESPACE_DNS, section.filename)
            self.shards.append(shard)