1

我想编写一个 python 脚本,使用它可以从格式化的驱动器中恢复文件。我知道格式化不会删除驱动器上的数据,而是标记该空间可用于覆盖。那么我怎样才能恢复那些没有被覆盖的文件呢?

4

3 回答 3

1

这样的脚本不太可能工作,因为实现文件处理的 python 函数和 C 库旨在在完整的文件系统上工作。恢复数据所需要做的是从磁盘本身进行原始读取。所以也许你的问题应该是关于这个的。

关于stackoverflow的相关python问题:

于 2014-04-26T18:30:56.673 回答
1

也许问题不在于 python 脚本,而在于文件恢复。如果是这种情况,您需要的策略会根据驱动器的格式和您使用的操作系统而有所不同。

您可以尝试完全不使用 python 来恢复文件,它使用文件系统和操作系统的特定特性,您可以恢复已删除的文件。

于 2020-06-25T13:20:05.943 回答
1

您可以使用 sleuthkit:-

import argparse
import subprocess
import re
import os

TYPECODES = ['\-', 'r', 'd', 'b', 'l', 'p', 's', 'w', 'v']
DESCRIPTIONS = [
    'unknown type',
    'regular file',
    'deleted file',
    'block device',
    'symbolic link',
    'named FIFO',
    'shadow file',
    'whiteout file',
    'TSK virtual file',
]
TYPEDICT = dict(zip((tt.strip('\\') for tt in TYPECODES),  DESCRIPTIONS))

parser = argparse.ArgumentParser(
    description='Recover files from a disk image using SleuthKit',
)
parser.add_argument(
    'image', type=str, nargs=1, help='path to disk image or mount point',
)
parser.add_argument(
    '-o', '--output', type=str, nargs='?', dest='output', default='recovered',
    help=('output extracted files to this directory [default=./recovered/]'),
)
parser.add_argument(
     '-v', '--verbose', dest='verbose', action='store_true',
    default=False, help=('print progress message'),
)


def recover(imgpath, outpath, verbose=False):

    # check that we can open image
    try:
        with open(imgpath, 'r'):
            pass
    except IOError:
        print('Unable to open %s. Check that the path is '
              'correct, and that you have read permission.' % imgpath)
        return

    # if the output directory exists, check that it's writeable
    if os.path.isdir(outpath):
        if not os.access(outpath, os.W_OK):
            print('Output directory %s is not writeable - check permissions'
                  % outpath)
            return
    # otherwise create it
    else:
        try:
            os.makedirs(outpath)
        except IOError:
            print('Could not create output directory %s - check permissions'
                  % outpath)
            return

    cmd = ['fls', '-i', 'raw', '-p', '-r', imgpath]

    p = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
    out, err = p.communicate()

    if p.returncode:
        print('Command "%s" failed:\n%s' % (' '.join(cmd), err))
        return

    ft = ''.join(TYPECODES)
    regex = '([%s])/([%s])\s+\*\s+(\d+):\s+(.*)' % (ft, ft)
    success = {}
    failure = {}
    skipped = {}

    for ftype, mtype, inode, relpath in re.findall(regex, out):

        recpath = os.path.join(outpath, relpath)
        recdir, recname = os.path.split(recpath)
        item = {relpath:[imgpath, relpath]}

        # don't try to recover directories
        if os.path.isdir(recpath):
            continue

        # only worth recovering deleted files
        elif (ftype in ('r', 'd')) and (mtype in ('r', 'd')):
            if not os.path.isdir(recdir):
                if os.path.exists(recdir):
                    os.remove(recdir)
                os.makedirs(recdir)
            cmd = ['icat', '-i', 'raw', '-r', imgpath, inode]
            with open(recpath, 'wb', 4096) as outfile:
                err = subprocess.call(cmd, stdout=outfile, bufsize=4096)
            if err:
                msg = '[FAILED]'
                failure.update(item)
            else:
                msg = '[RECOVERED]'
                success.update(item)
            if verbose:
                if ftype != mtype:
                    realloc_msg = (
                        '[WARNING: file name structure (%s) '
                        'does not match metadata (%s)]'
                        % (TYPEDICT[ftype], TYPEDICT[mtype]))
                else:
                    realloc_msg = ''
                print('%s %s:%s --> %s %s'
                       % (msg, imgpath, inode, recpath, realloc_msg))
        else:
            # skip unknown/other file types
            if verbose:
                print('[SKIPPED] %s:%s [%s / %s]'
                       % (imgpath, inode, TYPEDICT[ftype], TYPEDICT[mtype]))
            skipped.update(item)

    print('-' * 50)
    nsuccesses = len(success)
    nfailures = len(failure)
    nskipped = len(skipped)
    print('%i files successfully recovered to %s'
          % (len(success), outpath))
    print('%i files skipped' % nskipped)
    print('%i files could not be successfully recovered' % nfailures)
    if nfailures:
        print('\n'.join([(' * ' + pth) for pth in failure.keys()]))
    print('-' * 50)

if __name__ == '__main__':
    args = parser.parse_args()
    imgpath = args.image[0]
    outpath = args.output
    recover(imgpath, outpath, verbose=args.verbose)

只需将脚本复制粘贴到您的 Pycharm 中。

于 2021-07-29T15:12:14.457 回答