记 * 恢复ext4硬盘的数据


本人所写的博客都为开发之中遇到问题记录的随笔,主要是给自己积累些问题。免日后无印象,如有不当之处敬请指正(欢迎进扣群 24849632 探讨问题);

早些日子invaid 泄漏了部份数据,我姗姗的下载了一个15多个G的7-zip压缩包。忙着解压时因为停电导到硬盘无法读取。尝试了一些方法都无法恢复硬盘的数据读取。

然后重新使用命令mkfs.ext4的创建了文件系统。刚回车便后悔了,这硬盘是能正常使用ls命令了,但硬盘上那些重要的数据却因为这个操作彻底失去了链接。硬盘上资料相当重要,约有400多G,我很想把这些资料找回来,因为涉及到大部份个人隐私数据,同时要恢复这么多资料钱已经布擦布的我只能自己尝试看能不能恢复数据了。

在网上找到办法无法恢复硬盘的数据,而又因为重构了超级表,那要恢复数据只能自己想办法了。

在github上找到了ext4magic的源代码,我打算在此代码的基础上逐个读取硬盘上的inode,尝试看数据是否能成功恢复。

ext4magic的池子地址为:https://github.com/iSWORD/ext4magic.githttps://github.com/iSWORD/ext4magic.git

源代码包下载后,配置编译时出现的问题在此略过,将需要安装的依赖统一及需要执行的指令放在下面的代码框内:

jingtongact@wsl:~/ext4magic$sudo apt install -y libtool libblkid-dev libext2fs-dev libuuidm-ocaml-dev libghc-bzlib-dev libmagic-dev
jingtongact@wsl:~/ext4magic$cp /usr/share/libtool/build-aux/config.sub .
jingtongact@wsl:~/ext4magic$cp /usr/share/libtool/build-aux/config.guess .
jingtongact@wsl:~/ext4magic$autoreconf -ivh
jingtongact@wsl:~/ext4magic$./configure
jingtongact@wsl:~/ext4magic$make

首先要做的是读取硬盘镜像上的第一个文件,在虚拟机上做如下配置

 在此虚拟盘上创建一个text.txt的文件

jingtongact@vbox:/data$mkfs.ext4 /dev/sdd1
jingtongact@vbox:/data$sudo mount /dev/sdd1 /data
jingtongact@vbox:/data$cd /data
jingtongact@vbox:/data$touch test.txt
jingtongact@vbox:/data$echo "hello,world">>test.txt
jingtongact@vbox:~$sudo umount /dev/sdd1
jingtongact@vbox:~$sudo dd if=/dev/sdd1 of=test.image

将上面生成的test.image文件复制至windows系统,这样就有了测试用的ext4文件镜像,下面要做的第一个操作就是尝试通过修改ext4magic源代码来将test.image内的test.txt文件恢复出来。

学习是个漫长的过程,为了更详细的了解EXT4的文件格式,需要先从创建EXT4格式的磁盘格式说

起。GITHUB上的 e2fsprogs 项目提供了LINUX下的mkfs.ext4工具https://github.com/tytso/e2fsprogs.git https://github.com/tytso/e2fsprogs.git%C2%A0

第一步:初始化文件系统格式,包括初始化超级块

 EXT4的超级块定义

/*
 * Structure of the super block
 */
