如何用Python实现一个文件粉碎机?

为什么下面的代码删除文件后,还可用 360 软件恢复回来(已亲测)?难道要用 mmap 模块吗?

#--------------------------------------------------

import tkinter.filedialog as tf

def selecFile(title='多文件选择',fmt='.'):

    '''(多个)文件选择(对话框) 返元组 取消时返空'''
    return tf.askopenfilenames(title=title,filetypes=[('all files',fmt)])

def myRemoveFiles():

'''彻底删除文件'''
paths = selecFile(title='选择要删除的文件')  #
if paths:
    if tm.askokcancel('重要提示!','确定永久删除吗?'):
        fn = '_Test{}_.tmp'
        _dir = os.path.dirname(paths[0])
    for i, _file in enumerate(paths):
        try:
            fsize = os.path.getsize(_file)
            with open(_file,'rb+') as f:
                for _ in range(3):
                    f.seek(0,0)
                    f.write(os.urandom(fsize))
                     
            file = os.path.abspath(os.path.join(_dir,fn.format(i)))
            os.rename(_file,file)
            os.remove(file)
            
            print(_file,"OK")
        except Exception as err:
            print(_file,str(err))


如何用Python实现一个文件粉碎机?

23 回复

要覆盖掉文件在磁盘的数据才行吧


import os
import random

def secure_delete(file_path, passes=3):
    """
    安全删除文件(文件粉碎)
    
    参数:
        file_path: 文件路径
        passes: 覆盖次数(默认3次符合DOD 5220.22-M标准)
    """
    try:
        # 1. 检查文件是否存在
        if not os.path.exists(file_path):
            print(f"文件不存在: {file_path}")
            return False
        
        # 2. 获取文件大小
        file_size = os.path.getsize(file_path)
        
        # 3. 多次覆盖文件内容
        with open(file_path, 'rb+') as f:
            for pass_num in range(passes):
                # 移动到文件开头
                f.seek(0)
                
                # 生成随机数据覆盖
                random_data = os.urandom(file_size)  # 使用加密安全的随机数
                f.write(random_data)
                
                # 确保数据写入磁盘
                f.flush()
                os.fsync(f.fileno())
                
                print(f"第 {pass_num + 1} 次覆盖完成")
        
        # 4. 重命名文件(可选,增加恢复难度)
        temp_name = file_path + '.tmp'
        os.rename(file_path, temp_name)
        
        # 5. 最后删除文件
        os.remove(temp_name)
        
        print(f"文件已安全删除: {file_path}")
        return True
        
    except Exception as e:
        print(f"删除失败: {e}")
        return False

# 使用示例
if __name__ == "__main__":
    # 创建一个测试文件
    test_file = "test_secret.txt"
    with open(test_file, 'w') as f:
        f.write("这是敏感数据,需要安全删除")
    
    # 安全删除文件
    secure_delete(test_file)

这个实现的核心是多次用随机数据覆盖原文件内容,然后删除。关键点:

  1. 多次覆盖:使用os.urandom()生成加密安全的随机数据,覆盖3次(可调整)
  2. 强制写入flush()fsync()确保数据写入物理磁盘
  3. 重命名:增加恢复难度
  4. 异常处理:处理文件不存在等异常情况

注意:这只是软件层面的安全删除,固态硬盘(SSD)由于磨损均衡技术,物理恢复仍有可能。

简单建议:对于真正敏感的数据,建议使用专门的硬件销毁工具。

要直接磁盘访问,不能只是删记录,把文件所在扇区多次写入随机数据就行

直接把文件内容改了不就行了?原来的肯定找不回来了。

恢复回来倒是可以,但是恢复回来的文件应该已经是乱码了吧?

粉碎机是必须抹盘的
删除或彻底删除只是把原来文件在磁盘的位置,标记为可用空间而已
覆盖实质只是“另存”,然后把文件索引指向新的位置,原来的位置标记为可用

比较好奇,如果直接对文件操作,而不是直接对磁盘访问,能保证覆写文件的时候,覆盖的是相同的硬盘区域吗?

用勒索病毒试试


然而,楼主这种方法,如果是 360 恢复这种软件,按文件名寻找丢失的文件,寻找回来的应该是已经被随机写入过的版本吧?我猜原版的文件还在,但已经没法用文件名寻找了。


我针对他的标题说的,他的正文和标题是两种情况


用 360 扫描出来的是这种文件: Test0.tmp
恢复后,改扩展名为原来的类型:打开一看,还是原来的内容,不是乱码!!!

为了进一步验证,我把上面函数中关于重命名及删除文件的代码注释掉,执行完后,原文件大小不变,内容为乱码!!
为什么恢复后却是原本的内容而不是乱码?

Python 吗
Os.system(“shred your_file”)
解决问题

我们对指针进行再操作的时候,肯定会覆盖(破坏)指针指向地址的数据,那么对于文件对象为什么从文件首开始写操作,不能破坏其数据?
那么利用 mmap 模块,对文件建立内存映射,再对映射进行全员覆盖,这样会有不同吗?



一般来说修改文件内容会写入原位置,因为不需要重新分派扇区,性能有利。例外是 cow 和带在线自动碎片整理的文件系统

我没懂你为什么要 rename

360 文件粉碎机是直接摘除文件系统 cluster 索引,文件系统无法定位到这个文件,更别说恢复,你上无法恢复内容,用 python 实现的话,有点麻烦,你得解析到该文件在 ntfs 相对物理盘地址和文件偏移量大小,然后随机填充 0 和 1,30 次以上,基本上来说就恢复不了

做个实验:
写 0 并格式化一个 U 盘(保证没有干扰)
写一个文件,看能不能找到
覆盖完不要删除,看能不能找到
最后人工删除,看能不能找到

好奇对于类似 ZFS/AppleFS 这种 WAL 的 FS,

在不填满整个 storage pool 的前提下如何覆盖已删除文件的数据块?

先加密后删除。即使恢复了那么数据没有意义。这样思路不是更简洁?

def myRemoveFiles():
‘’‘彻底删除文件’’’
paths = selecFile(title=‘选择要删除的文件’) #
if paths:
if tm.askokcancel(‘重要提示!’,‘确定永久删除吗?’):
fn = ‘Test{}.tmp’
_dir = os.path.dirname(paths[0])
for i, _file in enumerate(paths):
try:
# fsize = os.path.getsize(_file)
# with open(_file,‘rb+’) as f:
# for _ in range(3):
# f.seek(0,0)
# f.write(os.urandom(fsize))

fd = os.open(_file,os.O_RDWR)
with mmap.mmap(fd,0,access=mmap.ACCESS_WRITE) as m:
m.write(os.urandom(m.size()))
m.flush()
os.close(fd)

file = os.path.abspath(os.path.join(_dir,fn.format(i)))
os.rename(_file,file)
os.remove(file)

print(_file,“OK”)
except Exception as err:
print(_file,str(err))

用 mmap 时未发现能恢复

抹盘,全写 0 三十遍

为什么要 30 遍啊

回到顶部