Y Ü K S E L __ T O P R A K D E L E N
  Anti-Debug, Anti-Trace ve Anti Sourcer Metodları
 

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

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.


 
   
 
Bu web sitesi ücretsiz olarak Bedava-Sitem.com ile oluşturulmuştur. Siz de kendi web sitenizi kurmak ister misiniz?
Ücretsiz kaydol