在上一篇文章《數(shù)據(jù)恢復(fù)(一)-linux下ext文件系統(tǒng)數(shù)據(jù)刪除原理淺析》中分析了ext數(shù)據(jù)刪除的原理,這篇文章中會結(jié)合實例分析數(shù)據(jù)恢復(fù)的原理。 ext 含義全稱Linux extended file system, extfs,即Linux擴展文件系統(tǒng),Ext2就代表第二代文件擴展系統(tǒng),Ext3/Ext4以此類推,它們都是Ext2的升級版,只不過為了快速恢復(fù)文件系統(tǒng),減少一致性檢查的時間,增加了日志功能,所以Ext2被稱為索引式文件系統(tǒng),而Ext3/Ext4被稱為日志式文件系統(tǒng)。并且Linux還支持很多文件系統(tǒng),包括XFS、NFS、Fat等文件系統(tǒng)。 ext3/4 數(shù)據(jù)恢復(fù)思路由于Ext3/Ext4被稱為日志式文件系統(tǒng),所以文件的刪除會有日志記錄。就意味著被刪除的inode的block指針還可以從journal日志的inode副本中找到,也就有可能從磁盤中恢復(fù)出被刪除的文件。 經(jīng)過extundelete、ext3grep、ext4magic等幾款linux下ext數(shù)據(jù)恢復(fù)軟件的測試,總結(jié)出ext數(shù)據(jù)恢復(fù)的原理。 journal日志恢復(fù)基于journal日志從inode副本中找到block指針從而確定被刪除文件在磁盤上的物理位置進行恢復(fù)。 文件特征恢復(fù)掃描整個磁盤,基于文件魔數(shù)(Magic Number)特征直接從磁盤中恢復(fù)文件。 實驗環(huán)境
模擬ext3下文件刪除后進行恢復(fù)因為實驗環(huán)境中centos7默認用的是ext4的文件系統(tǒng),但是要測試ext3的文件刪除,通常需要掛載一個新的硬盤并格式化為ext3。這里提供一個更簡單的解決辦法。 dd生成一個2G大小的空文件[root@VM-8-8-centos newpart]# pwd
/newpart
[root@VM-8-8-centos newpart]# dd if=/dev/zero of=test.ext3 bs=1024M count=2
dd: memory exhausted by input buffer of size 1073741824 bytes (1.0 GiB)
[root@VM-8-8-centos newpart]# dd if=/dev/zero of=test.ext3 bs=128M count=16
16+0 records in
16+0 records out
2147483648 bytes (2.1 GB, 2.0 GiB) copied, 13.2437 s, 162 MB/s
[root@VM-8-8-centos newpart]# ll -h
total 2.1G
-rw-r--r-- 1 root root 2.0G Mar 11 23:28 test.ext3 可以看到第一次使用dd命令生成空文件時報錯了,dd: memory exhausted by input buffer of size。申請的內(nèi)存的過大,超過了內(nèi)存的限制。這里要生成一個2G的文件,一次寫入內(nèi)存的大小為1024M即1G,而機器的內(nèi)存只有1G,超出內(nèi)存限制導(dǎo)致dd命令報錯。所以可以將bs的值改小,并分為多次寫入文件,對最后生成的文件大小不會有影響。 mkfs.ext3將空文件格式化為ext3文件系統(tǒng)
這里指定生成inode-size大小為128的ext文件系統(tǒng),默認為256(后面會解釋)。 掛載ext3文件到系統(tǒng)目錄[root@VM-8-8-centos newpart]# df -Th
Filesystem Type Size Used Avail Use% Mounted on
/dev/vda1 ext4 25G 8.2G 16G 35% /
/dev/vdb1 ext4 40G 180M 37G 1% /newpart
[root@VM-8-8-centos newpart]# mount -o loop test.ext3 /ext3
[root@VM-8-8-centos newpart]# df -Th
Filesystem Type Size Used Avail Use% Mounted on
/dev/vda1 ext4 25G 8.2G 16G 35% /
/dev/vdb1 ext4 40G 180M 37G 1% /newpart
/dev/loop1 ext3 2.0G 3.1M 1.9G 1% /ext3
[root@VM-8-8-centos newpart]# cd /ext3/
[root@VM-8-8-centos ext3]# mkdir test && cd test
[root@VM-8-8-centos test]# cp /etc/passwd ./
[root@VM-8-8-centos test]# ls -ilh
total 4.0K
98306 -rw-r--r-- 1 root root 1.8K Mar 11 23:59 passwd 此時已經(jīng)將我們的ext3文件作為文件系統(tǒng)掛載到系統(tǒng)目錄中。進入該分區(qū)中,拷貝passwd作為測試文件。 模擬文件刪除并記錄block指針
//文件被刪除后,原inode的block指針被填0,獲取為空 這里需要強度的是雖然將ext3文件系統(tǒng)掛載到了系統(tǒng)的/ext3目錄下,但是文件系統(tǒng)本身也有根目錄(區(qū)別于系統(tǒng)根目錄),因此這里使用ls -d /test,而非ls -d /ext3/test。 在刪除文件之前特地記錄了inode中block的值,也就是磁盤中該文件的真實位置。使用dd命令讀取該block位置的文件。 刪除文件后根據(jù)刪除前的block仍能在磁盤中找到該文件。因此要想成功恢復(fù)被刪除的文件,關(guān)鍵在于如何從journal日志中找到inode副本中的block值。 使用debugfs的logdump獲取日志中inode副本[root@VM-8-8-centos test]# debugfs /dev/loop1 -R 'logdump -i <98306>'
debugfs 1.45.6 (20-Mar-2020)
Inode 98306 is at group 12, block 393218, offset 128
Journal starts at block 1, transaction 2
FS block 393218 logged at sequence 47, journal block 369 (flags 0x2)
(inode block for inode 98306):
Inode: 98306 Type: bad type Mode: 0000 Flags: 0x0
Generation: 0 Version: 0x00000000
User: 0 Group: 0 Size: 0
File ACL: 0
Links: 0 Blockcount: 0
Fragment: Address: 0 Number: 0 Size: 0
ctime: 0x00000000 -- Thu Jan 1 08:00:00 1970
atime: 0x00000000 -- Thu Jan 1 08:00:00 1970
mtime: 0x00000000 -- Thu Jan 1 08:00:00 1970
Blocks: //該副本中為空
FS block 393218 logged at sequence 50, journal block 397 (flags 0x2)
(inode block for inode 98306):
Inode: 98306 Type: regular Mode: 0644 Flags: 0x0
Generation: 4264657513 Version: 0x00000001
User: 0 Group: 0 Size: 1825
File ACL: 0
Links: 1 Blockcount: 8
Fragment: Address: 0 Number: 0 Size: 0
ctime: 0x622b71c8 -- Fri Mar 11 23:59:04 2022
atime: 0x622b71c8 -- Fri Mar 11 23:59:04 2022
mtime: 0x622b71c8 -- Fri Mar 11 23:59:04 2022
Blocks: (0+1): 16994 //被刪除文件的inode副本中的block指針
.....
No magic number at block 1620: end of journal. 注意上面的 Blocks: (0+1): 16994 為block指針。 使用logdump 命令在journal日志中找到了多個indoe為98306的副本,這里只展示了兩個。第一個block記錄為空,在第二個副本中找到了原始block的指針,且與之前記錄的文件block指針值一致,證明該方法有效,可成功恢復(fù)文件。 使用dd從磁盤中dump恢復(fù)文件
文件恢復(fù)成功!沒有使用任何數(shù)據(jù)恢復(fù)軟件,僅使用linux自帶的命令恢復(fù)了被刪除的文件。 補充:為什么使用dd命令dump恢復(fù)的文件MD5值不一樣?[root@VM-8-8-centos test]# md5sum /etc/passwd
5e39a7f4aa25cd0de397c1685597460b /etc/passwd
[root@VM-8-8-centos test]# md5sum passwd
118c4d51a0425cf6d028076a54ba7fa9 passwd
[root@VM-8-8-centos test]# diff -Naur /etc/passwd passwd
--- /etc/passwd 2022-03-10 11:04:45.106866879 +0800
+++ passwd 2022-03-12 00:50:51.000000000 +0800
@@ -34,3 +34,4 @@
lighthouse:x:1000:1000::/home/lighthouse:/bin/bash
zgao:x:0:1001::/home/zgao:/bin/bash
redis:x:991:984:Redis Database Server:/var/lib/redis:/sbin/nologin
+
\ No newline at end of file 很明顯兩者的md5并不相同,但用cat看到的內(nèi)容卻一樣。因為dd命令是按照bs的大小來dump文件的,因為文件系統(tǒng)block-size為4096,整塊一起dump包括了文件結(jié)尾填0部分,所以兩者的md5值會不同。 小結(jié)這里通過ext3演示了文件刪除后的通過日志的方式恢復(fù)文件過程,由于ext4和ext3都是日志文件系統(tǒng),數(shù)據(jù)恢復(fù)思路是一樣的,就不再贅述了。 debugfs的logdump命令存在bug?在大量ext3/4的數(shù)據(jù)恢復(fù)實驗中發(fā)現(xiàn),logdump命令并不一定成功!網(wǎng)上有大量誤導(dǎo)人的文章,根本沒有弄清楚原理!在此花費了大量時間驗證! 結(jié)論:無論ext3、4,只有在文件系統(tǒng)的inode-size值為128時,logdump命令計算得到的journal日志才是正確的。而ext3默認indoe-size為128,ext4默認為256,因此通常ext3下使用logdump的結(jié)果是正確的,ext4則是錯誤的! 關(guān)于在ext4中如何從journal日志中正確獲取indoe副本會在后續(xù)的系列文章中分析。 基于文件特征進行文件恢復(fù)這種恢復(fù)思路最典型的實現(xiàn)工具就是 foremost 。 foremost是一款根據(jù)文件頭,尾和內(nèi)部結(jié)構(gòu)來嘗試從鏡像文件(或者磁盤)中恢復(fù)文件的工具。foremost默認可以掃描出 jpg, gif, png, bmp, avi, exe, mpg, mp4, wav, riff, wmv 等文件。但是通過配置它的配置文件(默認為 /etc/foremost.conf),你還可以為它增加新的支持類型。 工具的使用網(wǎng)上有很多教程,這里只分析其實現(xiàn)原理。
常見文件類型的文件頭尾 分析png圖片文件格式特征以下圖為例,一張png格式的圖片。 將其放在上面創(chuàng)建的ext3分區(qū)中,并模擬刪除。
模擬png圖片文件被刪除對比上表的png文件頭尾,頭部89 50 4E 47,尾部AE 42 60 82。 [root@VM-8-8-centos test]# debugfs /dev/loop1 -R 'ls -d /test'
debugfs 1.45.6 (20-Mar-2020)
98305 (12) . 2 (12) .. 98306 (56) passwd
98307 (4016) logo.png
[root@VM-8-8-centos test]# debugfs /dev/loop1 -R 'blocks <98307>'
debugfs 1.45.6 (20-Mar-2020)
17302 17303 17304 17305 17306 17307 17308 17309 17310 17311 17312 17313 16794 17314 17315 17316 17317 16816 16817 16818 16819 16820 16821 16822 16823 16824 16825 16826 16827 16828 16829 16830 16831 17632 17633 17634 17635 //該圖片文件包含多個連續(xù)block
[root@VM-8-8-centos test]# rm -f logo.png
[root@VM-8-8-centos test]# debugfs /dev/loop1 -R 'ls -d /test'
debugfs 1.45.6 (20-Mar-2020)
98305 (12) . 2 (12) .. 98306 (4072) passwd
<98307> (4016) logo.png
[root@VM-8-8-centos test]# debugfs /dev/loop1 -R 'blocks <98307>'
debugfs 1.45.6 (20-Mar-2020)
// 文件被刪除后獲取block指針為空 暴力搜索匹配文件特征
將ext3分區(qū)看做成一個大文件,進行暴力搜索匹配文件特征(頭部和尾部特征)。 如果我們使用dd命令進行dump,這里需要用到16進制來計算,4096的十六進制為1000。由于文件頭部肯定在任意一個block的起始位置,所以相除必為整數(shù)倍。 在線16進制計算工具 這里算出來的值和我們之前用debugfs看到的block值相等。此時只要再算出偏移位置即可從磁盤中恢復(fù)文件。 使用dd將文件從磁盤中dump出來[root@VM-8-8-centos test]# dd if=/newpart/test.ext3 bs=4096 count=1 skip=17302 | xxd
00000000: 8950 4e47 0d0a 1a0a 0000 000d 4948 4452 .PNG........IHDR
00000010: 0000 1a7e 0000 059b 0806 0000 00ba cb9c ...~............
00000020: 5100 0000 0970 4859 7300 002e 2300 002e Q....pHYs...#...
00000030: 2301 78a5 3f76 0000 0019 7445 5874 536f #.x.?v....tEXtSo
00000040: 6674 7761 7265 0041 646f 6265 2049 6d61 ftware.Adobe Ima
00000050: 6765 5265 6164 7971 c965 3c00 0239 8449 geReadyq.e<..9.I
00000060: 4441 5478 daec dd01 0100 200c 8030 b57f DATx...... ..0.. 對于大文件,由于文件block不一定連續(xù),還需要從起始block中獲取到下一個block所在位置進行索引,再將文件“拼起來”即可恢復(fù)被刪除的文件。 對于文件不連續(xù)的情況,會在后面的數(shù)據(jù)恢復(fù)系列文章中深入分析。 總結(jié)本文從ext兩種數(shù)據(jù)恢復(fù)的思路深入分析,未使用任何數(shù)據(jù)恢復(fù)工具的前提下,逐步展示了數(shù)據(jù)恢復(fù)的原始過程,希望大家對數(shù)據(jù)恢復(fù)有更深刻的理解。 |
|
來自: zjshzq > 《網(wǎng)絡(luò)》