Harry Potter ve Dosyalarla Oynanmanın Saptanması
“Harry Potter ve Melez Prens” kitabında Dumbledore Harry’ye şöyle der: “Profesör Slughorn’un bana ilettiği anılar onun tarafından
değiştirilmiş.”
Potter sorar: “İyi de niye böyle bir şey yaptı ki?”
Dumbledore: “Çünkü
anımsadıklarından utanıyor. Bize kendini daha iyi ve masum göstermek için
belleğin bazı kısımlarını sildi, değiştirdi. Fark edebileceğin gibi bunu biraz
kaba-saba yapmış”
Bellek dosyasının değiştirildiğinin Dumbledore tarafından nasıl saptandığını bilmiyoruz. Ama Powershell içindeki “hash”
komutlarını kullanarak dosyaların değiştirilip değiştirilmediğini
anlayabiliriz.
Ama öncelikle “hash” nedir?
“Hash” (“Özet”) geçmişten
aşina olduğumuz CRC mekanizmasının daha gelişmiş bir şekli.
Floppy disklerle,
disketlerle iş yaptığımız dönemlerde, disk üzerindeki verinin bozuk olduğuna
işaret eden CRC hataları alırdık. Şimdi giderek daha az alıyoruz.
CRC Cyclic Redundancy Check sözcüklerinin
kısaltması ve verinin sağlam olup olmadığını görmek için veriye ek bir bilginin
eklenmesi anlamına geliyor.
CRC mekanizmasında, bir veri bloğu içindeki veriler
(verilerin sayısal gösterimi) toplanıyor ve belli bir sayıya bölünüyor. O
sayıya P diyelim. Bölüm işleminin sonucunda “kalan”, veri bloğunun sonuna
ekleniyor, veri bu şekilde iletiliyor ya da disk üzerinde tutuluyor. Sonra,
veri diskten okunurken ya da karşı tarafta alındığında veri bloğu toplamı
tekrar yapılıyor, bu toplam P’ye bölünüyor, kalan bulunuyor ve bu kalanın veri
bloğu sonundaki CRC değeriyle aynı olup olmadığına bakılıyor. Eğer aynıysa veri
bozulmamış demektir. Aynı değilse veride bir bozulma, oynama vardır.
Bir örnekle durumu açıklayalım:
P değeri 17 olsun, blok içindeki veriler de şu şekilde
olsun: 90 69 66 82 65 79 78 69.
Verilerin toplamı 598 olur, bunu P değeri olan 17 ile
bölersek kalan 3 olur. Bu “3” değerini veri bloğunun sonuna ekleriz.
Veriyi diskten okurken ya da karşı tarafa
gönderdiğimizde veri bloğu tekrar toplanacak, 17’ye bölünecek, kalan
bulunacaktır. Eğer bu hesaplanan kalan veri bloğunun arkasındaki CRC değeriyle
aynıysa o zaman verinin değişmediğini ya da bozulmadığını varsayabiliriz.
Veride bir bozulma ya da değişiklik olduğunu
düşünelim. Örneğin, 82 yerine 43 okuduğumuzu düşünelim. O zaman bloğu
topladığımızda toplam 559 çıkacak, 17’ye böldüğümüzde kalan 15 olacak, bu da
bloğun sonundaki CRC değeriyle uyuşmayacaktır. Yani, veri bozulmuştur.
CRC metodu yanılmaz değildir. Eğer veri bloğu P’nin
katları kadar bozulursa CRC hatayı saptayamaz. Ama P değerini daha hassas
seçerek hataların çoğunu (hiçbir zaman hepsini değil) saptayabiliriz.
Gördüğünüz gibi CRC değeri verinin tamamına karşılık
gelmez. CRC değeri veriye ilişkindir, veri için benzersizdir ama CRC’ye bakarak veriyi bulamazsınız. CRC basittir de; CRC değerine ve P değerine bakarak veri toplamı için
çeşitli seçenekleri hesaplayabiliriz.
CRC veri iletiminde gürültüden kaynaklanan hatalara ya
da disk ortamı üzerindeki hatalara karşı halen kullanılıyor. CRC verinin
bozulup bozulmadığını saptıyor ama bir güvenlik (security)
mekanizması değil. Üçüncü partiler veriyi okuyabilir (CRC değeri dahil olmak
üzere).
“Hash” (“Özet”) yöntemi çok
daha gelişmiş bir yöntem. En önemli farkı, 1 Baytlık veri-dosya için de, 1 MB’lık veri-dosya için de aynı uzunlukta hash değeri üretiyor oluşu. Bu yüzden “hash”in
karşılık geldiği verinin ne olduğunu, neye benzediğini tahmin etmek çok zor. Hash değeri dosya ya da veriyle gönderilebilir ama bu
zorunlu değil. Örneğin, dosyaların hash değerlerini
bir kez üretip saklayabiliriz, sonra dosyaların güncel hallerinin hash değeriyle bu saklanan değerleri karşılaştırıp
dosyaların değiştirilip değiştirilmediğini bulabiliriz.
Powershell get-filehash komutu dosyalar için hash
değeri üretir. Bu komutu tek bir dosya için ya da çok sayıda dosya için
kullanabiliriz. Aşağıdaki resme bakalım:
Bu resimde, E:ProfsMemories
klasöründeki dosyaların hash değerini üretiyoruz.
İkinci komuttan önce Slughorn.txt dosyasının adını
SlughornNew.txt şeklinde değiştiriyorum ama gördüğünüz gibi hash
değeri aynı kalıyor.
Üçüncü komuttan önce SlughornNew.txt dosyasında küçük
bir değişiklik yapıyorum ve dosyanın hash değerinin
değiştiğini görüyorum.
Hash işlemi
dosyaların adına değil içeriğine bağlı.
Şimdi hash değerinin ne
olduğunu öğrendiğimize göre dosyalara yönelik bir çözüm geliştirebiliriz.
İlk yapacağımız şey, dosyaların şu anki hash değerlerini bir dosyaya aktarmak. Bu dosya bizim için
ileride yapacağımız karşılaştırmalara temel oluşturacak.
İlgili komut şu şekilde:
Get-ChildItem e:profsmemories | get-filehash | select path,hash | export-csv filelist.csv
Yaratılan dosyayı yalnızca bizim erişebildiğimiz bir
yerde ve aşağıdaki betiğin çalıştırıldığı yerde tutacağız:
$filehashes=@{}
import-csv filelist.csv
| foreach{$filehashes.add($_.path,$_.hash)}
$files=Get-ChildItem
e:profsmemories
foreach ($file in $files)
{
$lookfile=$file.fullname
$lookfilehash=(get-filehash $lookfile).hash
$resulthash=($filehashes.GetEnumerator() | where {$_.name -eq $lookfile}).value
#write-host “sıradaki dosya”,$lookfile,$lookfilehash,$resulthash
if ($lookfilehash -ne $resulthash) {write-host $lookfile,”changed”}
}
Betiğin birinci satırında bir hash
tablosu tanımlıyoruz ve ikinci satırda içini filelist.csv dosyasının içeriği
ile dolduruyoruz. Hash tablolaları
arama için bize kolay bir yol sunuyor ama bu tablonun kendisini dosyaların hash değeri ile karıştırmayalım.
Üçüncü satırda $files
şeklinde bir değişken tanımlıyoruz ve klasör içindeki dosyaların adlarını bu
değişkende topluyoruz.
Foreach döngüsünde $files değişkenindeki adları teker teker alıyoruz, her dosya
için bir hash değeri üretiyoruz ve bu değeri hash tablosunda saklanan orijinal değerle
karşılaştırıyoruz. Eğer bu iki değer aynı değilse dosyada değişiklik yapılmış
demektir, dosyanın adını raporluyoruz.
Dumbledore bu betiği
periyodik olarak çalıştırarak dosyalarla oynanıp oynanmadığını anlayabilir.
Eğer kendisi dosyalarda bir değişiklik yapacaksa, değişikliklerden sonra ilk
komutu çalıştırıp temel dosyayı tazeleyebilir.
Dumbledore için neler
yapmıyoruz ki.