Esempio n. 1
0
    def get_content(self, partition):
        """Extract the content of the file.

        This method works by extracting the $DATA attribute."""
        if self.is_ghost:
            logging.error(u'Cannot restore ghost file {}'.format(self))
            return None

        image = DiskScanner.get_image(partition.scanner)
        dump = sectors(image, File.get_offset(self), FILE_size)
        parsed = parse_file_record(dump)

        if not parsed['valid'] or 'attributes' not in parsed:
            logging.error(u'Invalid MFT entry for {}'.format(self))
            return None
        attrs = parsed['attributes']
        if ('$ATTRIBUTE_LIST' in attrs and
                partition.sec_per_clus is not None):
            _integrate_attribute_list(parsed, partition, image)
        if '$DATA' not in attrs:
            attrs['$DATA'] = []
        datas = [d for d in attrs['$DATA'] if d['name'] == self.ads]
        if not len(datas):
            if not self.is_directory:
                logging.error(u'Cannot restore $DATA attribute(s) '
                              'for {}'.format(self))
            return None

        # TODO implemented compressed attributes
        for d in datas:
            if d['flags'] & 0x01:
                logging.error(u'Cannot restore compressed $DATA attribute(s) '
                              'for {}'.format(self))
                return None
            elif d['flags'] & 0x4000:
                logging.warning(u'Found encrypted $DATA attribute(s) '
                                'for {}'.format(self))

        # Handle resident file content
        if len(datas) == 1 and not datas[0]['non_resident']:
            single = datas[0]
            start = single['dump_offset'] + single['content_off']
            end = start + single['content_size']
            content = dump[start:end]
            return str(content)
        else:
            if partition.sec_per_clus is None:
                logging.error(u'Cannot restore non-resident $DATA '
                              'attribute(s) for {}'.format(self))
                return None
            non_resident = sorted(
                (d for d in attrs['$DATA'] if d['non_resident']),
                key=lambda x: x['start_VCN']
            )
            if len(non_resident) != len(datas):
                logging.warning(
                    u'Found leftover resident $DATA attributes for '
                    '{}'.format(self)
                )
            return self.content_iterator(partition, image, non_resident)
Esempio n. 2
0
    def get_content(self, partition):
        """Extract the content of the file.

        This method works by extracting the $DATA attribute."""
        if self.is_ghost:
            logging.error(u'Cannot restore ghost file {}'.format(self))
            return None

        image = DiskScanner.get_image(partition.scanner)
        dump = sectors(image, File.get_offset(self), FILE_size)
        parsed = parse_file_record(dump)

        if not parsed['valid'] or 'attributes' not in parsed:
            logging.error(u'Invalid MFT entry for {}'.format(self))
            return None
        attrs = parsed['attributes']
        if ('$ATTRIBUTE_LIST' in attrs and
                partition.sec_per_clus is not None):
            _integrate_attribute_list(parsed, partition, image)
        if '$DATA' not in attrs:
            attrs['$DATA'] = []
        datas = [d for d in attrs['$DATA'] if d['name'] == self.ads]
        if not len(datas):
            if not self.is_directory:
                logging.error(u'Cannot restore $DATA attribute(s) '
                              'for {}'.format(self))
            return None

        # TODO implemented compressed attributes
        for d in datas:
            if d['flags'] & 0x01:
                logging.error(u'Cannot restore compressed $DATA attribute(s) '
                              'for {}'.format(self))
                return None
            elif d['flags'] & 0x4000:
                logging.warning(u'Found encrypted $DATA attribute(s) '
                                'for {}'.format(self))

        # Handle resident file content
        if len(datas) == 1 and not datas[0]['non_resident']:
            single = datas[0]
            start = single['dump_offset'] + single['content_off']
            end = start + single['content_size']
            content = dump[start:end]
            return str(content)
        else:
            if partition.sec_per_clus is None:
                logging.error(u'Cannot restore non-resident $DATA '
                              'attribute(s) for {}'.format(self))
                return None
            non_resident = sorted(
                (d for d in attrs['$DATA'] if d['non_resident']),
                key=lambda x: x['start_VCN']
            )
            if len(non_resident) != len(datas):
                logging.warning(
                    u'Found leftover resident $DATA attributes for '
                    '{}'.format(self)
                )
            return self.content_iterator(partition, image, non_resident)
Esempio n. 3
0
    def __init__(self, parsed, offset, is_ghost=False, ads=''):
        index = parsed['record_n']
        ads_suffix = ':' + ads if ads != '' else ads
        if ads != '':
            index = unicode(index) + ads_suffix
        attrs = parsed['attributes']
        filenames = attrs['$FILE_NAME']
        datas = attrs.get('$DATA', [])

        size = None
        for attr in datas:
            if attr['name'] == ads:
                if 'real_size' in attr:
                    size = attr['real_size']
                elif not attr['non_resident']:
                    size = attr['content_size']
                break

        filtered = [
            f for f in filenames if f.has_key('content') and
            f['content'] is not None and
            f['content']['name_length'] > 0 and
            f['content']['name'] is not None
        ]
        name = best_name([
            (f['content']['namespace'], f['content']['name'] + ads_suffix)
            for f in filtered
        ])
        hasname = name is not None

        if not hasname:
            name = 'File_%s' % index

        is_dir = (parsed['flags'] & 0x02) > 0 and not len(ads)
        is_del = (parsed['flags'] & 0x01) == 0
        File.__init__(self, index, name, size, is_dir, is_del, is_ghost)
        # Additional attributes
        if hasname:
            first = filtered[0]['content']
            parent_id = first['parent_entry']
            File.set_parent(self, parent_id)
            File.set_offset(self, offset)
            File.set_mac(
                self, first['modification_time'],
                first['access_time'], first['creation_time']
            )
        self.ads = ads
Esempio n. 4
0
    def __init__(self, parsed, offset, is_ghost=False, ads=''):
        index = parsed['record_n']
        ads_suffix = ':' + ads if ads != '' else ads
        if ads != '':
            index = unicode(index) + ads_suffix
        attrs = parsed['attributes']
        filenames = attrs['$FILE_NAME']
        datas = attrs['$DATA'] if '$DATA' in attrs else []

        size = None
        for attr in datas:
            if attr['name'] == ads:
                if 'real_size' in attr:
                    size = attr['real_size']
                elif not attr['non_resident']:
                    size = attr['content_size']
                break

        filtered = [
            f for f in filenames if f.has_key('content') and
            f['content'] is not None and
            f['content']['name_length'] > 0 and
            f['content']['name'] is not None
        ]
        name = best_name([
            (f['content']['namespace'], f['content']['name'] + ads_suffix)
            for f in filtered
        ])
        hasname = name is not None

        if not hasname:
            name = 'File_%s' % index

        is_dir = (parsed['flags'] & 0x02) > 0 and not len(ads)
        is_del = (parsed['flags'] & 0x01) == 0
        File.__init__(self, index, name, size, is_dir, is_del, is_ghost)
        # Additional attributes
        if hasname:
            first = filtered[0]['content']
            parent_id = first['parent_entry']
            File.set_parent(self, parent_id)
            File.set_offset(self, offset)
            File.set_mac(
                self, first['modification_time'],
                first['access_time'], first['creation_time']
            )
        self.ads = ads