Root > Documents > Web Güvenlik Açıkları > Assembler (8)
Cyber-Warrior.Org \ Doküman \ Web Güvenlik Açıkları > Assembler (8)
Madde
  Yazar : «¥¡g¡t€®»
  Date : 23.11.2004 16:16:30
 
# Assembler (8)
 


INT ve INTO, IRET ve SIGT Komutları



INT komutu daha öncede bahsettiğim gibi işletim sisteminin yada sistemin kesme tablosundan bir kesmeyi (interrupt) çağırmayı sağlar. Kesmeler sistem kesmeleri, işletim sistemi kesmeleri ve boş kesmeler olarak ayrılırlar. Bu kesmelerde dinamik ve statik olarak ikiye ayrılırlar. Dinamik kesmeler sürekli yada belli zaman aralıklarıyla çalşırlar. Statik kesmeler ya işlem olunca yada hiç çalışmazlar Boş kesmeler kullanıcılara ayrılmıştır ve statiktirler. Dinamik kesmelere örnek olarak 08h kesmesini verebiliriz. Bu sistem zamanlayıcısı (system timer) kesmesidir ve saniyede 18.2 kez gibi bir periyodu vardır.



Kesme tablosu 0:0 segmentinde başlar var segment:offset mantığı ile çalışır. Yani ilk olarak kesmenin segmenti ve sonrada adresi yer alır. Korumalı modda ise "kesme betimleyici tablo" olarak değişmiştir.





