İçeriğe atla
0 XP 0
14 dkderinleşmeyle 16 dk55 XP7 etkinlik

Dosya sistemleri: NTFS ve ext4 temelleri

Bu derste
  • 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.

Soldan bir tane seç, sağdan eşini seç. Kullanılmış bir seçeneği yeniden seçersen yeni öğeye taşınır.

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
fin-pc12 diskinin bölüm haritası. Tek NTFS bölümü 2048. sektörde başlar.

Çı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.

ogrenci@lab

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
fsstat birim başlığını okur. Küme boyutu ve $MFT'nin yeri buradan gelir.

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)
fls dosya adı katmanını, istat tek bir kaydın üstverisini açar. update.exe silinmiş ama kaydı ve kümeleri duruyor.

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
Kayıt-tür-kimlik biçimiyle tek bir akış çekilir. Akış yerleşik veridir, dosya silinse de kayıtta durur.

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
web01 kök biriminde uploads klasöründeki ayar.php dosyasının inode kaydı. Açılı parantez içindeki sayı inode numarasıdır.

Çı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.

Bu derste bir hata mı gördün? Bildir