struct ext2_super_block {
/*000*/	__u32	s_inodes_count;		/* Inodes count */
	__u32	s_blocks_count;		/* Blocks count */
	__u32	s_r_blocks_count;	/* Reserved blocks count */
	__u32	s_free_blocks_count;	/* Free blocks count */
/*010*/	__u32	s_free_inodes_count;	/* Free inodes count */
	__u32	s_first_data_block;	/* First Data Block */
	__u32	s_log_block_size;	/* Block size */
	__u32	s_log_cluster_size;	/* Allocation cluster size */
/*020*/	__u32	s_blocks_per_group;	/* # Blocks per group */
	__u32	s_clusters_per_group;	/* # Fragments per group */
	__u32	s_inodes_per_group;	/* # Inodes per group */
	__u32	s_mtime;		/* Mount time */
/*030*/	__u32	s_wtime;		/* Write time */
	__u16	s_mnt_count;		/* Mount count */
	__s16	s_max_mnt_count;	/* Maximal mount count */
	__u16	s_magic;		/* Magic signature */
	__u16	s_state;		/* File system state */
	__u16	s_errors;		/* Behaviour when detecting errors */
	__u16	s_minor_rev_level;	/* minor revision level */
/*040*/	__u32	s_lastcheck;		/* time of last check */
	__u32	s_checkinterval;	/* max. time between checks */
	__u32	s_creator_os;		/* OS */
	__u32	s_rev_level;		/* Revision level */
/*050*/	__u16	s_def_resuid;		/* Default uid for reserved blocks */
	__u16	s_def_resgid;		/* Default gid for reserved blocks */
	/*
	 * These fields are for EXT2_DYNAMIC_REV superblocks only.
	 *
	 * Note: the difference between the compatible feature set and
	 * the incompatible feature set is that if there is a bit set
	 * in the incompatible feature set that the kernel doesn't
	 * know about, it should refuse to mount the filesystem.
	 *
	 * e2fsck's requirements are more strict; if it doesn't know
	 * about a feature in either the compatible or incompatible
	 * feature set, it must abort and not try to meddle with
	 * things it doesn't understand...
	 */
	__u32	s_first_ino;		/* First non-reserved inode */
	__u16   s_inode_size;		/* size of inode structure */
	__u16	s_block_group_nr;	/* block group # of this superblock */
	__u32	s_feature_compat;	/* compatible feature set */
/*060*/	__u32	s_feature_incompat;	/* incompatible feature set */
	__u32	s_feature_ro_compat;	/* readonly-compatible feature set */
/*068*/	__u8	s_uuid[16] __nonstring;		/* 128-bit uuid for volume */
/*078*/	__u8	s_volume_name[EXT2_LABEL_LEN] __nonstring;	/* volume name, no NUL? */
/*088*/	__u8	s_last_mounted[64] __nonstring;	/* directory last mounted on, no NUL? */
/*0c8*/	__u32	s_algorithm_usage_bitmap; /* For compression */
	/*
	 * Performance hints.  Directory preallocation should only
	 * happen if the EXT2_FEATURE_COMPAT_DIR_PREALLOC flag is on.
	 */
	__u8	s_prealloc_blocks;	/* Nr of blocks to try to preallocate*/
	__u8	s_prealloc_dir_blocks;	/* Nr to preallocate for dirs */
	__u16	s_reserved_gdt_blocks;	/* Per group table for online growth */
	/*
	 * Journaling support valid if EXT2_FEATURE_COMPAT_HAS_JOURNAL set.
	 */
/*0d0*/	__u8	s_journal_uuid[16] __nonstring;	/* uuid of journal superblock */
/*0e0*/	__u32	s_journal_inum;		/* inode number of journal file */
	__u32	s_journal_dev;		/* device number of journal file */
	__u32	s_last_orphan;		/* start of list of inodes to delete */
/*0ec*/	__u32	s_hash_seed[4];		/* HTREE hash seed */
/*0fc*/	__u8	s_def_hash_version;	/* Default hash version to use */
	__u8	s_jnl_backup_type;	/* Default type of journal backup */
	__u16	s_desc_size;		/* Group desc. size: INCOMPAT_64BIT */
/*100*/	__u32	s_default_mount_opts;	/* default EXT2_MOUNT_* flags used */
	__u32	s_first_meta_bg;	/* First metablock group */
	__u32	s_mkfs_time;		/* When the filesystem was created */
/*10c*/	__u32	s_jnl_blocks[17];	/* Backup of the journal inode */
/*150*/	__u32	s_blocks_count_hi;	/* Blocks count high 32bits */
	__u32	s_r_blocks_count_hi;	/* Reserved blocks count high 32 bits*/
	__u32	s_free_blocks_hi;	/* Free blocks count */
	__u16	s_min_extra_isize;	/* All inodes have at least # bytes */
	__u16	s_want_extra_isize;	/* New inodes should reserve # bytes */
/*160*/	__u32	s_flags;		/* Miscellaneous flags */
	__u16	s_raid_stride;		/* RAID stride in blocks */
	__u16	s_mmp_update_interval;  /* # seconds to wait in MMP checking */
	__u64	s_mmp_block;		/* Block for multi-mount protection */
/*170*/	__u32	s_raid_stripe_width;	/* blocks on all data disks (N*stride)*/
	__u8	s_log_groups_per_flex;	/* FLEX_BG group size */
	__u8	s_checksum_type;	/* metadata checksum algorithm */
	__u8	s_encryption_level;	/* versioning level for encryption */
	__u8	s_reserved_pad;		/* Padding to next 32bits */
	__u64	s_kbytes_written;	/* nr of lifetime kilobytes written */
/*180*/	__u32	s_snapshot_inum;	/* Inode number of active snapshot */
	__u32	s_snapshot_id;		/* sequential ID of active snapshot */
	__u64	s_snapshot_r_blocks_count; /* active snapshot reserved blocks */
/*190*/	__u32	s_snapshot_list;	/* inode number of disk snapshot list */
#define EXT4_S_ERR_START ext4_offsetof(struct ext2_super_block, s_error_count)
	__u32	s_error_count;		/* number of fs errors */
	__u32	s_first_error_time;	/* first time an error happened */
	__u32	s_first_error_ino;	/* inode involved in first error */
/*1a0*/	__u64	s_first_error_block;	/* block involved in first error */
	__u8	s_first_error_func[32] __nonstring;	/* function where error hit, no NUL? */
/*1c8*/	__u32	s_first_error_line;	/* line number where error happened */
	__u32	s_last_error_time;	/* most recent time of an error */
/*1d0*/	__u32	s_last_error_ino;	/* inode involved in last error */
	__u32	s_last_error_line;	/* line number where error happened */
	__u64	s_last_error_block;	/* block involved of last error */
/*1e0*/	__u8	s_last_error_func[32] __nonstring;	/* function where error hit, no NUL? */
#define EXT4_S_ERR_END ext4_offsetof(struct ext2_super_block, s_mount_opts)
/*200*/	__u8	s_mount_opts[64] __nonstring;	/* default mount options, no NUL? */
/*240*/	__u32	s_usr_quota_inum;	/* inode number of user quota file */
	__u32	s_grp_quota_inum;	/* inode number of group quota file */
	__u32	s_overhead_clusters;	/* overhead blocks/clusters in fs */
/*24c*/	__u32	s_backup_bgs[2];	/* If sparse_super2 enabled */
/*254*/	__u8	s_encrypt_algos[4];	/* Encryption algorithms in use  */
/*258*/	__u8	s_encrypt_pw_salt[16];	/* Salt used for string2key algorithm */
/*268*/	__le32	s_lpf_ino;		/* Location of the lost+found inode */
	__le32  s_prj_quota_inum;	/* inode for tracking project quota */
/*270*/	__le32	s_checksum_seed;	/* crc32c(orig_uuid) if csum_seed set */
/*274*/	__u8	s_wtime_hi;
	__u8	s_mtime_hi;
	__u8	s_mkfs_time_hi;
	__u8	s_lastcheck_hi;
	__u8	s_first_error_time_hi;
	__u8	s_last_error_time_hi;
	__u8	s_first_error_errcode;
	__u8    s_last_error_errcode;
/*27c*/ __le16	s_encoding;		/* Filename charset encoding */
	__le16	s_encoding_flags;	/* Filename charset encoding flags */
	__le32  s_orphan_file_inum;	/* Inode for tracking orphan inodes */
	__le32	s_reserved[94];		/* Padding to the end of the block */
/*3fc*/	__u32	s_checksum;		/* crc32c(superblock) */
};