(Yukarıda gerçek modda interrupt tablosunu görüyorsunuz. Int1\'in  vectörü   025f:1528  )

Bir kesmenin vektörlerini bulmak için kesme sayısı*4 işlemini yapabiliriz. Burada 4 olmasının nedeni segment:offset ikisinin herbirinin 16 bitlik değerler olmasındandır. Kesme vektörlerini değiştirebiliriz. Ancak mutlaka geriçağrım (callback) olmak zorunda. Aksi takdirde sistem dönüşümü sağlanamadığı için kilitlenme ve hatalara neden ol
acaktır.



INT komutlarının seg:off adreslerinde işleme başladıktan sonra daima IRET komutu ile geriye döner. Bu komut kesme dönüşümü için tasarlanmış bir RET komutunun türevidir. Aynı şekilde korumalı modda IRETD komutu geri dönüşüm sağlar.



INTO komutu ise taşma kesmesini çağırmak için tahsis edilmiştir. Taşma durumunu yani overflow durumu bayrak registerde kontrol altındadır ve sistem 4 numaralı kesmeyi bu bayrak için tahsis etmiştir.

Özel kesmelerin başında INT 3 kesmesi gelir. Bu kesme CPU\' nun vermiş ol
duğu "debug" özelliğine yardımcı olarak "kesme noktası" (breakpoint) özelliğini işletir. Diğer kesme numaraları INT komutu ile iki byte uzunluğunda iken INT 3  komutu sadece 1 byte uzunluğundadır.

Debug işlemi işlemcinin desteklediği bir özelliktir. Bu öz
ellik Kapan bayrak (Trap flag) ile aktif  hale geçer ve bu bayrak set (1) olduktan sonra işlemci hem makine komutunda INT 1 kesmesini çağırır. Bu sayede hem registerler hem komutlar tek tek simule edilebilir.



Windows ortamında ise Windows debug için yukarıda bahsettiğim temel işlevi yapacak API fonksiyonları vermiştir. Öncelikle var olan yada yeni oluşturulacak bir process (oluşum, uygulama) DEBUG_ONLY ve DEBUG_ONLY_THIS_PROCESS şeklinde oluşturulur.Bu oluşumu CreateProcess ile gerçekleştirebiliriz. WaitForDebugEvent isimli API fonksiyonu ile olaylar akışına göre kontrol edilir. GetThreadContext ve SetThreadContext ile o andaki registerler, IP noktası, eflaglar alınabilir. WaitForDebugEvent sonrasi uygulama hafızaya yüklenmiş ve çalışmaya hazır ise uygulamanın EFLAG bayrağının TR (Kapan = trap) set ederiz ve uygulama hem komuttan sonra single-step exception üretir.

Kısaca :



CreateProcess DEBUG_ONLY,DEBUG_ONLY_THIS_PROCESS
WaitForDebugEvent



    .EXCEPTION_DEBUG_EVENT
    GetThreadContext, EFLAG
    or [eflag],TR
    SetThreadContext
...
    .EXCEPTIONS_ SINGLE_STEP
    GetThreadContext
    ReadProcessMemory
...
ContinueDebugEvent



şeklinde tablolandırabiliriz.



Önemli kesmelerden bazıları:

08h    -  Sistem Timer kesmesi
10h    -  Video kesmesi
13h    -  Disk işlemleri
16h    - Klavye işlemleri ve flash bios
21h    - Dos fonksiyonları kesmesi
25h    - Disk okuma
26h    - Disk yazma
33h    - Mouse işlemleri



 



SIGT komutu ise korumalı modda kesme betimleyici tabloyunun yerini öğrenmeye yarar. Bu sayede DOS \' da olduğu gibi kesme tablosuna ulaşırız. Yalnız bu tabloda vectörler 4 byte uzunluğunda değildir.32+16 bit yani 48 bit uzunluğundadır. 48 bitlik bir değeri fword ile gösterebiliyoruz. Bu tabloda vektörler taban adresi(32bit)+limit (16bit) şeklinde oluşur.



AAA, AAD, AAM, ASD komutları



Bu komutlar matematiksel toplama, çıkarma, çarpma ve bölme işleminden sonra ondalıktan taşan kısmı ayırırlar. Bu ASCII ayarlamasıdır ve görevini "ASCII MOD ondalık olarak" şeklinde özetleyebiliriz. Örneğin AAA komutu:



xor eax,eax         eax = 0
mov al,0a           eax = 0ah
aaa
                        eax = 0109h ( 0ah-9 = 1 = ah)

AAS komutu
ise AAA\' nın tam tersidir. Çıkarma işlemi sonucunda ondalık mod olarak düzeltme yapmadır. Yukarıdaki işlemde AAA yenine AAS kullanırsak sonuç eax =FF04h olacaktır.



AAM komutu ise çarpım işlemi sonunda ondalık düzeltme yapılmasıdır.  Yukarıda örnekde AAA yerine AAM olursa sonuç 0100h olacaktır. Çünkü 0ah içinde 1 tane 9 var.



AAD komutu ise bölme işlemi sonunda ondalık düzeltme yapılmasıdır.



HLT ve WAIT komutu



Bu komutlar normal programlarda pek görülmezler. Çünkü işletim sisteminin programlanmasıyla ilgilidirler. HLT komutu Intel tarafından işlemciyi durdurur şeklinde açıklanmıştır. Ancak Windows gibi çok işlemcili bir işletim sisteminde işlemciyi durdurmak sözkonusu değildir. Gerçek modda maskeleme işlemi yapar. Wait komutuda bekleme işlemi yapmaya yarar ve yine işletim sistemi programlanması ile ilgilidir. Normalde bu iki komut sistem açılışı esnasında gerekli yerlerde kullanılırlar ancak sonra pek kullanım durumu sözkonusu olmaz.



CPUID,  RTSTC komutları ve Random



CPUID komutu işlemcinin türünü, cache( önbellek) uzunluğunu, modelini öğrenmek için CPUID komutunu kullanırız. Bu komut bize eax registerin 3 değerinde ayrı ayrı bilgiler verir. Çıkış bilgilerini EBX,ECX,EDX registerlere yükler. Bunlar yazı olabileceği gibi bit seviyesinde de olabilir. Örneğin Intel bir işlemci için:



mov eax,0
cpuid
mov [data1],ebx  ; \'Genu\'
mov [data2],ecx  ; \'ntel\'
mov [data3] ,edx ; \'inel\'





Eğer EAX register 1 olursa CPUID komutu bize yine EAX ve EDX register ile versiyonu hakkında bir bilgi verecektir.



Eğer EAX register 2 olursa CPUID komutu bize EAX,EBX,ECX,EDX registerler ile biter bazında cache ve CPU bilgisi verecektir. Bunların tam listesini Intel dökümanlarından yada ilgili yardım dosyalarından bulabilirsiniz.



RDSTC komutu CPU sayacını okur. Bilgisayar çalışmaya başladığı andan itibaren saymayan başlayan sayaçlar vardır. Bunlar gerek işletim sistemi içerisinde gerekse RDSTC gibi sistem içerisindedir. RDSTC doğal bir random (rasgele sayı üretici) denilebilir. CPU\' nun hızına bağlı olarak çalışır ve farklı işlemcilerde farklı değerler gözlenir. RDSTC dinamik bir sayaçtır. Dolayısıyla rasgele sayı üreten prosedürler içinde kullanılanır. EAX:EDX registerler ile 64 bitlik bir sonuca ulaşılabilir.



Şimdide randomlar yani rasgele üretilen sayılar konusuna değinmek istiyorum. Bu konu pek çok alanda önemli bir yer tutar. Maalesef bu konuda Türkçe olarak dile getirilen fikirler ya bir yerden alıntı olarak karşımıza çıkıyor yada iyice araştırılmadan söyleniliyor.  



Randomlar (rasgele sayı üreticileri) dinamik random ve statik random olarak ikiye ayrılır. Dinamik randomlar her çağrımda ve çalıştırmada farklı farklı sayılar üretir ve ortaya "tekrar edilmesi imkansız" bir sayı rutini çıkar. Bu random prosedürlerinin çekirdeği RDSTC gibi rasgele sayı üreten bir komuttan yada GetTickCount gibi bir API fonksiyonundan oluşur.



Statik randomlar ise  kullanıcının verdiği sayı ile matematiksel ve lojik işlemler yaparak istenilen değerde modlar yani sınırlar. Bunlar tam olarak gerçek randomlar değildir. Çünkü her defasında aynı sabit sayı girişi olduğu için ve aynı işlemler yapıldığı için aynı sayılar oluşur. Dolayısıyla rasgelelik olayı sahtedir. Ancak bu randomlar demolar - tanıtımlar gibi sabit animasyon, efekt yapan uygulamalardan kullanılır. Böylece istenilen sahnelerin veya olayların gerçekleşmesi sağlanır.



RDSTC ile işlemci hızını bulmaya yarayan örnek:
;---------------------------------------------------------------------------
---
.data
capt    db \'CPU Test\',0
format    db \'CPU Speed = %lu Mhz\',0
buffer    db 30 dup (0)




.code
main:
    xor eax,eax
    db 0fh,31h ;rdtsc
    mov ebx,eax
    call Sleep, 1000
    db 0fh,31h ;rdtsc
    sub eax,ebx
    sub eax,8
    xor edx,edx
    mov ecx,1000000
    div ecx
    call _wsprintfA, offset buffer, offset format, eax
    call MessageBoxA, 0 ,offset buffer, offset capt, 0            
    call ExitProcess , 0
   
;------------------------------------------------------------------------------



Kısaca program ilk olarak o andaki CPU sayacını alıyor. Sonra 1.000ms (1 sn) bekletiliyor ve yine o andaki CPU sayacı alınıp birbirinden çıkarılıyor. İndirgemek için 1.000.000\' a bölünüyor ve işlemcinin 1 saniyede yaptığı işlem gücü yani işlemci hızını buluyor.



KAYNAK TAMAMEN INTERNETTEN TEMİN EDİLİP TARAFIMDAN DERLENMİŞTİR...



 

   
   
Cyber-Warrior TIM All Legal and illegal Rights Reserved.\CWDoktoray 2001©