Adli Bilişimde Veri Kazıma Algoritması
Ham byte akışında özelleştirilebilir başlangıç ve bitiş imzalarıyla bitişik dosya kurtaran carving motorunu açıklar. Trie araması, blok örtüşmesi, aralık çıkarımı ve doğrulama aşamaları incelenir.
File carving, dosya sistemi kayıtlarına başvurmadan ham veri içinden dosya başlangıçlarını, bitişlerini ve biçime özgü yapıları arayarak veri kurtarma işlemidir. Silinmiş dosyanın dizin girdisi, inode kaydı veya küme zinciri bozulmuş olsa bile içerik diskte duruyorsa dosyanın yeniden elde edilmesi mümkün olabilir. NIST de file carving işlevini dosya sistemi metadatası yerine içerikten hareketle dosya arama ve yeniden oluşturma olarak sınıflandırır.
Paylaştığım çekirdek kodu tamamen kendim geliştirdim. Amacım yalnız bilinen birkaç dosya başlığını arayan bir yardımcı program yazmak değildi. Aynı tarama motorunu byte dizileri, seek edilebilir akışlar ve dd gibi araçlarla alınmış ham disk imajları üzerinde kullanabilen, yeni dosya türleri için özelleştirilmiş imzalar ekleyebildiğim bağımsız bir kurtarma katmanı oluşturdum.
Bu çekirdeği kurumsal ve akademik adli bilişim çalışmalarımda gerçek veri üzerinde kullandım. Dosya sistemi üzerinden artık erişilemeyen çok sayıda dosyayı kurtarmamda özellikle özel imza desteği etkili oldu. Hazır araçların tanımadığı kuruma özgü dosya biçimlerinde veya belirli bir yazılımın ürettiği değişmez byte dizilerinde, biçimin gerçek yapısını inceleyip daha seçici başlangıç ve bitiş örüntüleri tanımlayabildim.
Dosya kurtarmadan file carving'e
Klasik silinmiş dosya kurtarma, çoğunlukla dosya sisteminin geride bıraktığı metadata üzerinden ilerler. Dosyanın adı, ilk kümesi, uzunluğu veya küme zinciri korunmuşsa içeriğin yeniden bulunması görece kolaydır. File carving ise bu kayıtların bulunmadığı, bozulduğu veya güvenilir kabul edilmediği durumlarda devreye girer.
File carving yaklaşımı 2000'li yılların başında Foremost ve daha sonra Scalpel gibi araçlarla yaygınlaştı. Foremost, başlangıç ve bitiş değerleri ile iç dosya yapılarını kullanarak doğrudan sürücüler veya dd tarafından oluşturulmuş imajlar üzerinde çalışmak üzere geliştirilmişti. Pal ve Memon'un file carving tekniklerinin gelişimini ele alan çalışması da alanı, metadata tabanlı kurtarmadan içerik ve dosya yapısı tabanlı yeniden oluşturmaya doğru ilerleyen bir araştırma alanı olarak sınıflandırdı.
Benim geliştirdiğim çekirdeğin temel çalışma alanı da ham byte uzayıdır. Girdi bir dosya sistemi nesnesi olarak değil, sıralı byte dizisi olarak görülür:
\[
D = \{d_0,d_1,\ldots,d_{N-1}\}
\]Algoritma için bu dizinin RAM içindeki bir byte dizisinden, bir MemoryStream nesnesinden, büyük bir dosyadan veya fiziksel ortamın bit düzeyinde alınmış kopyısından gelmesi temel mantığı değiştirmez. Girdi yalnızca okunabilir bir akış ve konum bilgisi sağlar.
Ham disk imajı bu kullanım için özellikle değerlidir. NIST, disk imajını serbest alan ve slack alan dahil özgün ortamın bit düzeyindeki kopyası olarak tanımlar. SWGDE de fiziksel edinimin bitstream kopya üretmesini, kaynak ortam üzerinde yazma yapılmamasını ve mümkün olduğunda write blocker kullanılmasını önerir.
Burada önemli bir sınır vardır. File carving çekirdeği bir edinim aracı değildir. Delili kopyalamaz, write blocker görevi görmez ve zincirleme muhafazayı kendi başına sağlamaz. Doğru kullanımda çekirdek, doğrulanmış ham imajın çalışma kopyası üzerinde çalışan analiz katmanıdır.
Özelleştirilebilir imza modeli
Dosya biçimlerinin önemli bir bölümü ayırt edici sabitlerle başlar. JPEG başlangıcı, PNG imzası, PDF başlığı, ELF tanımlayıcısı veya ZIP yerel dosya kaydı buna örnektir. Bazı biçimlerde dosya sonu da tanımlanabilir. JPEG sonlandırıcısı, PNG IEND yapısı veya PDF son işareti bu yaklaşımda kullanılabilir.
Geliştirdiğim modelde her dosya türü kavramsal olarak dört bilgiyle temsil edilir:
Alan İşlev
Uzantı Kurtarılan dosyanın türü Başlangıç imzası Aday dosya başlangıcını belirleyen byte dizisi Bitiş imzası Dosyanın sonunu belirleyen isteğe bağlı örüntü Bitiş uzaklığı Bitiş imzasından sonra dosyaya dahil edilecek byte sayısı
Bitiş uzaklığı küçük fakat önemlidir. Bazı yapılarda bulunan işaret doğrudan dosyanın son byte'ı değildir. İşaretten sonra sabit alanlar veya yapısal bilgiler bulunabilir. Yalnız imzanın sonuna kadar kesmek, görünüşte bulunan fakat biçimsel olarak eksik bir dosya üretebilir.
Kaynak kodda görüntü, belge, arşiv, yürütülebilir dosya, ses, video, ağ paketi yakalama dosyası ve sanal disk gibi farklı aileler için imzalar bulunur. Aynı uzantı için birden fazla başlangıç varyantının tanımlanabilmesi, gerçek dünyadaki kodlayıcı farklılıklarını karşılamak açısından önemlidir. JPEG bunun belirgin örneğidir. Dosyalar ortak başlangıç işaretine sahip olsa da sonraki uygulama belirteçleri farklı olabilir.
Özel imza ekleyebilmek, kurumsal kullanımda hazır tür listesinden daha değerli hale geldi. Bir uygulamanın yalnız kendi ürettiği dosyalarda bulunan sabit yapıyı belirlediğimde, çok genel ve kısa bir imza yerine daha uzun bir örüntü tanımlayabildim. Bu, yanlış pozitifleri azaltırken genel araçların tanımadığı içerikleri kurtarmamı sağladı.
PhotoRec de bilinmeyen biçimler için uzantı, imza uzaklığı ve magic value tanımlanmasına izin verir. Geliştirici düzeyinde daha güvenilir kurtarma için içerik denetimi, uzunluk kontrolü ve footer algılama gibi biçime özgü mekanizmaların gerektiğini özellikle belirtir. Benim çekirdeğimdeki özelleştirme yaklaşımı da aynı temel gerçeğe dayanır: iyi bir imza, yalnız birkaç rastgele byte değil, dosya biçiminin yapısal bilgisidir.
Çoklu örüntü arama motoru
Büyük bir disk imajını her imza için baştan sona taramak verimsizdir. P farklı imza ve N byte uzunluğunda bir kaynak için bağımsız taramalar yaklaşık olarak şu maliyeti oluşturur:
\[
O(PN)
\]Geliştirdiğim çekirdekte bütün başlangıç ve bitiş imzaları ortak bir byte trie yapısında birleştirilir. Aynı byte önekiyle başlayan imzalar ortak geçişleri paylaşır. JPEG varyantları veya ZIP tabanlı biçimler gibi benzer başlangıçlara sahip tanımlar için aynı byte'lar tekrar tekrar karşılaştırılmaz.
Yapı, Aho-Corasick algoritmasının ortak önek fikrine yakındır, ancak tam bir Aho-Corasick otomatı değildir. Başarısızlık bağlantıları oluşturmak yerine tarama her olası başlangıç konumunda trie kökünden başlar ve ilk uyumsuzlukta kesilir. En uzun imza uzunluğu L olmak üzere teorik üst sınır şöyledir:
\[
O(NL)
\]İmzalar kısa ve L sabit olduğunda çalışma süresi pratikte doğrusal davranır:
\[
O(N)
\]Bu tercih, genel metin arama problemindeki teorik en iyi çözümü hedeflemekten çok, sınırlı uzunluktaki ikili imzalar için küçük ve öngörülebilir bir sıcak yol oluşturur. Geçişler byte değerine göre doğrudan erişilen tablolarda tutulduğu için her adım hash hesabı veya karakter karşılaştırma zinciri gerektirmez.
Otomatın hazırlanması yalnız ilk kullanımda yapılır. Hexadecimal imzalar byte dizilerine çevrilir, uzunluklarına göre işlenir ve ortak geçiş tablosu oluşturulur. Daha sonraki disk taramalarında aynı yapı tekrar kullanılabilir. Çok sayıda imajın aynı uygulama sürecinde incelendiği kurumsal işlerde bu başlangıç maliyeti önemsiz hale gelir.
Büyük veride akış tasarımı
Bir disk imajının tamamını RAM'e almak hem gereksiz hem de çoğu zaman mümkün değildir. Çekirdek bu nedenle büyük sabit bloklarla çalışır. Dosya daha küçük ardışık okumalarla ana tarama tamponuna alınır ve imza araması bu tampon üzerinde yürütülür.
Blok tabanlı taramada en önemli hata kaynağı sınır geçişidir. Bir imzanın ilk byte'ları önceki blokta, kalan byte'ları sonraki blokta bulunabilir. Bloklar birbirinden bağımsız aranırsa bu imza kaçırılır.
Bu sorunu en uzun imzanın boyutu kadar örtüşme kullanarak çözdüm. Önceki bloğun son kısmı sonraki bloğun başına taşınır. Böylece iki blok arasına bölünmüş her imza, en az bir tarama penceresinde bütün olarak bulunur.
En uzun imza L, blok uzunluğu B ise her sınırda yeniden incelenen veri yalnız L byte düzeyindedir:
\[
\text{ek tarama oranı} \approx \frac{L}{B}
\]Büyük bloklarda bu oran ihmal edilecek kadar küçüktür. Buna karşılık blok sınırında veri kaybetmeme garantisi sağlar.
Dosya akışı ardışık tarama seçeneğiyle açılır. Bu tercih işletim sistemine okuma örüntüsünün ileri yönlü olduğunu bildirir. Disk imajında geriye doğru rastgele erişim yerine büyük ve ardışık okumalar yapılması, dönen disklerde seek maliyetini azaltır; SSD ve ağ depolamada da ön okuma davranışından yararlanılmasını sağlar.
Byte dizisi için aynı motor bir bellek akışı üzerinde çalışabilir. Genel bir Stream kullanımı ise çekirdeği dosya sistemine veya belirli bir imaj biçimine bağlamaz. Kaynak çözülüp seek edilebilir bir byte akışı olarak sunulduğu sürece arama mantığı değişmez.
Başlangıç ve bitiş eşleştirme
Tarama aşaması bulunan her örüntüyü tür kimliği ve mutlak konumuyla kaydeder. Daha sonra eşleşmeler konuma göre sıralanır. Bir başlangıç işareti görüldüğünde, aynı dosya türünün uygun bitiş işareti ileri yönde aranır.
Arama sınırsız bırakılmaz. Tanımlı üst boyut, bir başlangıcın diskin çok ilerisindeki ilgisiz bir footer ile eşleştirilmesini engeller. Üst sınır aynı zamanda bozuk veya hiç tamamlanmamış dosyalarda gereksiz aramayı azaltır.
Bir dosya aralığı şu şekilde elde edilir:
\[
R=[p_h,\ p_f+l_f+o_f)
\]Burada:
\(p_h\) başlangıç imzasının konumudur.
\(p_f\) bitiş imzasının konumudur.
\(l_f\) bitiş imzasının uzunluğudur.
\(o_f\) biçime özgü bitiş uzaklığıdır.
Sonuç dosyanın tamamını belleğe kopyalamak yerine başlangıç ve bitiş konumlarıyla temsil edilir. Kaynaktaki bu aralık, sınırlandırılmış bir alt akış üzerinden okunabilir. Böylece yüzlerce megabaytlık bir kurtarma için aynı büyüklükte ikinci bir byte dizisi oluşturmak gerekmez.
Bu tasarım, kurtarma ile dışa aktarmayı birbirinden ayırır. Tarama önce adayların kaynak yolu, başlangıç konumu, bitiş konumu ve tür bilgisini üretir. Daha sonra yalnız gerekli adaylar ayrı dosyalara yazılabilir, hash değerleri hesaplanabilir veya biçim doğrulayıcılarına gönderilebilir.
Algoritmik maliyet
Kaynak uzunluğu N, en uzun imza L, bulunan örüntü sayısı M ve üretilen aday dosya sayısı K olsun.
Trie tabanlı taramanın üst sınırı:
\[
O(NL)
\]değerindedir. İmza uzunlukları sabit ve küçük olduğu için fiili davranış O(N) düzeyindedir.
Eşleşmelerin sıralanması:
\[
O(M\log M)
\]maliyet taşır. Tarama zaten ileri yönde yapıldığı için kayıtlar büyük ölçüde sıralı oluşur. Bununla birlikte blok örtüşmeleri ve aynı konumdaki çoklu imzalar nedeniyle son sıralama deterministik bir sonuç sağlar.
Başlangıç ve bitiş eşleştirme maliyeti veri dağılımına bağlıdır. Her başlangıç için tanımlı arama mesafesi içinde ileri tarama yapılır. İmza yoğunluğu düşük gerçek disklerde bu bölüm sınırlı kalır. Kötü niyetle hazırlanmış veya aynı örüntüyü çok sık içeren verilerde maliyet büyüyebilir.
Ana tarama tamponu sabit boyutludur. Buna karşılık bulunan örüntüler inceleme sonuna kadar bellekte tutulduğundan yardımcı alan:
\[
O(M)
\]olur. Çok büyük imajlarda belirleyici unsur imaj boyutundan çok imza eşleşmesi yoğunluğudur. Genel veri kümelerinde bu yaklaşım dengelidir. Aşırı yüksek eşleşme üreten özel ortamlarda sıralı eşleştirme ve parça parça sonuç yazımıyla bellek tüketimi daha da sınırlandırılabilir.
Kurtarılan dosyanın doğrulanması
Bir header ve footer bulunması, aradaki byte dizisinin kesin olarak geçerli bir dosya olduğunu kanıtlamaz. Aynı örüntü başka bir dosyanın gövdesinde, sıkıştırılmış veride veya rastgele byte dizisinde bulunabilir. Bir arşivin içinde gömülü başka dosyaların imzaları da görülebilir.
Bu nedenle carving sonucu bir adaydır. Güven düzeyi aşamalı olarak artırılmalıdır:
- Başlangıç ve bitiş imzası uyumu
- Makul dosya uzunluğu
- Biçime özgü yapısal ayrıştırma
- İç uzunluk, CRC veya checksum alanlarının doğrulanması
- Standart kod çözücüyle açılabilme
- Kaynak konumu ve hash değerinin kayıt altına alınması
Garfinkel, hızlı ve doğru carving işleminin aday byte dizilerini erken doğrulayan veya eleyen çok katmanlı bir karar problemi olarak ele alınmasını önermiştir. JPEG, OLE ve ZIP gibi biçimlerde hızlı nesne doğrulayıcıları bu yaklaşımın önemli parçasıdır.
NIST de silinmiş dosya kurtarmada sonuçların ilgisiz veya fazladan içerik barındırabileceğini ve incelemecinin kullanılan aracın sınırlamalarını anlaması gerektiğini belirtir. Dosya kurtarma sonuçlarının sınıflandırılması ve doğrulanmasına yönelik standart bir terminoloji önerilmesinin nedeni de aday, doğrulanmış dosya ve hatalı kurtarma gibi sonuçların birbirine karıştırılmasını önlemektir.
Kurumsal kullanımımda yalnız dosyanın açılmasıyla yetinmedim. Kaynak imaj, mutlak byte aralığı, dosya türü ve gerektiğinde hash değeri birlikte değerlendirilmelidir. Kurtarılan içeriğin delil değeri, algoritmanın dosyayı bulmasından değil, bütün sürecin tekrarlanabilir ve denetlenebilir olmasından gelir.
Bitişik dosyalar ve parçalanma sınırı
Bu çekirdek esas olarak bitişik yerleştirilmiş dosyaları kurtarır. Başlangıç ile bitiş arasındaki byte aralığının aynı dosyaya ait olduğunu varsayar. Dosya parçalanmışsa araya başka bir dosyanın veya serbest alanın girmesi mümkündür. Header-footer yöntemi bu durumda yanlış içerik birleştirebilir veya geçerli footer'ı hiç bulamayabilir.
NIST, başlangıç ve bitiş yapıları kolay tanınan ve bitişik yerleştirilmiş dosyalarda carving işleminin basit olduğunu, parçalanmanın ise problemi önemli ölçüde zorlaştırdığını vurgular. Akademik çalışmalar parçalanmış dosyalar için biçim doğrulama, küme benzerliği, olası parça sıralaması ve decoder geri bildirimi gibi daha karmaşık yöntemler geliştirmiştir.
Bu sınır, geliştirdiğim algoritmanın başarısıyla çelişmez. Gerçek vakalarda çok sayıda silinmiş dosya halen bitişik kümelerde bulunabilir. Özellikle küçük ve orta boyutlu görüntüler, belgeler, arşivler ve uygulama çıktılarında imza tabanlı bitişik carving yüksek verim sağlayabilir.
Algoritmanın başarısını artıran diğer unsur özel imzalardır. Genel bir dosya türünün parçalanmış örneklerini çözmeye çalışmak yerine, inceleme konusu sistemin ürettiği özgül ve bitişik kayıtları yüksek seçicilikle bulmak birçok kurumsal olayda daha etkili olabilir.
Deneyimin teknik karşılığı
Bu çekirdeği geliştirirken file carving problemini yalnız dosya başlığı listesi olarak ele almadım. Ortaya çıkan yapı birkaç ayrı mühendislik kararının birleşimidir:
Girdi kaynağından bağımsız akış modeli
Büyük dosyalar için sabit boyutlu blok taraması
Blok sınırlarında imza kaybını önleyen örtüşme
Ortak önekleri birleştiren çoklu örüntü otomatiği
Başlangıç ve bitiş işaretlerinin tek taramada bulunması
Dosya türüne özgü footer uzaklığı
Sınırsız yanlış eşleştirmeyi önleyen arama sınırı
Kurtarılan aralığı kopyalamadan sunan alt akış
Yeni ve kuruma özgü biçimlere genişletilebilen imza tanımı
Kurumsal ve akademik adli bilişim çalışmalarımda çok sayıda dosyayı kurtarabilmem, tek başına kısa bir magic value listesinden kaynaklanmadı. Başarılı sonuçlar, incelenen sistemin dosya biçimini anlamak, doğru imzayı seçmek, gereksiz kısa örüntülerden kaçınmak ve çıkan adayları biçimsel olarak doğrulamakla mümkün oldu.
Geliştirdiğim çekirdek, genel amaçlı bir dosya sistemi kurtarma paketi veya parçalanmış dosyaları otomatik birleştiren akıllı carver değildir. Teknik olarak daha doğru konumu, özelleştirilebilir imzalarla çalışan, akış tabanlı, bitişik dosya kurtarmaya odaklanmış yüksek kapasiteli bir carving motorudur.
Bu sınırları açık biçimde tanımlamak adli bilişim açısından önemlidir. Bir aracın neyi başarıyla yaptığı kadar neyi yapmadığı da bilinmelidir. Kendi çalışmalarımda elde ettiğim verimli sonuçların temelinde de bu yaklaşım vardı: dosya sisteminden bağımsız arama, kuruma özgü biçim bilgisi, kontrollü aralık çıkarımı ve sonucun ayrı bir doğrulama aşamasına tabi tutulması.