第二步:初始化UUID 及 UUID的校验

 第三步:检测坏块并从块表中去除

 第四步:建立符号及文件系统 

本文到此不得不做个180度的结尾,因为实在是工作太忙,也没有那么多时间去仔细的研究EXT4的文件结构,虽然丢失的资料很珍贵也很可惜,但幸运的是在一月前已经将大部份数据备份在了另一块硬盘上,当时买硬盘就是担心数据因为硬盘的故障丢失,所以在某东上买了个10T的盘。因此这次掉电事故整体上造成的损失还是可以控的。这硬盘上的数据在其它计算机上也有备份,因此大多数的资料还是找了回来,虽然在技术的想突破这个问题是可行的,但是找回的文件因为其它结构已经丢失,要恢复之前的目录结构还是比较难,而通过WINPE下的datarecover硬盘的部份数据也恢复在了lost+found文件夹,有一部份数据却也无法打开了。

要恢复这些数据找专业的机构因为涉及大量隐私数据,担心出现之前**希门类似的事情,所以也不考虑将这些数据给第三方机构去恢复,而自己搞的话,需要花费大量的精力,而又不会开展此类的业务,所以想想还是放弃自己去研究并恢复的这个想法。

在这期间感谢那么多朋友的关注,并提出的宝贵建议,在此表示十分感谢,并对关注此事的朋友说一声抱歉。

最后还是建议大家尽量将数据多做一个备份。为了数据的安全尽量选择好一点的硬盘。

参考资料

ext4数据恢复实战及文件系统结构详解 - 简书

使用hexdump工具追踪EXT4文件系统中的一个文件 - 姜姜csu - 博客园

ext4 文件分区丢失后(或误删除数据)恢复数据_尉澄华的博客-CSDN博客_ext4分区恢复

关于FreeBSD的fdisk和disklabel_asukaztc的博客-CSDN博客_disklabel

  • 28
    点赞
  • 30
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

晶通物控

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值