Diskin yapısı şu şekildedir.
Yukarıdaki şekilde gördüğünüz gibi disklerin üzerindeki dairesel izlere Track veya cylinder denir. Birden fazla disk kullanılırsa bunlar üzerindeki okuyucu kafalara ise head okudukları yüze Side denmektedir. Bir dairesel iz açısal olarak eş bölümlere ayrılmıştır. Bu bölümlere ise Sector denmektedir. Bütün bunlar göz önüne alındığında bir bilginin adresini vermek için kafa veya yüz numarası, izin numarası ve sektor numarası verilmelidir. Genel olarak bir track üzerinde bir sektörün belirlediği alan 512 byte'tır. Ancak bazı SCSI disklerde bu boyut değişebilmektedir. Bir disk üzerindeki
Sektör_Sayısı = (Kafa_Sayısı x Silindir_Sayısı x Sektor_Sayısı)
Bu rakamla bir sektörün boyutu çarpıldığında diskin kapasitesi bulunur.
Diske erişimi kolaylaştırmak için sektörler gruplanarak CLUSTER'lara bölünür. Cluster sektörden farklıdır. Ve formatlama esnasında bir cluster'ın kaç sektör olacağı belirlenir. Mesala bir cluster 8 sektörden oluşuyorsa cluster boyutu 4 KB olarak belirlenir.
Diskin üzerinde belli bloklar vardır. Bunlar
Partition: Partition disk üzerindeki bölümlendirme için kullanılır. Diskin 0. Sektör, 1. Cylinder, 0. Head'de bulunur. Burada bir kod bulunur. Bu kod üzerindeki bilgileri inceleyerek diskin üzerindeki boot sector bulunur. Boot sector belleğe yüklenir. Daha sonra buradaki kod sistemi yükler.
Boot: Her partition'ın başlangıç adresi olarak verilen adreste bulunur. Buradaki bilgi Partition'daki kod tarafından belleğe alınır. Buradaki program önce root dizine bakar. Burada IO.SYS, IO.COM isimli dosyalar aranır. Burada eğer bulunursa FAT'teki başlangıç noktasına gidilir. Buradan bir sonraki devam edeceği yer tespit edilir. Ve okunan Fat başlangıç adresinden data bloğu üzerindeki bilgi okunarak belleğe alınır. Sonrasını ise IO.SYS halleder.
FAT: (File Allocation Table) Burası tüm diskin yerleşim planını içerir. Bir kodla başlar bu FAT'in özelliğini belirtir. Genelde 0F8h değerini taşır. Buna Media Id Byte denir. Herhangi bir sakatlık durumuna karşı FAT 2 kopyadır. Silinen dosyanın adının ilk harfi alt-229 (sigma) yapılır. Dos baktığında eğer ilk harfi sigma ise dosyanın silindiğini kabul ederek bunu listelemez. Silinen bir dosyanın geri getirilmesi işlemi ise şu şekildedir. Dosyanın kaydındaki Fat'teki başlangıç noktası bilgisi alınır. Bu noktadan itibaren dosya boyunu kapsayacak sayıdaki Fat hücresi eğer boş ise dosya geri getirilebilir. Değilse getirilemez. Eğer dosya bölük pörçük yani dosyanın bölümleri diskin bir kaç bölgesinde yer alıyorsa dosya bozuk olarak undelete yapılabilir. Aşağıda örnek bir Root yapısı ve dosyaların yerlerini gösteren bir FAT görülmektedir.
ROOT ENTRY:
Dosya Adı
|
Dosyanın Fatteki Başlangıç Noktası
|
Fat Hücre Sayısı
|
IO.SYS
|
1
|
4
|
MSDOS.SYS
|
5
|
1
|
ÕOMMAND.COM
|
6
|
3
|
ÕONFIG.SYS
|
8
|
1
|
FAT:
Fat Hücre No
|
1
|
2
|
3
|
4
|
5
|
6
|
7
|
8
|
9
|
İçeriği
|
2
|
3
|
4
|
0FFFFh (Eof)
|
0FFFFh (Eof)
|
0
|
0
|
0
|
0FFFFEh (Bad Sector)
|
IO.SYS isimli dosya disk üzerinden okunmaya çalışıldığında öncelikle 1. Fat hücresinin işaret ettiği cluster okunur. Daha sonra 1. nolu fat hücresinin işaret ettiği 2 nolu Fat hücresinin işaret ettiği Cluster okunur. Arkasından 3. Hücre işlem görür. 4. Hücredeki EOF ifadesine istinaden okuma işlemi durur.
MSDOS.SYS isimli dosya ise doğrudan 5. nolu fat hücresinin işaret ettiği cluster üzerinden okunur ve işlem sonlanır.
COMMAND.COM ve CONFIG.SYS isimli dosyalar silinmiştir. Eğer en son config.sys dosyası kopyalanmışsa ve ilkin command.com dosyası undelete yapılırsa command.com dosyasının son bölümünde CONFIG.SYS olacak şekilde dosya bozuk olarak undelete yapılır. Eğer geri getirilmezde CONFIG.SYS dosyası istenirse bu durumda CONFIG.SYS dosyası başarıyla geri getirilecektir. Ama eğer COMMAND.COM tekrar undelete yapılmaya kalkılırsa undelete işlemin gerçekleştirilemeyeceğini söyleyerek çıkacaktır.
9 nolu fat hücresi ise o cluster'ın bozuk olduğuna işaret eder.
WIN 95 ve NT 4.0 dosyalar silindiğinde Recycle.bin isimli görünmez bir dizine taşır. ve nereden attığını bir yere kaydeder. eğer dosya geri getirilirse aynen yerine yerleşir. Eğer Recycle.bin boşaltılmışsa dosyalar o zaman silinmiş demektir.
Dosyaların güvenliği için ve daha hızlı erişmek için dosyaları bir bütün halinde tutmak tavsiye edilir. Bu işlem içinde en azından haftada bir defa DEFRAG programının çalıştırılması yeterli olacaktır.
Elbetteki bu yapıda bir dosyayı okumak için diskin kafası bir ileri bir geri gidip gelecektir. Bunu hızlandırmak amacıyla smartdrv gibi programlar diskin çok okunup yazılan bölümlerini belleğe alır. Diske yazıyorum deyip kandırıp belleğinde bir süre saklar. Disk serbest kaldığı anda bunları yazar. Bu şekilde işlemler yaklaşık 2-50 misli hızlanmaktadır. Ancak bunların sakatlığıda eğer yazmadan makine kapatılırsa yazmak üzere olduğu bilgiler silinir. ve eski durumlarında kalır. Bundan korunmak için makineyi doğrudan kapatmak yerine CTRL-ALT-DEL tuşlarına basarak makinenin en tekrar açılma işlemini başlatmak daha sonra kapatmaktır. Smartdrv türü programlar bu tuşu kontrol ederek eğer belleğinde bir şey kalmışsa bunu diske yazıp ondan sonra makinenin kapanmasını sağlarlar.
Root: Ana dizin veya kök dizine Root adı verilir. Burada dosyaların isimleri ve bazı bilgileri tutulmaktadır. Yapısı şu şekildedir.
İsmi
|
Boyu
|
Açıklama
|
Dosya adı
|
8 byte
|
Dosyanın ismi burada tutulur.
|
Uzantısı
|
3 byte
|
Dosyanın uzantısı burada tutulur.
|
Özellikleri
|
1 byte
|
Dosyanın Read only hidden ve bunun gibi bilgileri burada tutulur.
|
Ayrılmış alan
|
8 byte
|
Bu alan DOS tarafından boş bırakılır. Burası NT ve WIN95 türü programlar tarafından uzun dosya isimlerinin kontrolü için kullanılır.
|
Tarih ve Saat
|
4 byte
|
Dosyanın son değiştiği tarih ve saat
|
Başladığı Yer
|
2 byte
|
Dosyanın FAT üzerinde başlangıç noktası
|
Uzunluğu
|
4 byte
|
Dosyanın kaç byte olduğu
|
Toplam
|
32 byte
|
Burada aynı zamanda diskin etiketide saklanır. dosya boyu 0, uzunluğu 0, saat ve tarih bos ve ozelliginde sadece Etiket bilgisi olduğu yazılıdır. Aslında dizinlerde dosyalar gibi disk üzerinde saklanır. ilk açıldıklarında bir cluster boyundadır. Daha sonra yetmediği zaman sanki dosyaya ek yapılıyor gibi eklentiler yapılır. Ancak özelliği Dizin olan bu dosyalar DOS tarafından farklı değerlendirilerek içinin gösterilmesi gibi fonksiyonlar yerine getirilir. Bunun dışında Root dizinin farklı bir özelliği boyu sabittir değişmez. Bu sebeble bazı virüsler kendilerini Root'un en alt kısmına yerleştirirler. Böylece kendilerini gizlemiş olurlar. Win 95 ve NT uzun dosya isimleri için silinmiş dosya kayıtları yaratırlar. ilk byte 0E5h değeridir. Dosya adı, uzantısı ve diğer bilgilerinin yerine dosyanın uzun adının bir kısmı tutulur.
Data: Burada diske kayıtlı dosyaların ve dizinlerin içerikleri kaydedilir.
Dos'ta diske erişim için int 25h ve int 26h kullanılır. Sector No verilerek herhangi bir adrese ulaşılır.
Bunun dışında diske erişmek için Int 13h kullanılır. Bu servis BIOS tarafından hazırlandığından Dos'tan bağımsız olarak kullanılabilir. Bunun dışında CD'ye erişmek için MSCDEX (Microsoft Compact Disk Extention)'in hazırladığı Int 2Fh kullanılır. Bu arada Int 2F çok amaçlı bir servistir. Bu servis içerisinde microsoft'un undocumented (Saklı) servisleride mevcuttur.
DOS'ta iken bir dosya açılması için gereken aşamalar aşağıdaki gibidir.
x Int 21h Servisi üzerinden dosya aç komutu çalıştırılır.
x Int 25h Servisi üzerinden diskten directory entry okunur. Buraya bir dosya kaydı açılır. Bu kayıt 32 byte boyundadır. Öncelikle directory'deki bilgiler okunur. Sonra en alta dosya ile alakalı bilgi eklenir.
x Int 25h kullanılarak FAT okunur buradan boş olan bir Fat hücresi seçilerek bu seçilen hücreye ilkin (EOF) bilgisi kaydedilir. Sonra int 26h ile yazılır.
x Directory entry'e eklenen satıra başlangıç fat hücreno kaydedilerek Int 26h ile yazılır.
x Seçilen başlangıç Fat hücresinin işaret ettiği Data bölgesine dosyanın içeriği yazılır.
x Eğer bu hücrenin belirttiği yer yeterli gelmezse Fat üzerinden tekrar boş bir hücre aranır. Bu hücreye (Eof) ifadesi yazılır. Başladığı fat hücresine de buranın adresi yazılır. Bu hücrenin işaret ettiği yerde kullanılır.
x Dosyayı kapat komutu gelir. Bu komutla dizindeki dosya kaydındaki dosyanın boyu güncellenir.
x Bütün bu işlemler esnasında INT 25h ve INT 26h BPB (Bios Parameter Block)'taki bilgilere uygun olarak adres hesaplamasına gider. Hesapladığı adrese göre INT 13h'ı çağırarak buraya yazma işini gerçekleştirir. INT 13h diske erişmek için gerekli programa sahiptir. Diskin I/O adresine gerekli bilgileri vererek diskin bu adresteki bilgileri okumasını ve aktarmasını sağlar.
x WIN 95 ve NT 4.0 diske erişimi kısıtlamak amacıyla INT 13h'ı kendi üstüne alır ve çağrıları kendisi değerlendirir. Eğer sakatlık yapacak bir çağrı alırsa bunu engeller. Bunun dışında 95 DOS modunda açıldığından uzun dosya isimlerini korumak için diske doğrudan erişimi engellemiştir. Bu engeli kaldırmak için LOCK komutu kullanılır. Engeli tekrar koymak için UNLOCK komutu vardır.
Anti-Debug, Anti-Trace ve Anti Sourcer Metodları
Bilindiği gibi yazılan programlar debug programları ile işleyişleri incelenip farklı işlere zorlanabilirler. Diğer taraftan sourcer türü programlar aracılığıyla yazılan programların kaynak kodları çıkartılabilir. Burada bu türlü işlemlerin nasıl engelleneceği anlatılmaktadır.
Anti-Debugging metodları iki katagoride incelenebilir:
1. Koruma Amaçlı;
2. Kendi Kendini Değiştiren Kodlar.
Bu tür koruma metodları bugünlerde en fazla virüslerde kullanılmaktadır. Bu tür trikler virüsün yaptığı işin çözülmesini engeller böylece virüsün nasıl bulaştığı ve orjinal kodu çözülemez. Ayrıca kaynak kodu da çıkartılamaz. Bu tür örneklere ait kaynak kodlar dökümanın sonuna doğru verilmiştir.
Bu tür triklerin en fazla kullanım alanı bulduğu başka bir alan ise kopyalamaya karşı koruma programlarıdır. Bu tür programlar içeride nasıl kontrol yaptıkları tespit edilemesin diye Anti-Debug, Anti-Trace ve Anti-Source metodlarıyla korunmaktadırlar. Dolayısı ile kırılmaları oldukça güçleşmektedir.
1. Koruma Amaçlı:
Koruma amaçlı metodlar kullanıcının kodu debug etmesi veya kaynak kodunu çıkartmasını engelemek için kullanılır. Bu tür metodlar normal çalışma esnasında düzgün çalışmasına rağmen Debug yapılırken sistemi sakatlamakta veya Debug programını göçertmektedirler.
1.1. Interrupt'ların devre dışı bırakılması:
Interrupt'ların devre dışı bırakılması en çok kullanılan metodlardan biridir. Değişik metodları vardır.
1.1.1. Donanım kontrolü ile interrupt'ın devre dışı bırakılması:
Port 21h üzerinden kontrol edilen 8259 Interrupt kontrolcüsüne komut göndererek IRQ hatlarının devre dışı bırakılması esasına dayanır. Port 21h adresindeki her bit bir IRQ hattını kontrol eder. Bit 0 IRQ 0'ı, Bit 1 IRQ 1'i şeklinde. Buradan 0-7 arası IRQ'lar kontrol edilebilir. Bu arada IRQ 1 klavye kontrolcüsünden gelen sinyali taşır. Klavyeden her tuşa basılışta IRQ1 çağrılır. Bu IRQ'nun karşılığı olan INTERRUPT CPU tarafından çağrılarak basılan tuşla ilgili bilginin klavyenin belleğinden alınması sağlanır. Böylece her tuşa bastığınızda bilgi uçmaz. Belleğe alınır. Eğer Debug işlemi esnasında bir sonraki komuta geç komutu verilemezse program debug edilemez. Basitçe klavyeyi kilitleyerek kullanıcının bir sonraki tuşa basması engellenir. Böylece program korunmuş olur.
Örnek:
Adres
|
Hex
|
Instruction
|
CS:0100
|
E4 21
|
IN AL,21
|
CS:0102
|
0C 02
|
OR AL,02
|
CS:0104
|
E6 21
|
OUT 21,AL
|
Diğer taraftan, Klavyeye ait PPI (Programmable Peripheral Interface)'ın bulunduğu Port 61h'a komut gönderilerekte klavye kilitlenebilir.
Örnek:
Adres
|
Hex
|
Instruction
|
CS:0100
|
E4 61
|
IN AL,61
|
CS:0102
|
0C 80
|
OR AL,80
|
CS:0104
|
E6 61
|
OUT 61,AL
|
1.1.2. Yazılımla Interrupt'ın devre dışı bırakılması:
Bu biraz daha kolay bir anti-debugging metodu'dur. Tüm yapmanız gereken Debugger'lar tarafından kullanılabileceğini düşündüğünüz interrupt vektörlerini farklı adreslere yöneltmek veya boşaltmak. Bir başka metod ise hataları kontrol eden interrupt vektörlerini kendi üzerinize alarak üstünüze aldığınız hata konrolcüsünün hatasını devreye sokmak. Unutmamanız gereken işlem bittikten sonra eski vektörleri yerine getirmenizdir. Interrupt vektörünü Int 21h'ın 25h fonksiyonunu kullanmak yerine kendinizin değiştirmesi.Çünki Int 21h'ı çağırdığınızda debugger bunu anlayıp kendisini zincire ekleyerek sizi kandırabilir. Bu sebeble gidip kendiniz değiştirmeniz önerilir. Aşağıdaki örnek interrupt 03h - Breakpoint interrupt'ının ele geçirilmesi gösterilmektedir.
Örnek:
Adres
|
Hex
|
Instruction
|
CS:0100
|
EB 04
|
JMP 0106
|
CS:0102
|
00 00
|
ADD [BX+SI],AL
|
CS:0104
|
00 00
|
ADD [BX+SI],AL
|
CS:0106
|
31 C0
|
XOR AX,AX
|
CS:0108
|
8E C0
|
MOV ES,AX
|
CS:010A
|
26 8B 1E 0C 00
|
MOV BX,ES:[000C]
|
CS:010F
|
89 1E 02 01
|
MOV [0102],BX
|
CS:0113
|
26 8B 1E 0E 00
|
MOV BX,ES:[000E]
|
CS:0118
|
89 1E 04 01
|
MOV [0104],BX
|
CS:011C
|
26 C7 06 4C 00 00 00
|
MOV Word Ptr ES:[000C],0000
|
CS:0123
|
26 C7 06 4E 00 00 00
|
MOV Word Ptr ES:[000E],0000
|
1.1.3. Vektör Ayarlamaları
Bu metod interrupt vektörleri üzerinde oynayarak, bu vektörlere akışı yönlendirmeye dayanır. Bu tür bir işlem kodçözücü kodda da kullanılmaktadır. (Bkz. 2.1) Bu metodda bilgiler interrupt vektörlerinin işaret ettiği yerde tutulur. Elbetteki normal çalışma esnasında 01h, 03h kullanılmaz. Tabi debug etmeyi düşünmüyorsanız. Bu metod gayet güzel çalışmaktadır.
Örnek:
Adres
|
Hex
|
Instruction
|
CS:0100
|
31 C0
|
XOR AX,AX
|
CS:0102
|
8E D0
|
MOV SS,AX
|
CS:0104
|
BC 0E 00
|
MOV SP,000E
|
CS:0107
|
2E 8B 0E 34 12
|
MOV CX,CS:[1234]
|
CS:010C
|
50
|
PUSH AX
|
CS:010D
|
31 C8
|
XOR AX,CX
|
CS:010F
|
21 C5
|
AND BP,AX
|
CS:0111
|
58
|
POP AX
|
CS:0112
|
E2 F8
|
LOOP 010C
|
1.1.4. Interrupt Yerdeğiştirme
Bu biraz çatlakça bir trik. Ve sadece programınızın artık daha fazla debug istemediğini düşünüyorsanız kullanın. Interrupt 16h ve 21h'ın vektörlerini 01h ve 03h'a kopyalamakla ne yapılabilir. Normal bir çalışmada böyle bir şey yapılmaz. Eğer kullanıcı programı debug etmek isterse programın içinde geçen INT 01 komutları normal bir INT komutuna döndürmek zorundadır. Bu trik çok etkili olabilir. Çünki herhangi bir şekilde CD01(INT 01)'i CD16 (INT 16)'ya değiştirmek kolaydır. Ancak Int 03'için özel komut olan 0CCh tek byte'tır. ve iki byte'lık bir komutla değiştirilemez.
Örnek:
Adres
|
Hex
|
Instruction
|
CS:0100
|
FA
|
CLI
|
CS:0101
|
31 C0
|
XOR AX,AX
|
CS:0103
|
8E C0
|
MOV ES,AX
|
CS:0105
|
26 A1 84 00
|
MOV AX,ES:[0084]
|
CS:0109
|
26 A3 04 00
|
MOV ES:[0004],AX
|
CS:010D
|
26 A1 86 00
|
MOV AX,ES:[0086]
|
CS:0111
|
26 A3 06 00
|
MOV ES:[0006],AX
|
CS:0115
|
B4 4C
|
MOV AH,4C
|
CS:0117
|
CD 01
|
INT 01
|
1.2. Zaman Kontrolü:
Nispeten daha az kullanılan bir metoddur. Ancak programın çalışması esnasında tüm interrupt'ları devre dışı bırakan debuggerları (Örnek: Borland Turbo Debugger) devre dışı bırakmak için gayet kullanışlı bir metoddur. Bu metod basitçe saati kontrol eder ve değişene kadar kısır döngüde bekler. Bu değer interrupt 08h tarafından değiştirilir. Diğer bir örnek eğer Port 21h'dan okunan değer (IN) 01h ile OR'lanır ve tekrar Port 21h'a yazılsa bile (IRQ 0'ı devreye sokar) Eğer hala devreye girmemiş ise o zaman debugger aktiftir. Şunu dikkate almak gerekiyor. Bu metod RUN yapılıyorsa etkindir. Eğer TRACE veya STEP by STEP çalıştırılsa çalışmaz.
Örnek:
Adres
|
Hex
|
Instruction
|
CS:0100
|
2B C0
|
SUB AX,AX
|
CS:0102
|
FB
|
STI
|
CS:0103
|
8E D8
|
MOV DS,AX
|
CS:0105
|
8A 26 6C 04
|
MOV AH,[046C]
|
CS:0109
|
A0 6C 04
|
MOV AL,[046C]
|
CS:010C
|
3A C4
|
CMP AL,AH
|
CS:010E
|
74 F9
|
JZ 0109
|
1.3. Debugger'ı yanıltmak:
Bu metod gayet güzel bir tekniktir. Turbo Debugger ve benzeri debugger'lar için kullanılır. Bu işlem bir komutun ortasına atlayarak yapılır. Aslında bir sonraki komut aptal bir komuttur. ve içerisinde başka bir komutu içerir. Siz aptal komutu atlayıp gerçek komuta atladığınızda debugger'ı yanıltmış olursunuz. Ancak normal step debugger kullanıyorsanız (Örnek Debug veya SymDeb) bu işe yaramayacaktır. Çünki komutlarınız komut komut çalıştırıldığından jump ettiği noktada sizi bekleyecektir.
Örnek:
Adres
|
Hex
|
Instruction
|
CS:0100
|
E4 21
|
IN AL,21
|
CS:0102
|
B0 FF
|
MOV AL,FF
|
CS:0104
|
EB 02
|
JMP 0108
|
CS:0106
|
C6 06 E6 21 00
|
MOV Byte Ptr [21E6],00
|
CS:010B
|
CD 20
|
INT 20
|
Şuna dikkat edin :
Adres
|
Hex
|
Instruction
|
CS:0108
|
E6 21
|
OUT 21,AL
|
Dikkat:
Bu trik herhangi bir debugger'ın çalışmasını etkilemez. Bu sadece kullanıcının başka bir komutun çalıştırldığını düşünürken başka bir komut çalıştırılır.
1.4. Check CPU Flags:
This is a nice trick, effective against almost any real mode debugger. What you should do is simply set the trace flag off somewhere in your program, and check for it later. If it was turned on, a debugger runs in the background...
Örnek:
Adres
|
Hex
|
Instruction
|
CS:0100
|
9C
|
PUSHF
|
CS:0101
|
58
|
POP AX
|
CS:0102
|
25 FF FE
|
AND AX,FEFF
|
CS:0105
|
50
|
PUSH AX
|
CS:0106
|
9D
|
POPF
|
Programın ortasında :
Adres
|
Hex
|
Instruction
|
CS:1523
|
9C
|
PUSHF
|
CS:1524
|
58
|
POP AX
|
CS:1525
|
25 00 01
|
AND AX,0100
|
CS:1528
|
74 02
|
JZ 152C
|
CS:152A
|
CD 20
|
INT 20
|
1.5. Debugger'ın çalışmasını kesme:
Bu teknik debugger RUN modunda iken çalışmasını keser. Yapacağınız şey programın içerisinde rastgele yerlere INT 3 komutu yerleştirmek. RUN modunda olduğunuz halde program hep bir yerlerde kesilir ve siz sürekli RUN demek durumunda kalırsınız. Bu ise oldukça sıkıcı bir durum. Eğer debugger dışında iseniz bu bir çırpıda geçecektir.
Örnek:
Adres
|
Hex
|
Instruction
|
CS:0100
|
B9 64 02
|
MOV CX,0264
|
CS:0103
|
BE 10 01
|
MOV SI,0110
|
CS:0106
|
AC
|
LODSB
|
CS:0107
|
CC
|
INT 3
|
CS:0108
|
98
|
CBW
|
CS:0109
|
01 C3
|
ADD BX,AX
|
CS:010B
|
E2 F9
|
LOOP 0106
|
1.6. Bilgisayarı Stack kullanarak çökertmek:
Bu trik debugger'ların kendi stack'larını kullanmak yerine kullanıcı programının stack'ını kullanması esasına dayanır. Eğer debug çalışıyorsa stack değişecektir. Stack kod alanını gösterdiğinden komutlar işletilirken aradaki stack bölgesindeki abuk sabuk komutlar sistemi çökertir. Böylece debug yapılırken sistem çöker. Eğer debug çalışmıyorsa bu alanlar değişmeyeceğinden program normal çalışır ve bu alanı geçer.
Önemli not: Bu kodu çalıştırırken CLI yapıp iş bittikten sonra STI yapmayı unutmayın. Eğer bu komut aralığında herhangi bir interrupt çağrılırsa bu alan değişeceğinden bilgisayar olmadık bir yerde çöker.
Örnek:
Adres
|
Hex
|
Instruction
|
CS:0100
|
8C D0
|
MOV AX,SS
|
CS:0102
|
89 E3
|
MOV BX,SP
|
CS:0104
|
0E
|
PUSH CS
|
CS:0105
|
17
|
POP SS
|
CS:0106
|
BC 0B 01
|
MOV SP,010B
|
CS:0109
|
90
|
NOP
|
CS:010A
|
90
|
NOP
|
CS:010B
|
EB 02
|
JMP 010F
|
CS:010D
|
90
|
NOP
|
CS:010E
|
90
|
NOP
|
CS:010F
|
89 DC
|
MOV SP,BX
|
CS:0111
|
8E D0
|
MOV SS,AX
|
1.7. TD386'yı V8086 modundayken çökertmek:
Bu Turbo Debugger'ın V8086 modulü (TD386)'nü çökertmek için güzel bir metoddur. Temeli sıfıra bölme işlemidir. Sıfıra bölme işlemi sistemi çökertip programın kesilmesine neden olur. Halbuki sıfıra bölme işlemi INT 00h'ı çağırır. Eğer siz INT 00h vektörünü bir sonraki komuta getirirseniz böylece sistem çakılmadan yoluna devam eder. Halbuki Turbo Debugger bunu farkettiği anda programı keser. Normal çalışırken ise sorun çıkmaz.
Önemli not: Eski INT 00h vektörünü kaydetmeniz gerekiyor. İşiniz bittiğinde bu vektörünü düzeltin. Eğer bunu yapmazsanız sistem bir sonraki INT 00h çağrısında çökecektir.
Örnek:
Adres
|
Hex
|
Instruction
|
CS:0100
|
31 C0
|
XOR AX,AX
|
CS:0102
|
8E D8
|
MOV DS,AX
|
CS:0104
|
C7 06 00 00 12 01
|
MOV WORD PTR [0000],0112
|
CS:010A
|
8C 0E 02 00
|
MOV [0002],CS
|
CS:010E
|
B4 00
|
MOV AH,00
|
CS:0110
|
F6 F4
|
DIV AH
|
CS:0112
|
B8 00 4C
|
MOV AX,4C00
|
CS:0115
|
CD 21
|
INT 21
|
1.8. Herhangi bir V8086 Prosesini çökertme:
TD386'yı göçertme metodlarından biri Hatalı Komut işletmektir. Ne yazıkki, V8086 ortamında çalışan başka bir program tarafından işletilen bir hatalı komut ta sizin sisteminizi etkileyebilir. Metod sıfıra bölme metodu ile aynıdır. Ancak bu metodda interrupt 0Dh (13) kullanılır. İşletilen hatalı bir komut programda bir sonraki satırdan devam etmenizi sağlar. Ancak Debugger üzerinden çalıştırıyorsanız işletilen komutla debugger duracak ve programı kesecektir. Böylece debug yapılması engellenmiş olur.
Önemli not: Orjinal interrupt vektörlerini eski değerlerine döndürmezseniz herhangi bir sakatlık durumunda sistemin çakılmasına neden olur.
Örnek:
Adres
|
Hex
|
Instruction
|
CS:0100
|
31 C0
|
XOR AX,AX
|
CS:0102
|
8E D8
|
MOV DS,AX
|
CS:0104
|
C7 06 34 00 13 01
|
MOV WORD PTR [0034],0113
|
CS:010A
|
8C 0E 36 00
|
MOV [0036],CS
|
CS:010E
|
83 3E FF FF 00
|
CMP WORD PTR [FFFF],+00
|
CS:0113
|
B8 00 4C
|
MOV AX,4C00
|
CS:0116
|
CD 21
|
INT 21
|
2. Kendi Kendini Değiştiren Kodlar:
2.1. Şifreleme / Çözme algoritmaları :
İlk katagori basit bir kod, bu kod şifrelidir ve basit bir çözme rutini eklenmiştir. Bu arada eğer debugger bir breakpoint koymuşsa buda arada kaynayacağından farklı bir komuta dönüşecektir. Dolayısıyla sistemin çakılmasına neden olur. Böylece debugging işlemi kesilir. Aşağıdaki örnek Haifa virüsünden alınmıştır. Eğer siz CS:0110 adresine breakpoint koyacak olursanız, asla bu adrese ulaşamazsınız. Sebebi işlemin sonucunda ne olacağı kimse tarafından bilinemez.Dolayısıyla ne kod işletileceği bilinemez.
Not: eğer trace işlemi için çok fazla uğraşmak istemiyorsanız. çözme işlemini kodun sonundan itibaren başlatın. Böylece enazından çok fazla uğraşmadan debug işlemini gerçekleştirebilirsiniz.
Örnek:
Adres
|
Hex
|
Instruction
|
CS:0100
|
BB 71 09
|
MOV BX,0971
|
CS:0103
|
BE 10 01
|
MOV DI,0110
|
CS:0106
|
91
|
XCHG AX,CX
|
CS:0107
|
91
|
XCHG AX,CX
|
CS:0108
|
2E 80 35 97
|
XOR Byte Ptr CS:[DI],97
|
CS:010C
|
47
|
INC DI
|
CS:010D
|
4B
|
DEC BX
|
CS:010E
|
75 F6
|
JNZ 0106
|
CS:0110
|
07
|
POP ES
|
CS:0111
|
07
|
POP ES
|
2.2. Kendini-Değiştiren Kodlar
2.2.1. Basit Kendini Değiştirme:
Bu metod basit bir şifreleme metodlarına dayanır. Bir komutu işletmeden evvel değiştirmeye dayanır. Aşağıdaki örnekte Call işlemi yapıldıktan sonra Call'dan sonra gelen komut değiştirilir. Eğer 'P'/Debug veya F8/Turbo Debugger ile işletirseniz programın bir anda sonlandığını göreceksiniz. Trace yaparsanız CD 20 olan bir sonraki komut trace işlemi esnasında CC 20'ye dönecektir. CC Int 03h'ı çağırdığından debugger kontrolü ele alabilir. Oysa burası CALL yapıldıktan sonra rutinin içerisinde başka bir kod ile değiştirilir.
Örnek:
Adres
|
Hex
|
Instruction
|
CS:0100
|
E8 04 00
|
CALL 0107
|
CS:0103
|
CD 20
|
INT 20
|
CS:0105
|
CD 21
|
INT 21
|
CS:0107
|
C7 06 03 01 B4 4C
|
MOV Word Ptr [0103],4CB4
|
CS:010D
|
C3
|
RET
|
Dikkat:
Adres
|
Hex
|
Instruction
|
CS:0103
|
B4 4C
|
MOV AH,4C
|
2.2.2. The Running Line (Kendi kendini şifreleme):
Bu örnek Kendi kendini kontrol eden ve kendi kendini değiştiren bir koddur. Bazen "The Running Line" ismiyle anılıur. Bu Serge Pachkovsky tarafından kodlanmıştır.Basit trik noktaları olan bir gösterimdir. Ancak burada bahsedilen diğer tekniklerden farklı olarak, Bu göreceli olarak vektör tablosundaki korumaları engeller. Bu son derece basitleştirilmiş bir örnektir.
XOR AX, AX
MOV ES, AX
MOV WORD PTR ES:[4*1+0],OFFSET TRACER
MOV WORD PTR ES:[4*1+2],CS
MOV BP, SP
PUSHF
XOR BYTE PTR [BP-1], 1
POPF
MOV AX, 4C00H ; This will not be traced!
DB 3 DUP ( 98H )
DB C5H, 21H
TRACER:
PUSH BP
MOV BP, SP
MOV BP, WORD PTR [BP+2]
XOR BYTE PTR CS:[BP-1], 8
XOR BYTE PTR CS:[BP+0], 8
POP BP
IRET
MOV ES, AX
MOV WORD PTR ES:[4*1+0],OFFSET TRACER
MOV WORD PTR ES:[4*1+2],CS
MOV BP, SP
PUSHF
XOR BYTE PTR [BP-1], 1
POPF
MOV AX, 4C00H ; This will not be traced!
DB 3 DUP ( 98H )
DB C5H, 21H
TRACER:
PUSH BP
MOV BP, SP
MOV BP, WORD PTR [BP+2]
XOR BYTE PTR CS:[BP-1], 8
XOR BYTE PTR CS:[BP+0], 8
POP BP
IRET
2.2.3. Prefetch Instruction Queue (PIQ) Ayarlamaları
Bu metod herhangi bir debugger'ı atlatabilir. veya herhangi bir bir seferde bir işlem yapan debugger'ları atlatabilir.PIQ CPU üzerinde bulunur. Komutları işletmeden evvel belleğe çekilir. Böylece işletmek için tekrar çağrı yapılmaz. Zaten CPU içerisinde mevcuttur. Eski CPU'larda bu 6 veya 4'tür. Yenilerde ise 25 kadardır. işlem basitçe şu şekilde tanımlanabilir. Bir şekilde PIQ ile Bellekteki bilgi farklılaştırılır. Kod bu şekilde yazılır. Eğer debugger içerisinde ise adım adım program çalıştırıldığından PIQ her defasında temizlenir. Dolayısıyla her zaman güncel kalır. Oysa normal çalışma esnasında orjinal kalan ve değişmeyen PIQ'dan dolayı eski kod işleme sokulur. Ve program bir sonraki satırı işler geçer. Oysa farklılaşmanın olmadığında program döner durur.
Örnek:
Adres
|
Hex
|
Instruction
|
CS:0100
|
B9 75 02
|
MOV CX,0275
|
CS:0103
|
BE 90 01
|
MOV SI,0190
|
CS:0106
|
89 F7
|
MOV DI,SI
|
CS:0108
|
AC
|
LODSB
|
CS:0109
|
C7 06 0F 01 24 06
|
MOV Word Ptr [010F],0624
|
CS:010F
|
34 73
|
XOR AL,73
|
CS:0111
|
AA
|
STOSB
|
CS:0112
|
C7 06 0F 01 24 06
|
MOV Word Ptr [010F],0624
|
CS:0118
|
E2 EE
|
LOOP 0108
|
Şuna Dikkat edin.
Adres
|
Hex
|
Instruction
|
CS:010F
|
24 06
|
AND AL,06
|
=============================================
Açıklamalar:
Program örneklerinde CLI/STI çifti kullanılmamıştır. Interrupt kontrolü veya üzerine alma durumlarında bu komutların başta ve sonra yer alması gereklidir. Bunun sebebi eğer siz interrupt vektörünü değiştirirken interrupt çağrılırsa sistem çökecektir