Dosya sistemleri: NTFS ve ext4 temelleri
- Sleuth Kit ile bölüm tablosunu, NTFS $MFT kaydını ve ext4 inode yapısını oku. Ofseti doğru hesapla. Gizli veri akışını bulmayı öğren.
- Bu derste fin-pc12 imajında bölüm ofsetini hesaplayacak, bir $MFT kaydını ve web işaretini çözecek, web01 imajında da bir inode açacaksın.
- Defteri tanımadan silinen dosyayı da kurtaramazsın, zaman damgasını da yorumlayamazsın.
Puan bütün etkinlikleri cevaplayınca hesaba yazılır. Bu dersi tamamlayınca +55 XP alacaksın. Giriş yapmadan ilerlersen puan yalnız bu tarayıcıda durur.
Disk aslında numaralı bloklardan ibarettir. Dosya adı, klasör ya da tarih diskin yüzeyinde yazmaz. Bunları dosya sistemi denen bir defter tutar.
Adli analizde bulduğun hemen her şey bu defterden okunur: silinen dosyanın adı, bir programın diske düştüğü saat, gizlenmiş bir veri akışı. Bu derste mkaya kullanıcısının fin-pc12 makinesinden alınan imajı katman katman açacaksın.
Önce iki defteri tanıyacaksın: Windows'un NTFS'i ve Linux'un ext4'ü. Sonra bölüm tablosundan ofseti hesaplayacak, bir $MFT kaydının içine girecek ve web01 sunucusunun imajında bir inode okuyacaksın. Bu işi Sleuth Kit ve e2fsprogs araçlarıyla yapacaksın.
İki defter: $MFT ve inode tablosu
NTFS'te her şey dosyadır, defterin kendisi de. Ana dosya tablosu (Master File Table) kısaca $MFT adını taşır. Birimdeki her dosya ve klasör için en az bir kayıt açar.
Kayıt çoğu birimde 1024 bayttır ve FILE imzasıyla başlar. Kaydın numarası dosyanın kimliğidir. Başlıkta bir de sıra numarası durur.
Kayıt boşaltılıp yeniden kullanıldıkça bu sayı artar, böylece 812 numaralı kaydın bugünkü sahibini dünkü sahibinden ayırırsın. Tablonun ilk kayıtları sistem dosyalarına ayrılır. 0 numara $MFT'nin kendisidir, 1 numara tablonun başını yedekleyen $MFTMirr, 2 numara işlem günlüğü $LogFile, 5 numara kök klasördür. Tablonun başı bozulursa kurtarma $MFTMirr kopyasından başlar.
Her kayıt özniteliklerden oluşur. $STANDARD_INFORMATION zaman damgalarını ve dosya bayraklarını tutar. $FILE_NAME dosyanın adını ve üst klasörünü tutar. $DATA ise içeriği ya da içeriğin diskteki yerini tutar.
Silinen dosyanın adı, kaydı başka bir dosyaya verilene kadar $FILE_NAME içinde bekler. NTFS değişiklikleri ayrıca günlüğe yazar. $LogFile yarım kalan işlemleri geri almak için tutulur. $Extend klasöründeki $UsnJrnl ise hangi dosyanın ne zaman ve neden değiştiğini sırayla kaydeder.
Dosya silinse bile adı bu günlüklerde bir süre yaşar. Aynı kayıt iki ayrı klasör girdisinden de gösterilebilir. Buna sert bağ (hard link) denir. Dosya tektir, adı ikidir ve bir adı silmek içeriği silmez.
ext4 tarafında defterin adı inode tablosudur. inode dosyanın boyutunu, sahibini, iznini, zaman damgalarını ve blok adreslerini tutar. Dosya adı inode'da durmaz.
Ad, üst klasörün veri bloğundaki dizin girdisinde yazar ve oradan inode numarasını gösterir. Birimin genel bilgisi superblock içindedir: blok boyutu, inode sayısı, son bağlanma zamanı ve günlük ayarları.
ext4 üstveri değişikliklerini jbd2 günlüğüne yazar. Bu fark kurtarmayı doğrudan etkiler. NTFS'te silinen dosyanın adı kayıtla birlikte bekler. ext4'te dizin girdisi ile inode arasındaki bağ çabuk kopar, bu yüzden adı içerikle eşleştirmek daha zordur.
Etkinlik 1 / 7
NTFS'te bütün dosya kayıtlarını tutan ana tablonun adı nedir? ____
Etkinlik 2 / 7
Yapıyı ait olduğu dosya sistemiyle eşleştir.
Bölüm tablosu ve ofset hesabı
Dosya sistemine ulaşmadan önce diskin bölüm haritasını okursun. Eski düzenin adı MBR'dir (Master Boot Record) ve diskin ilk 512 baytını kaplar. İlk 446 bayt önyükleme kodudur. Ardından her biri 16 bayt olan dört bölüm girdisi gelir.
Son iki bayt 55 AA imzasıdır ve bu imza yoksa araçlar tabloyu tanımaz. MBR sektör adresini 32 bitle yazar, 512 baytlık sektörlerde bu sınır yaklaşık 2 TB eder.
Yeni düzen GPT (GUID Partition Table) bu sınırı kaldırır. 0. sektörde koruyucu bir MBR durur, GPT başlığı 1. sektördedir ve bölüm girdileri onu izler.
Başlığın bir yedeği diskin son sektöründe saklanır. Bozulmuş bir GPT'yi bu yedekten okursun.
Derinleş:MBR'den GPT'ye: 63. sektörden 2048. sektöre
MBR bölüm tablosu 1983'te PC DOS 2.0 ile geldi. O dönemin diskleri silindir, kafa ve sektör (CHS) düzeniyle adreslenirdi.
Bir izde en çok 63 sektör bulunduğu için ilk bölüm uzun yıllar 63. sektörden başladı. Windows XP de bu düzeni kullandı.
Windows Vista ile ilk bölüm 1 MB sınırına, yani 2048. sektöre hizalanmaya başladı. Sebep performanstır: 4096 baytlık fiziksel sektörlü disklerde ve SSD'lerde hizasız bir küme iki fiziksel sektöre taşar ve her yazma yavaşlar. Bu tarihçe adli analizde de işe yarar.
İmajda ilk bölüm 63. sektörde başlıyorsa disk büyük olasılıkla eski bir sistemde bölümlenmiştir. GPT ise Intel'in 1990'ların sonunda başlattığı EFI çalışmasından doğdu ve bugün UEFI belirtiminin parçasıdır.
Her bölüm kendine özgü bir GUID taşır. Başlık ve girdi dizisi CRC32 sağlama değeriyle korunur. Araç sağlama değeri tutmayan başlığı bozuk sayar ve diskin sonundaki yedeğe geçer.
$ mmls fin-pc12.dd
DOS Partition Table
Offset Sector: 0
Units are in 512-byte sectors
Slot Start End Length Description
000: Meta 0000000000 0000000000 0000000001 Primary Table (#0)
001: ------- 0000000000 0000002047 0000002048 Unallocated
002: 000:000 0000002048 0976771071 0976769024 NTFS / exFAT (0x07)
003: ------- 0976771072 0976773167 0000002096 UnallocatedÇıktıyı satır satır oku. Units satırı birimin 512 baytlık sektör olduğunu söyler. Meta satırı bölüm tablosunun kendisidir.
İlk Unallocated satırı 0 ile 2047 arasındaki boşluktur, çünkü modern kurulum ilk bölümü 1 MB sınırına hizalar. 002 numaralı satır NTFS bölümüdür: 2048. sektörde başlar ve 976769024 sektör sürer. Sleuth Kit araçları ofseti sektör olarak ister, bu yüzden fls ve istat komutlarına -o 2048 verirsin.
Linux'un mount komutu ise bayt ister: 2048 × 512 = 1048576. İmajı salt okunur bağlamak için mount -o ro,loop,offset=1048576 yazarsın. Son Unallocated satırını da atlama. Bölümlerin dışında kalan sektörler hiçbir dosya sistemine ait değildir ve veri saklamak için kullanılabilir.
Etkinlik 3 / 7
fin-pc12.dd imajındaki bölüm tablosunu listele.
Etkinlik 4 / 7
fin-pc12.dd imajında NTFS bölümü 2048. sektörde başlıyor, sektör 512 bayt. mount -o ro,loop,offset=____ komutuna yazacağın bayt ofseti kaçtır?
$MFT kaydının içi: öznitelik ve yerleşik veri
Bölümü bulduktan sonra dosya sistemi tipini varsayma, ölç. fsstat birimin başlığını okur. Aşağıdaki çıktıda dosya sistemi tipi, birim seri numarası, kayıt boyutu, küme boyutu ve $MFT'nin başladığı küme durur.
Küme boyutu 4096 bayttır. 1000 baytlık bir dosya bile tam bir küme kaplar ve artan 3096 baytta kümenin önceki sahibinden kalan veri durabilir. Birim seri numarasının son sekiz hanesi, yani 2C8EF6B1, LNK ve Prefetch dosyalarında da geçer.
Bir dosyanın hangi birimden açıldığını bu sayı bağlar. Version satırında Windows XP yazması seni şaşırtmasın. Sleuth Kit, XP ile gelen NTFS 3.1 sürümünü böyle adlandırır ve bugünkü Windows sürümleri de aynı sürümü kullanır.
$ fsstat -o 2048 fin-pc12.dd FILE SYSTEM INFORMATION -------------------------------------------- File System Type: NTFS Volume Serial Number: 5A2C8F1E2C8EF6B1 OEM Name: NTFS Volume Name: Windows Version: Windows XP METADATA INFORMATION -------------------------------------------- First Cluster of MFT: 786432 First Cluster of MFT Mirror: 2 Size of MFT Entries: 1024 bytes Size of Index Records: 4096 bytes Range: 0 - 412416 Root Directory: 5 CONTENT INFORMATION -------------------------------------------- Sector Size: 512 Cluster Size: 4096 Total Cluster Range: 0 - 122096126 Total Sector Range: 0 - 976769022
Her öznitelik türü bir sayı taşır. $STANDARD_INFORMATION 0x10 yani 16, $FILE_NAME 0x30 yani 48, $DATA 0x80 yani 128 numaradır. Klasörler içeriklerini $INDEX_ROOT (144) ve $INDEX_ALLOCATION (160) içinde tutar. Bu sayıları fls çıktısının her satırında görürsün.
r/r 812-128-3 gösterimi üç parçadır: 812 kayıt numarası, 128 öznitelik türü yani $DATA, 3 ise bu özniteliğin kayıt içindeki kimliğidir. Baştaki r/r türü iki kez yazar. İlki dizin girdisine, ikincisi üstveriye göredir.
Yıldız silinmiş girdiyi gösterir. (realloc) etiketi ise adın eski olduğunu, kaydın artık başka bir dosyaya verildiğini söyler. O satırın zaman damgaları yeni sahibe aittir.
$ fls -r -p -o 2048 fin-pc12.dd | grep -E 'butce|update|fatura|kargo' r/r 41-128-1: Users/mkaya/Documents/butce.xlsx r/r * 812-128-3: Users/mkaya/AppData/Local/Temp/update.exe -/r * 913-128-1: Users/mkaya/Downloads/fatura.pdf.js -/r * 913-128-4: Users/mkaya/Downloads/fatura.pdf.js:Zone.Identifier r/r * 1377-128-1(realloc): Users/mkaya/Downloads/kargo_takip.zip $ istat -o 2048 fin-pc12.dd 812 MFT Entry Header Values: Entry: 812 Sequence: 5 $LogFile Sequence Number: 2204811376 Not Allocated File Links: 1 [... zaman damgası satırları ...] Attributes: Type: $STANDARD_INFORMATION (16-0) Name: N/A Resident size: 72 Type: $FILE_NAME (48-2) Name: N/A Resident size: 86 Type: $DATA (128-3) Name: N/A Non-Resident size: 1458176 init_size: 1458176 2618880 2618881 2618882 2618883 2618884 2618885 2618886 2618887 (... toplam 356 küme)
Küçük dosyalar ayrı bir küme bile kullanmaz. İçerik $DATA özniteliğiyle birlikte kaydın içine yazılır. Buna yerleşik (resident) veri denir.
1024 baytlık kayıtta başlık ve öteki öznitelikler de yer kapladığı için sınır yaklaşık 700 bayttır. Kesin sayı ad uzunluğuna ve öznitelik sayısına göre değişir. Bu yüzden küçük bir metin dosyası silinse bile kaydında tam olarak durabilir.
Büyük dosyada istat Non-Resident yazar ve içeriğin durduğu kümeleri listeler. update.exe 1458176 bayttır ve 356 kümeye yayılır. NTFS bu listeyi kayıtta veri çalışması (data run) denen kısa bir biçimde tutar: başlangıç kümesi ve uzunluk. Parçalı dosyanın her parçası ayrı bir çalışma olur.
Derinleş:Veri çalışmasını elle çözmek
update.exe kaydının $DATA özniteliğinde şu baytlar durur: 32 64 01 00 F6 27 00. İlk bayt başlıktır ve iki yarıya bölünür. Sağdaki yarı (2) uzunluk alanının kaç bayt olduğunu, soldaki yarı (3) başlangıç alanının kaç bayt olduğunu söyler.
Sonraki iki bayt uzunluktur: 64 01, küçük uçlu (little-endian) okununca 0x0164 yani 356 küme eder. Ardından gelen üç bayt başlangıçtır: 00 F6 27, yani 0x27F600 ve onluk düzende 2618880. istat çıktısındaki ilk küme de budur. Sondaki 00 baytı listenin bittiğini gösterir.
Dosya parçalı olsaydı ikinci bir çalışma gelirdi. Dikkat edilecek nokta şudur: ikinci ve sonraki çalışmaların başlangıç değeri mutlak değildir. Bir önceki çalışmanın başlangıcına göre işaretli bir farktır ve eksi de olabilir.
Başlangıç alanı hiç olmayan çalışma ise seyrek (sparse) bölgedir, diskte yer kaplamaz ve sıfır okunur. Araçlar bu hesabı senin yerine yapar. Elle çözebilirsen bozuk bir kayıtta aracın neden hata verdiğini anlarsın.
Etkinlik 5 / 7
NTFS'te 300 baytlık bir metin dosyasının içeriği nerede durur?
Alternatif veri akışı ve web işareti
Alternatif veri akışı (Alternate Data Stream, ADS) NTFS'e özgüdür. Bir dosya asıl içeriğinin yanında adlandırılmış ikinci bir $DATA taşıyabilir. Gezgin bu akışı göstermez, boyut sütunu da yalnız asıl içeriği sayar.
Saldırgan araçlarını bu yüzden buraya saklayabilir (MITRE ATT&CK T1564.004). Aynı özellik analiste de kanıt bırakır. Tarayıcı ve e-posta istemcisi internetten gelen dosyaya Zone.Identifier adlı bir akış ekler. Buna web işareti (Mark of the Web) denir.
fls çıktısında akış, dosya adına iki nokta ile eklenmiş ayrı bir satırdır. Türkçe Windows'ta Gezgin İndirilenler yazar ama diskteki klasörün adı Downloads'tır. Aşağıda silinmiş fatura.pdf.js dosyasının akışını kayıt ve öznitelik kimliğiyle çekiyorsun.
$ icat -o 2048 fin-pc12.dd 913-128-4 [ZoneTransfer] ZoneId=3 ReferrerUrl=https://posta.altaykargo.example/ HostUrl=https://cdn-update-srv.example/f/fatura.pdf.js
ZoneId=3 İnternet bölgesi demektir. 0 yerel makine, 1 yerel intranet, 2 güvenilen siteler, 4 kısıtlı sitelerdir.
HostUrl dosyanın indirildiği adresi, ReferrerUrl ise bağlantının tıklandığı sayfayı verir. Bu dört satır zincirin ilk halkasını gösterir: mkaya dosyayı kurum posta sayfasındaki bir bağlantıdan cdn-update-srv.example adresinden indirdi. Canlı sistemde aynı akışları dir /r komutu listeler.
Savunma tarafında Sysmon'un 15 numaralı olayı (FileCreateStreamHash) adlandırılmış akış oluşunca kayıt düşer ve içeriğin özetini yazar. Bu olayı merkezî kayıt sistemine gönderen kurum, indirilen dosyanın kaynağını makineye dokunmadan görür. Toplu incelemede MFTECmd $MFT dosyasını CSV'ye çevirir. InUse, HasAds ve IsAds sütunlarıyla silinmiş ya da akış taşıyan kayıtları hızla süzersin.
Etkinlik 6 / 7
fls çıktısındaki bu satır için hangisi doğrudur?
Önce kodu oku, sonra çıktıyı seç.
-/r * 913-128-4: Users/mkaya/Downloads/fatura.pdf.js:Zone.Identifier
ext4 tarafı: inode, kapsam ve dizin girdisi
Linux sunucularda karşına çoğunlukla ext4 çıkar. Birim blok gruplarına bölünür ve her grup kendi inode tablosunu taşır. inode kaydı varsayılan olarak 256 bayttır.
Bazı numaralar ayrılmıştır: 2 kök klasör, 8 günlük, 11 ise lost+found klasörüdür. Blok adresleri kapsam (extent) yapısında durur. Kapsam tek tek blok yazmak yerine bir aralık tutar: şu bloktan başla, şu kadar blok say.
Tek kapsam, 4096 baytlık bloklarla 128 MB'a kadar yer tanımlar. Büyük dosya böylece kısa bir kayıtla anlatılır, ama parçalı dosyada kapsam ağacını izlemen gerekir. ext4 doğum zamanını crtime alanında saklar ve damgaları nanosaniye inceliğinde yazar.
$ TZ=UTC debugfs -R 'stat <2360941>' web01-kok.img Inode: 2360941 Type: regular Mode: 0644 Flags: 0x80000 Generation: 2451736081 Version: 0x00000000:00000001 User: 33 Group: 33 Project: 0 Size: 3418 File ACL: 0 Links: 1 Blockcount: 8 Fragment: Address: 0 Number: 0 Size: 0 ctime: 0x6aa73bdf:2a8c7e10 -- Mon Sep 14 00:12:15 2026 atime: 0x6aa73bdf:2a8c7e10 -- Mon Sep 14 00:12:15 2026 mtime: 0x6aa73bdf:2a8c7e10 -- Mon Sep 14 00:12:15 2026 crtime: 0x6aa73bdf:2a8c7e10 -- Mon Sep 14 00:12:15 2026 Size of extra inode fields: 32 Inode checksum: 0x8c1f02ab EXTENTS: (0):9486337
Çıktıyı satır satır oku. Type ve Mode dosyanın düzenli bir dosya olduğunu ve 0644 izni taşıdığını söyler. Flags: 0x80000 inode'un kapsam kullandığını gösterir. User 33, Debian ve Ubuntu'da web sunucusunun çalıştığı www-data hesabıdır, yani dosyayı web sunucusu yazmıştır.
Dört damga aynı anı gösterir, crtime satırı doğumdur. Her damganın solundaki onaltılık sayı Unix zamanıdır, iki noktadan sonraki ek alan nanosaniyeyi ve iki dönem bitini taşır. EXTENTS satırı içeriğin tek bir blokta, 9486337 numarada durduğunu söyler. Komutu TZ=UTC ile çalıştırdın, çünkü debugfs saati analiz makinesinin saat dilimine çevirir.
Dosya adı bu çıktıda yoktur. Adı üst klasörün dizin girdisinden okursun. debugfs'in ls komutu ya da fls bu girdileri listeler.
USB bellek ve hafıza kartlarında FAT32 ile exFAT sık görülür. Bu sistemler çok daha az üstveri tutar: izin yoktur, sahip yoktur. FAT32 erişim zamanını yalnız tarih olarak saklar ve damgaları UTC yerine yerel saatle yazar.
Analiz penceresi bu yüzden dardır. Hangi dosya sistemiyle çalışırsan çalış sırayı koru: önce bölümler, sonra dosya sistemi tipi, sonra dizin ağacı. Doğrudan anahtar kelime aramaya atlamak zaman kazandırmaz.
Bulduğun baytın hangi dosyaya ait olduğunu söyleyemezsin. Autopsy arayüzü de alttan aynı Sleuth Kit kitaplığını kullanır. Komut satırını bilen analist, arayüzün gösterdiği sonucu denetleyebilir.
Etkinlik 7 / 7
Doğru mu, yanlış mı?
ext4'te dosya adı inode yapısının içinde saklanır.
Okumayı istediğin sırayla sürdürebilirsin. Ders, bütün etkinlikleri cevapladığında tamamlanır.
- Etkinlik 1· İki defter: $MFT ve inode tablosu
- Etkinlik 2· İki defter: $MFT ve inode tablosu
- Etkinlik 3· Bölüm tablosu ve ofset hesabı
- Etkinlik 4· Bölüm tablosu ve ofset hesabı
- Etkinlik 5· $MFT kaydının içi: öznitelik ve yerleşik veri
- Etkinlik 6· Alternatif veri akışı ve web işareti
- Etkinlik 7· ext4 tarafı: inode, kapsam ve dizin girdisi