Bir dosya silindiğinde çoğu zaman verinin kendisi anında buharlaşmaz; dosya sisteminin “bu alan artık boş” dediği muhasebe kayıtları değişir. İşte ham disk imajını hexedit ile açıp inode ve blok adreslerini elle okumak, biraz arkeoloji biraz dedektiflik gibidir: kumların altından byte byte hikâye çıkarırız.
``
Not: Bu yazı adli analiz ve kendi verinizi kurtarma senaryoları içindir. Gerçek diskte değil, imaj kopyası üzerinde çalışın. Yazma işlemi, kurtarılabilir veriyi ezebilir.
Silinme Ne Demek?
Dosya sistemi bir dosyayı genellikle iki parçayla takip eder: metadata ve data. Metadata; isim, izin, zaman damgası, inode numarası ve verinin hangi bloklarda durduğunu söyler. Data ise dosyanın gerçek içeriğidir.
Basitleştirilmiş denklem şöyle düşünülebilir:
\[\text{Dosya} = \text{İsim Kaydı} + \text{Inode} + \text{Veri Blokları}\]Silme sırasında dizin girdisi kaldırılır, inode’un bağlantı sayısı düşer ve bloklar “boş” kabul edilir. Ama bloklar üzerine yeni veri yazılmadıysa hâlâ oradadır.
| Özellik | Ext4 | Btrfs |
|---|---|---|
| Metadata modeli | Inode tablosu ve blok grupları | B-tree tabanlı, COW mimarisi |
| Elle yorumlama | Daha öngörülebilir | Daha karmaşık |
| Silinmiş veri şansı | Üzerine yazılmadıysa iyi | Snapshot/COW varsa bazen çok iyi |
| Zorluk seviyesi | Orta | İleri |
Bu yazıda ana örneği Ext4 üzerinden kuracağız; Btrfs için de mantığı karşılaştıracağız.
Güvenli Laboratuvar Hazırlığı
Önce diskten ya da bölümden imaj alın:
sudo dd if=/dev/sdb1 of=disk.img bs=4M status=progress conv=noerror,sync
cp disk.img lab.img
hexedit lab.img
hexedit içinde gezinirken unutmayın: sayılar çoğu zaman little-endian saklanır. Yani ekranda 00 10 00 00 görüyorsanız bu değer 0x00001000, yani 4096 olabilir.
Ext4 Inode Adresini Hesaplamak
Ext4’te süperblok genelde bölüm başlangıcından 1024 byte sonra başlar. Buradan blok boyutu, inode boyutu, grup başına inode sayısı gibi bilgiler okunur.
Blok boyutu formülü:
\[\text{block\_size} = 1024 \times 2^{s\_log\_block\_size}\]Bir inode’un disk üzerindeki konumu için:
\[\text{group} = \left\lfloor \frac{inode - 1}{inodes\_per\_group} \right\rfloor\] \[\text{index} = (inode - 1) \bmod inodes\_per\_group\] \[\text{inode\_offset} = inode\_table\_block \times block\_size + index \times inode\_size\]Örneğin inode numarası 131083, blok boyutu 4096, inode boyutu 256 ve grup başına inode sayısı 8192 ise ilgili blok grubunu ve inode tablosundaki yerini bu formüllerle buluruz.
Inode İçindeki İpuçları
Ext4 inode yapısında önemli alanlar şunlardır:
| Alan | Tipik offset | Anlamı |
|---|---|---|
i_mode |
0x00 |
Dosya türü ve izinler |
i_size_lo |
0x04 |
Dosya boyutu düşük 32 bit |
i_links_count |
0x1A |
Bağlantı sayısı |
i_blocks_lo |
0x1C |
Ayrılmış blok bilgisi |
i_block |
0x28 |
Extent veya blok işaretçileri |
i_dtime |
0x14 |
Silinme zamanı |
Silinmiş dosyada i_links_count sıfır olabilir ve i_dtime doludur. Asıl hazine ise i_block alanındadır. Modern Ext4 çoğunlukla extent kullanır. i_block alanında 0a f3 görürseniz, bu little-endian 0xf30a extent sihirli değeridir.
Extent başlığı kabaca şöyledir:
struct ext4_extent_header {
__le16 eh_magic; // 0xf30a
__le16 eh_entries; // kaç kayıt var
__le16 eh_max;
__le16 eh_depth; // 0 ise yaprak
__le32 eh_generation;
}
eh_depth = 0 ise hemen ardından gerçek extent kayıtları gelir:
struct ext4_extent {
__le32 ee_block; // dosya içi mantıksal blok
__le16 ee_len; // uzunluk
__le16 ee_start_hi; // fiziksel blok üst bitler
__le32 ee_start_lo; // fiziksel blok alt bitler
}
Fiziksel blok hesabı:
\[\text{physical} = (ee\_start\_hi \ll 32) + ee\_start\_lo\]Byte offset ise:
\[\text{byte\_offset} = \text{physical} \times \text{block\_size}\]Veriyi Çekmek
Diyelim extent bize fiziksel blok 250000, uzunluk 12, blok boyutu 4096 dedi. Dosyayı şöyle çıkarabiliriz:
dd if=lab.img of=recovered.bin bs=4096 skip=250000 count=12 status=progress
Bu komut imajdan 12 blok okur ve recovered.bin dosyasına yazar. Dosya parçalıysa her extent ayrı çıkarılır, sonra mantıksal blok sırasına göre birleştirilir.
Btrfs Neden Daha Çetrefilli?
Btrfs’te klasik “inode tablosu” beklentisi boşa düşer. Metadata B-tree yapılarında tutulur; ayrıca Copy-on-Write sayesinde eski sürümlerin izleri kalabilir. Bu harika bir kurtarma şansı sunar ama elle hex ile çözümlemek Ext4’e göre daha zahmetlidir.
| Kavram | Ext4 karşılığı | Btrfs karşılığı |
|---|---|---|
| Inode yeri | Hesaplanabilir tablo | B-tree item |
| Veri adresi | Extent alanı | File extent item |
| Eski veri | Üzerine yazılmadıysa | COW/snapshot ile kalabilir |
| Elle kurtarma | Formülle mümkün | Ağaç yapısı takibi gerekir |
Sonuç
Ext4’te manuel kurtarma; süperbloktan parametreleri okumak, inode adresini hesaplamak, extent kayıtlarını yorumlamak ve fiziksel blokları dd ile çekmekten ibarettir. Btrfs ise daha modern ve güçlüdür ama elle analizde daha fazla ağaç gezmeyi gerektirir. Kısacası: Ext4 düz bir harita, Btrfs ise üç boyutlu labirenttir. İkisi de çözülebilir; yeter ki byte’lar hâlâ yerinde olsun.
Yorumlar