You need to enable JavaScript to run this app. 如何编程读取磁盘空闲空间中留存的已删除文件原始字节数据
优惠活动
大模型
产品
解决方案
定价
更多

如何编程读取磁盘空闲空间中留存的已删除文件原始字节数据

核心实现逻辑

你要的空闲空间无结构字节流,核心实现两步即可:

  1. 获取目标磁盘/分区所有已分配块的偏移区间,排除这些区间后剩下的就是未分配(空闲)空间的区间列表
  2. 按偏移顺序读取原始块设备中所有未分配区间的字节,拼接后就是你需要的纯字节流

macOS + APFS 实现方案

操作需要root权限,且需要先关闭SIP(系统完整性保护)才能读取原始块设备。

  • 先通过diskutil apfs list获取目标APFS卷的块设备路径(形如/dev/disk1s2)和卷块大小(APFS默认块大小为4096字节)
  • 分配状态获取有两种可选方式:
    • 手动解析APFS结构:读取卷起始位置的超级块,找到分配位图的存储位置,遍历位图每一位,标记为0的就是未分配块,整理出所有未分配块的偏移区间
    • 借助成熟工具输出:直接调用sleuthkit套件的blkstat命令,解析输出即可直接拿到所有未分配块的偏移和长度,不需要手动解析文件系统结构
  • 读取未分配空间的C语言简化示例:
#include <fcntl.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>

int main() {
    // 替换为你的目标块设备路径
    int disk_fd = open("/dev/disk1s2", O_RDONLY);
    if (disk_fd < 0) {
        perror("打开磁盘失败,请确认有root权限且SIP已关闭");
        return 1;
    }
    // 这里替换为你拿到的未分配区间:起始偏移、长度
    off_t free_offset = 1048576;
    size_t free_len = 4096 * 200;
    char *buf = malloc(free_len);
    if (!buf) {
        perror("内存分配失败");
        close(disk_fd);
        return 1;
    }
    lseek(disk_fd, free_offset, SEEK_SET);
    ssize_t read_cnt = read(disk_fd, buf, free_len);
    if (read_cnt != free_len) {
        perror("读取磁盘失败");
    } else {
        // 这里将buf写入输出文件,即可得到对应区间的原始字节
        FILE *out = fopen("./free_space_dump.bin", "wb");
        fwrite(buf, 1, free_len, out);
        fclose(out);
    }
    free(buf);
    close(disk_fd);
    return 0;
}

注意:APFS的快照占用的块会被标记为已保留,如果你需要读取快照关联的残留数据,需要额外解析快照的块分配表。

Linux 平台实现(适配ext4/xfs/btrfs等)

操作需要root权限,块设备路径形如/dev/sda1。

  • ext4文件系统可以直接用ext2fs开源库,调用ext2fs_block_iterate2遍历所有已分配块,剩余区间就是未分配空间,不需要手动解析块组、块位图结构
  • btrfs、zfs这类写时复制文件系统,建议直接用sleuthkit的接口获取分配状态,避免手动处理快照、子卷的复杂分配逻辑

Windows 平台实现(适配NTFS/exFAT/FAT32)

操作需要管理员权限。

  • NTFS直接调用系统API即可:用CreateFile打开卷路径(形如\\.\C:),调用DeviceIoControl传入控制码FSCTL_GET_VOLUME_BITMAP,直接获取整个卷的簇分配位图,每一位对应一个簇的分配状态,0就是未分配簇
  • 拿到未分配簇的偏移和长度后,直接调用ReadFile读取对应位置的字节即可
  • exFAT/FAT32可以直接读取FAT表,遍历所有簇的分配标记,未标记为已用的就是未分配簇

通用注意事项

  • 尽量操作已卸载或者只读挂载的卷,避免读写状态下操作系统动态分配块,导致你读取的空闲空间数据和实际状态不一致
  • 不要在运行中的系统盘上做写入类操作,避免误操作损坏现有文件
  • 如果不需要兼容老旧文件系统,直接复用sleuthkit的成熟接口,可以大幅降低跨平台移植的工作量

内容的提问来源于stack exchange,提问作者mistertim

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.12 14:51:04