SlideShare une entreprise Scribd logo
1  sur  161
X86 TERSİNE
MÜHENDİSLİK
EĞİTİMİ
BÖLÜM-3
İSTANBUL
blog.btrisk.com @btrisk /btrisktv /btrisk
OYUN
6. AŞAMA
İÇ İÇE DÖNGÜLER
• İç içe döngülerin analizini kolaylaştırmak için renklendirme ve
gruplama yöntemlerinden faydalanabiliriz.
• Gruplama ve Analiz Metodu Önerisi
 Kalın mavi çizgiyi bul (döngü çizgisi)
 Kalın çizginin ok başından geriye doğru takip et
o Eğer bunu yaparken bir başka kalın mavi çizgiye
rastlarsan önce iç döngüyü grupla
 Döngüyü grupla
 Tüm döngüler gruplandıktan sonra fonksiyonun başından
itibaren analiz etmeye başla
o Pseudo Code ile tespitleri not et
o Tekrar grupla ve analize devam et
ÖN BİLGİ
VERİ YAPILARI [STRUCTURES]
• Assembly kodu içinde belli bir adresin offset'ine erişim
gözlendiğinde bu bir veri yapısı [structure] kullanımına işaret
olabilir.
• Bu durumda okunabilirliği artırmak için IDA'nın veri yapıları
imkanından faydalanabiliriz.
• İç içe döngüler ile birlikte bu konuyla ilgili uygulama örneğini
gerçekleştireceğiz.
ÖN BİLGİ
VERİ YAPILARI [STRUCTURES]
ÖN BİLGİ Veri yapılarının
anlamlandırılmasıyla ilgili
aşağıdaki kod parçasının
Assembly'ye dönüşümü ve veri
yapısını IDA'da modelledikten
sonra bunu koda yansıtma
örneğini görebilirsiniz.
ÖN BİLGİ İÇ İÇE DÖNGÜLER VE
VERİ YAPILARI
DEMO
#include <stdio.h>
typedef struct veriYapisi
{
int rakam;
int faktoriyel;
struct veriYapisi *sonraki;
} bilesen;
bilesen bilesen1 = { 5, 0, NULL }; bilesen bilesen2 = { 7, 0, &bilesen1 }; bilesen bilesen3 = { 3, 0,
&bilesen2 };
bilesen bilesen4 = { 4, 0, &bilesen3 }; bilesen bilesen5 = { 2, 0, &bilesen4 }; bilesen bilesen6 = { 8, 0,
&bilesen5 };
int main()
{
int i,j;
bilesen *cursor = &bilesen6;
int rakam;
for (i = 1; i<=6; i++)
{
cursor->faktoriyel = 1;
for (j = 1; j <= cursor->rakam; j++)
{
cursor-
>faktoriyel = cursor->faktoriyel * j;
}
cursor = cursor->sonraki;
}
cursor = &bilesen6;
for (i = 1; i<=6; i++)
{
printf("%d faktoriyel = %dn", cursor-
>rakam, cursor->faktoriyel);
cursor = cursor->sonraki;
}
getchar();
return 0;
}
Örnek olarak inceleyeceğimiz kodumuzda içinde [2] INTEGER ve bir [STRUCT
POINTER] barındıran bir veri yapısını kullanacağız.
Bu veri yapılarından oluşmuş bir dizi veriyi [GLOBAL] değişken olarak tanımladık
ve [OFFSET]'leri bir zincir liste oluşturacak biçimde ayarladık.
ÖN BİLGİ İÇ İÇE DÖNGÜLER VE
VERİ YAPILARI
DEMO
Bir [CURSOR] kullanarak zincir liste
[LINKED LIST] üzerinden gezerken
[faktoriyel] alanlarına [rakam]
verisinin faktoriyelini hesaplayarak
yazıyoruz.
ÖN BİLGİ İÇ İÇE DÖNGÜLER VE
VERİ YAPILARI
DEMO
Derlenmiş kodumuzu
IDA ile açalım.
ÖN BİLGİ İÇ İÇE DÖNGÜLER VE
VERİ YAPILARI
DEMO
Kodu sadeleştirmek için döngüleri
gruplama yoluna gideceğiz.
Bunun için daha önce de belirlediğimiz
gibi önce iç içe döngülerde en iç
döngülere yönlenmemiz lazım.
Genel yaklaşım olarak fonksiyonun
sonuna en yakın döngüden
gruplamaya başlayabiliriz. Kodun
sonundaki döngüyü oluşturan 3 bloğu
[CTRL] tuşunu basılı tutarak seçelim.
ÖN BİLGİ İÇ İÇE DÖNGÜLER VE
VERİ YAPILARI
DEMO
Seçtiğimiz blokları aynı renge boyamak için
sağ klikleyerek [Set node color] seçeneğini
seçelim.
ÖN BİLGİ İÇ İÇE DÖNGÜLER VE
VERİ YAPILARI
DEMO
Seçtiğimiz blokları renklendirelim.
ÖN BİLGİ İÇ İÇE DÖNGÜLER VE
VERİ YAPILARI
DEMO
Blokları gruplayıp tek bir kutu
şeklinde ifade etmek için sağ
klikleyip [Group nodes] seçeneğini
seçelim.
ÖN BİLGİ İÇ İÇE DÖNGÜLER VE
VERİ YAPILARI
DEMO
Grubumuza [DONGU_1] adını
verebiliriz.
ÖN BİLGİ İÇ İÇE DÖNGÜLER VE
VERİ YAPILARI
DEMO
[DONGU_1] grubunun toplanmış
hali soldaki gibi olacaktır.
ÖN BİLGİ İÇ İÇE DÖNGÜLER VE
VERİ YAPILARI
DEMO
Kalan bölümdeki kodları
incelediğimizde iç içe 2 döngü
olduğunu görebiliriz. Bunlardan
içte olanını oluşturan blokları
seçip renklendirelim.
ÖN BİLGİ İÇ İÇE DÖNGÜLER VE
VERİ YAPILARI
DEMO
Yeni grubumuza [DONGU_2] adını
verebiliriz.
ÖN BİLGİ İÇ İÇE DÖNGÜLER VE
VERİ YAPILARI
DEMO
Bu grubu da toplayarak kodu
sadeleştirmeye devam edelim.
ÖN BİLGİ İÇ İÇE DÖNGÜLER VE
VERİ YAPILARI
DEMO
Son olarak dıştaki döngüyü
oluşturan blokları seçelim ve
renklendirelim.
ÖN BİLGİ İÇ İÇE DÖNGÜLER VE
VERİ YAPILARI
DEMO
Son grubumuzu da [DONGU_3]
olarak adlandırıp toplayalım.
Görüleceği gibi kod analiz için
oldukça sadeleşti, şimdi sıra kod
bloklarının oluşturduğu grupları
adım adım açarak
anlamlandırmakta.
ÖN BİLGİ İÇ İÇE DÖNGÜLER VE
VERİ YAPILARI
DEMO
Demo uygulamamızı diğer örneklerde olduğu gibi detaylı olarak
incelemeyeceğiz. Ancak [var_C] değişkenine atanan offset adresine çift
tıklayarak bu alanda bulunan verilere göz atalım.
ÖN BİLGİ İÇ İÇE DÖNGÜLER VE
VERİ YAPILARI
DEMO
IDA için bu [.data] section'ında bulunan bu alanın özel bir anlamı yok, o nedenle
BYTE BYTE görüntülüyor veriyi.
ÖN BİLGİ İÇ İÇE DÖNGÜLER VE
VERİ YAPILARI
DEMO
Diyelimki detaylı bir analiz yaptık ve bu veri yapısının [3] adet DWORD'den
oluştuğu kanaatine vardık. Bu durumda veri alanları üzerinde [d] tuşuna [3] defa
basarak veriyi [DWORD – dd] formatına çevirebiliriz.
ÖN BİLGİ İÇ İÇE DÖNGÜLER VE
VERİ YAPILARI
DEMO
Oluşturduğumuz ilk veri yapısı bloğunun son alanındaki offset bilgisinden
faydalanarak zincir listeyi oluşturan diğer veri yapısı alanlarını da ortaya
çıkarabiliriz.
ÖN BİLGİ İÇ İÇE DÖNGÜLER VE
VERİ YAPILARI
DEMO
Detaylı kod analizi ve veri yapılarını inceleyerek ortaya çıkardığımız bilgileri koda
yansıtabilmek ve kodun okunabilirliğini artırabilmek için önce IDA'ya bir veri
yapısı tanımı yapmamız gerekir.
ÖN BİLGİ İÇ İÇE DÖNGÜLER VE
VERİ YAPILARI
DEMO
[INSERT] tuşuna basarak yeni oluşturacağımız veri yapısının
adını [VERI_YAPISI] verelim.
ÖN BİLGİ İÇ İÇE DÖNGÜLER VE
VERİ YAPILARI
DEMO
[d] tuşuna basarak veri yapısını oluşturan alanları
tanımlayalım ve [d] tuşuna 2 defa daha basarak bu veri
alanlarının büyüklüklerini [DWORD]'e dönüştürelim.
ÖN BİLGİ İÇ İÇE DÖNGÜLER VE
VERİ YAPILARI
DEMO
Kodu detaylı olarak
incelediğimizi, [var_C] lokal
değişkeninde bulunan veri
yapısı adresinin önce [EAX]
register'ına aktarıldığını ve
bunun [+4] byte offset'inde de
tespit ettiğimiz bir alanın var
olduğunu bildiğimizi
varsayalım.
ÖN BİLGİ İÇ İÇE DÖNGÜLER VE
VERİ YAPILARI
DEMO
[4] rakamını tıkladıktan
sonra sağ klikleyerek
context menü'yü açalım.
Burada tanımladığımız
veri yapısını seçerek
kodun anlaşılabilirliğini
artıralım.
ÖN BİLGİ İÇ İÇE DÖNGÜLER VE
VERİ YAPILARI
DEMO
Kod yanda görüldüğü gibi
bir veri yapısının içindeki
bir bileşene referans
verildiğini belirtecek hale
gelerek anlaşılırlığı
artacaktır.
6. AŞAMA
Ana fonksiyonda 4. aşama olarak
tahmin ettiğimiz fonksiyonun içine
girelim.
6. AŞAMA Bu fonksiyon diğerlerine nazaran
oldukça kompleks ve çok sayıda
döngü içeriyor.
Bu döngülerin bazıları da iç içe
[nested] döngüler gibi görünüyor.
NOT: IDA'nın döngüleri daha belirgin
hale getirmek için KOYU MAVİ
çizgiler kullandığından daha önce
bahsetmiştik.
6. AŞAMA
Karmaşık bir kodla karşı karşıya olduğumuzda, ki iç içe döngüler içeren bir kod
karmaşık olabilir, belli kod bölümlerini renklendirerek diğer bölümlerden
ayrıştırmak isteyebiliriz.
İç içe döngüleri daha anlaşılabilir hale getirmek için yapılabilecek bir diğer
uygulama döngüleri oluşturan kod bölümlerini gruplamak ve bu grupları
kapatmak olabilir
6. AŞAMA
İç içe döngüleri kapatmaya en içteki döngülerden başlamalıyız. Bir genelleme
yapamayız ancak en içteki döngülerin sıklıkla bulundukları bölüm fonksiyondan
çıkış noktasına yakın olan alanlardır.
Öyleyse [RETN] instruction'ına yakın olan döngüye bir göz atabilir ve bu kod
alanlarını renklendirebiliriz.
6. AŞAMA
En içteki döngüyü oluşturan kod bloklarını
renklendirelim.
Renklendirmeye [CMP] instruction'ını barındıran
test bölümünden başlayıp sayacın artırıldığı kod
bölümüne kadar devam edelim.
6. AŞAMA
Döngümüze test bloğundan önce gelen "initialization" bloğunu da ekleyelim. Bu
kod karmaşasında bu bölümü bulmak zor olsa da kod akış kollarını takip ederek
ve sayaç olarak kullanılan lokal değişken veya register'ı highlight ederek bu bloğu
da bulabiliriz.
6. AŞAMA
Döngü kod bloklarını gruplamadan önce [CTRL] tuşuna basılı tutarak blokları
seçelim. Blokların başlık bölümlerinin griye dönmesi seçme işleminin başarılı
olduğunu gösterir.
6. AŞAMA
Seçilen tüm kod bloklarını gruplamadan önce [SAĞ KLİK]leyerek context
menü'nün açılmasını sağlayalım ve [Group nodes] seçeneğini seçelim.
6. AŞAMA
Oluşturacağımız gruba bir isim vermemiz
gerekiyor. Döngüler üzerinde çalıştığımız için
bu grubu [DONGU_1] olarak isimlendirebiliriz.
6. AŞAMA
Bu kod bloğunu grupladığımızda kodun
anlaşılabilirliğine katkıda bulunmuş olduk.
6. AŞAMA İç içe döngüleri basitleştirmek için içten dışa doğru
bir yaklaşımın doğru olacağını söylemiştik. Şimdi
[DONGU_1]'in bir dışındaki döngüyü gruplamaya
çalışalım.
Renklendirmeyi kullanmak blokları ayrıştırmak için
duyduğumuz ihtiyaca bağlı, ancak biz tüm döngüleri
netleştirmek için boyamaya devam edebiliriz.
6. AŞAMA
Yine [CTRL] tuşunu basılı tutarken grubun parçası
olan kutuları seçebiliriz ve sağ klik ile gelen Context
Menü'den faydalanarak bu kutuları [node]
gruplayabiliriz.
6. AŞAMA
Bu grubu da [DONGU_2] olarak
isimlendirebiliriz.
6. AŞAMA
2. döngüyü de gruplandırdıktan sonra bir üst
döngünün daha olduğunu görebiliriz.
Ancak sol taraftaki kod bloklarına baktığımızda bu
bacakta da iç içe döngüler var gibi görünüyor.
Önce iç döngüleri gruplama prensibimiz gereği üst
seviyedeki döngüye geçmeden önce [DONGU_2]
seviyesindeki diğer alanları da sadeleştirmemizde
fayda var.
6. AŞAMA
Sol taraftaki döngünün bileşenlerini tespit
etmeye çalışalım.
6. AŞAMA Bu grubu da daha kolay ayrıştırmak için farklı
bir renge boyayalım.
Döngüleri gruplarken "initialization"
kutularını da dahil ettiğimize dikkat edin.
6. AŞAMA
Bu grubumuza da [DONGU_3] adını verelim.
6. AŞAMA
Döngüleri grupladıkça kodun nasıl daha kolay
anlaşılabilir hale geldiğine dikkat edin.
Elbette hatalı grupladığımız veya yanlış
yerden başladığımız durumlar olabilir, ancak
bu grupları tekrar oluşturma imkanımız var.
[DONGU_3]'ü grupladıktan sonra bu grubu
da içine alan bir başka döngü olduğunu
görebiliyoruz.
6. AŞAMA
[DONGU_3] 'ü de içine alan döngü bloğunu
renklendirelim.
6. AŞAMA
Son grubumuza da [DONGU_4] adını verelim.
6. AŞAMA Yeni bir iç döngüyü belirleyelim.
Döngüleri sunum sayfasında
incelemek daha zor, IDA
ekranında daha rahat biçimde
analizimizi gerçekleştirebiliriz.
6. AŞAMA Yeni grubumuzu renklendirelim.
6. AŞAMA Bu gruba da [DONGU_5] adını
verelim.
6. AŞAMA [DONGU_5]'i de içine alan bir üst
döngüyü belirleyelim.
6. AŞAMA Yeni grubumuzu renklendirelim.
6. AŞAMA Bu gruba da [DONGU_6] adını
verelim.
6. AŞAMA Tüm döngüleri gruplandırdıktan sonra kod çok
basit bir hale geldi.
Şimdi yeri geldikçe grupları açarak nasıl bir
algoritma barındırdıklarını incelemeye geçebiliriz.
6. AŞAMA
Fonksiyonumuz başlarında
[var_C] değişkenimize bir offset
adresi atanıyor.
6. AŞAMA
Bu offset'e geldiğimizde anlamlı
bir bilgi göremiyoruz, en azından
bize anlam ifade edebilecek
ASCII bir veri barındırmıyor bu
alan.
6. AŞAMA
Bu offset'in ne olduğunu
bilmesek de [var_C] lokal
değişkenine erişilen diğer
noktalarda bu değişkenin bir
adres bilgisi barındırdığını
belirtmemizde fayda var.
6. AŞAMA
Bu değişkeni
[BILINMEYEN_OFFSET] olarak
isimlendirebiliriz.
6. AŞAMA
Bu bloktaki çağrılan fonksiyonlara göz attığımızda daha önceden analiz
ettiğimiz bir fonksiyona rastlıyoruz.
Fonksiyonun işlevini hatırlamak için tekrar [ALTI_INT_OKU] fonksiyonunu
ziyaret edelim.
6. AŞAMA
Bu fonksiyon kendisine verilen
bir string'in içinden okuduğu 6
INTEGER değeri 2. parametre
olarak aldığı adres ve
sonrasındaki alanlara yazıyordu.
6. AŞAMA
[ASAMA_6] fonksiyonumuz tek
parametre alıyor görünüyor.
6. AŞAMA
Kodu anlamlandırmak amacıyla bu
parametrenin adını [PRM_GIRDI]
olarak düzenleyelim.
6. AŞAMA
Fonksiyon parametresi ile verilen
değerin [ALTI_INT_OKU] fonksiyonu
çağrılmadan hemen önce atandığı
lokal değişkenin adını
[L_PRM_GIRDI] olarak
düzenleyebiliriz. Bu alan aynı
zamanda [ALTI_INT_OKU]
fonksiyonuna verilen 1. parametre.
6. AŞAMA
[ALTI_INT_OKU] fonksiyonu ile ilgili
2 parametre aldığı ve 2.
parametrenin de okunan 6
INTEGER'ın yazılması için
kullanılacağını biliyoruz. Bu nedenle
stack'te bu adresin yazılacağı alana
[L_PTR_INT_GECICI] adını
verebiliriz.
6. AŞAMA
Stack'te [ALTI_INT_OKU]
fonksiyonuna verilen adresin kendisi
ise [var_38] alanının adresi. Bu alanı
da [L_PTR_INT] olarak
adlandırabiliriz. Bu adres okunan
INTEGER değerlerinin arka arkaya
yazılacağı alanın başlangıç adresi.
6. AŞAMA [DONGU_6] grubunu
açtığımızda döngünün sayacı
olarak [var_5C] alanının
kullanıldığını rahatlıkla
görebiliyoruz.
6. AŞAMA
Bu alanı anlamlandırmak için
adını [VAR_I] olarak
değiştirelim.
Burada sayacın [0] ile initialize
edildiğini, [5] ve daha altı
olduğu durumlarda (yani <6)
döngüde kalmaya devam
edildiğini görebiliyoruz.
6. AŞAMA
Grubun en altındaki blokta
sayacımızın "1" artırıldığını
[INC] görebiliyoruz.
6. AŞAMA
PSEUDO CODE (yani kod benzeri deyimlerle ifade etme) yaklaşımı ile analiz
ettiğimiz algoritmanın netleştirilmesi yöntemini daha önce de kullanmıştık.
Bu yönteme bu fonksiyon gibi çok karmaşık fonksiyonlarda daha da fazla
ihtiyacımız var. O nedenle algoritmanın analiz ettiğimiz bölümleri için bu
yöntemi kullanacağız.
PSEUDO CODE
int girdi[6]
for(VAR_I=0;VAR_I<6;VAR_I++)
{
...
}
6. AŞAMA
Eklediğimiz yorum satırında da
görüldüğü gibi okunan
INTEGER'lar [0] veya daha
küçük olamazlar.
6. AŞAMA
Hemen aşağıdaki blokta da
okunan INTEGER değerlerinin
[6]'dan büyük olamayacaklarını
görebiliyorz.
6. AŞAMA
PSEUDO CODE
int girdi[6]
for(VAR_I=0;VAR_I<6;VAR_I++)
if (girdi[VAR_I] <= 0 || girdi[VAR_I] > 6)
HATALI_DENEME()
6. AŞAMA
[DONGU_6] içinde
[DONGU_5]'i barındırıyor. Dış
döngüyü analiz ettikten sonra
onun içindeki döngüye
geçebiliriz.
6. AŞAMA
[DONGU_5]'in sayacı olarak
[var_60] lokal değişkeninin
kullanıldığını görüyoruz.
[var_60] önce "[VAR_I]+1"
ile initialize ediliyor. [6]'dan
küçük olduğu müddetçe de
iç döngüde kalmaya devam
ediyor uygulama.
6. AŞAMA
Kodu daha okunur hale
getirebilmek için [var_60]
değişkeninin adını [VAR_J]
olarak değiştirelim.
6. AŞAMA
Daha önce de bahsettiğimiz [VAR_J] değişkeninin bir
üst döngünün sayacı olan [VAR_I] sayacına [1]
eklenerek initialize edildiği kod bölümü.
6. AŞAMA
Yine daha önce bahsettiğimiz [VAR_J] değişkeninin [5]'in
üzerine çıkması halinde döngüden çıktığı kod bölümü.
6. AŞAMA
Dıştaki döngü [6] INTEGER değerinin üzerinden dönerken, içteki döngü de
incelenmekte olan INTEGER değerinden sonra gelen değerler üzerinden dönüyor.
Eğer bu değerler birbirleri ile aynı ise oyun sonlanıyor. Dolayısıyla girilen [6]
INTEGER'ın birbirlerinden farklı olmak zorunda olduğunu söyleyebiliriz.
6. AŞAMA
[VAR_J] sayacımızın artırıldığı (VAR_J++] kod bölümü.
6. AŞAMA
PSEUDO CODE
int girdi[6]
for(VAR_I=0;VAR_I<6;VAR_I++)
if (girdi[VAR_I] <= 0 || girdi[VAR_I] > 6)
HATALI_DENEME()
for(VAR_J=VAR_I+1; VAR_J<6;VAR_J++)
if(girdi[VAR_I]==girdi[VAR_J])
HATALI_DENEME()
6. AŞAMA
[DONGU_5] kod grubunu incelememiz bittiğine göre
kod karmaşıklığını azaltmak üzere tekrar geriye
toplayabiliriz.
6. AŞAMA
Aynı şekilde [DONGU_6] grubunu da geriye
toplayabiliriz. Sıra [DONGU_4] grubunda.
6. AŞAMA
[DONGU_6] grubu
toplandıktan sonra IDA yine
eskisi gibi görünecek.
6. AŞAMA
Şimdi [DONGU_4]'ü
[Ungroup] ederek
incelemeye başlayabiliriz.
6. AŞAMA
Şimdi [DONGU_4]'ü
[Ungroup] ederek
incelemeye başlayabiliriz.
Derleyicimiz sayaç olarak
yine [VAR_I]'yı kullanmayı
uygun görmüş.
Bu döngüde de benzer
biçimde [VAR_I] [0] ile
initialize ediliyor , sayaç her
döngüde [1] artırılıyor ve
indeks [6]'dan küçük ise
döngüde kalmaya devam
ediliyor.
6. AŞAMA
PSEUDO CODE
int girdi[6]
for(VAR_I=0;VAR_I<6;VAR_I++)
if (girdi[VAR_I] <= 0 || girdi[VAR_I] > 6)
HATALI_DENEME()
for(VAR_J=VAR_I+1; VAR_J<6;VAR_J++)
if(girdi[VAR_I]==girdi[VAR_J])
HATALI_DENEME()
for(VAR_I=0;VAR_I<6;VAR_I++)
6. AŞAMA
Bu haliyle döngünün son
bloğunu
anlamlandıramıyoruz,
[var_10] ve [var_58] lokal
değişkenlerinin ne için
kullanıldığına dair bir
fikrimiz yok.
O yüzden iç döngü olan
[DONGU_3] döngüsünü
incelemeye başlayabiliriz.
6. AŞAMA
[DONGU_3]'ün içinde
[BILINMEYEN_OFFSET]
adresi tekrar karşımıza çıktı.
[var_10] lokal değişkenine
atanan adres de bu offset
adresi. Bu yüzden bu
offset'teki verinin ne
olduğunu anlamaya
çalışırsak iyi olur.
6. AŞAMA
Tekrar hatırlamak için
[BILINMEYEN_OFFSET] lokal
değişkenine ilgili adresin ilk
atandığı fonksiyonun
başlarındaki kod bölümüne
göz atabiliriz.
6. AŞAMA
[0x40304C] adresini tekrar ziyaret
edelim.
Daha önce de bu alanın byte'lara
bölünmüş halde pek bir anlam
ifade etmediğini
değerlendirmiştik.
Ancak aşağıya ve yukarıya doğru
offset adreslerine benzer veriler
olduğunu görebiliyoruz.
6. AŞAMA
[BILINMEYEN_OFFSET] lokal
değişkeninin değeri [var_10]
lokal değişkenine atandıktan
sonra bu değişkene referans
veren diğer kod bölümlerine
göz atalım.
6. AŞAMA
Kodun alt bölümlerinde [var_10] lokal değişkeninde bulunan adresin [+8]
offset'inde bulunan bir DWORD değerin [EAX] register'ına atandığını ve
bunun da tekrar [var_10] lokal değişkenine atandığını görüyoruz. Bu
durumda [BILINMEYEN_OFFSET] adresindeki verileri DWORD değerlerine
dönüştürmeyi düşünebiliriz.
6. AŞAMA
Veri tipinin üzerine tıkladıktan
sonra [d] tuşuna [2] defa
basarak byte'ları DOUBLE
WORD'lere [dd]
dönüştürebiliriz.
Art arda 3 DWORD verisi
oluşturduğumuzda son
DWORD'ün bir başka offset'in
adresini içerdiğini
görebiliyoruz.
6. AŞAMA
Şimdi aynı işlemi ortaya
çıkardığımız offset olan
[0x403040] adresine atlayarak
gerçekleştirelim.
6. AŞAMA
Bu adresteki 3. DWORD değeri
de [0x403034] değerini
içeriyor. Bu da bir adrese
benziyor.
Aynı işlemi bu adreste de
gerçekleştirelim.
6. AŞAMA
Aynı işlemi gerçekleştirdiğimiz
6. alanda son DWORD değeri
[0] olarak karşımıza çıkıyor.
Bu noktadan sonra tekrar aynı
işlemi uygulayamıyoruz.
6. AŞAMA
Son incelemelerimizden sonra bir veri yapısıyla [STRUCTURE] karşı karşıya
olduğumuzu söyleyebiliriz.
IDA PRO, kodu daha anlaşılır hale getirebilmek için veri yapılarını ifade
edebileceğimiz bir imkan sağlıyor.
Bu imkanı kullanabilmek için [Structures] penceresine geçelim.
6. AŞAMA
Yeni bir veri yapısı eklemek için [INSERT] tuşuna basalım.
6. AŞAMA
Yeni bir veri yapımızın adını [VERI_YAPISI] olarak verelim.
6. AŞAMA
[VERI_YAPISI] isimli veri yapımız ekranda ortaya çıktı.
Şimdi veri yapımızın içeriğini tanımlayalım.
6. AŞAMA
Açıkçası veri yapısının alanlarını henüz net olarak anlayamadık. Ancak
her bir veri yapısının 3 adet [DWORD] içerdiğini düşünüyoruz.
Bir [DATA veri yapısı bileşeni oluşturmak için [D] tuşuna basalım.
6. AŞAMA
[DATA] alanının büyüklüğünün [DWORD] olduğunu belirtmek için veri alanını [D]
tuşu ile oluşturduktan sonra 2 defa [d] tuşuna basalım ve bu alanı [dd] olarak
belirleyelim.
Daha sonra ne amaçla kullanıldığını henüz bilmediğimiz bu alana üzerine
tıkladıktan ve [N] tuşuna bastıktan sonra [ALAN_1] adını verelim.
6. AŞAMA
Yeni veri alanlarını eklemek için ALTTAKİ [VERI_YAPISI] adına tıkladıktan sonra [D]
tuşuna basalım. Bu şekilde 3 [DWORD] alan tanımladıktan sonra son alana
[NEXT_OFFSET] adını verelim. Çünkü bu alanın bir offset adresi barındırdığından
eminiz ve son veri yapısının 3. DWORD alanında [0] yani [NULL] değerinin
bulunması da karşımızda bir zincir liste [LINKED LIST] olma ihtimalini güçlendirdi.
6. AŞAMA
Bu offset'in veri yapısının bir alanı olduğunu belirtmek
için [8] rakamına tıkladıktan sonra sağ klikleyerek
context menü'sünü açalım ve
[VERI_YAPISI.NEST_OFFSET] seçeneğini tıklayalım.
6. AŞAMA
Bu işlemden sonra kod daha
okunaklı hale gelecek ve
aktarılan verinin bir veri
yapısının bir bileşeni olduğunu
daha rahat anlayabileceğiz.
6. AŞAMA
Bu noktada ilk offset'in bir
zincir listenin ilk zinciri
olduğunu varsayabiliriz.
6. AŞAMA
Bu nedenle
[BILINMEYEN_OFFSET] lokal
değişken adını [LISTE_BASI]
olarak değiştirelim.
6. AŞAMA
PSEUDO CODE
int girdi[6]
struct {
int ALAN_1
int ALAN_2
int next_item
} item;
item LISTE_BASI = 0X40304C
for(VAR_I=0;VAR_I<6;VAR_I++)
if (girdi[VAR_I] <= 0 || girdi[VAR_I] > 6)
HATALI_DENEME()
for(VAR_J=VAR_I+1; VAR_J<6;VAR_J++)
if(girdi[VAR_I]==girdi[VAR_J])
HATALI_DENEME()
for(VAR_I=0;VAR_I<6;VAR_I++)
6. AŞAMA
[LISTE_BASI] adresi [var_10]
lokal değişkenine atandıktan
sonra her bir döngüde zincir
liste içindeki bir sonraki
bileşenin [NEXT_OFFSET]
adresinin [var_10] adresine
atandığını görebiliyoruz.
6. AŞAMA
Yazılımlarda genellikle zincir
listenin üzerinde çalışılan
bileşeninin adresinin
tutulduğu değişkene [CURSOR]
adı verilir. Biz de [var_10] lokal
değişkenini bu şekilde
adlandırabiliriz.
6. AŞAMA
PSEUDO CODE
int girdi[6]
struct {
int ALAN_1
int ALAN_2
int next_item
} item;
item LISTE_BASI = 0X40304C
for(VAR_I=0;VAR_I<6;VAR_I++)
if (girdi[VAR_I] <= 0 || girdi[VAR_I] > 6)
HATALI_DENEME()
for(VAR_J=VAR_I+1; VAR_J<6;VAR_J++)
if(girdi[VAR_I]==girdi[VAR_J])
HATALI_DENEME()
for(VAR_I=0;VAR_I<6;VAR_I++)
item CURSOR = LISTE_BASI
6. AŞAMA
Bu döngüde daha önceden [VAR_J] olarak adlandırdığımız sayacın kullanıldığını, önce [1] değeri ile
initialize edildiğini, her döngüde girdi olarak verilen INTEGER ARRAY'inin [VAR_I] indeksindeki değerin
[VAR_J] değeri ile karşılaştırıldığını , bu değer [VAR_J] değerini aşıncaya kadar [CURSOR]'ün bir sonraki
bileşene işaret edecek şekilde ilerletildiğini ve tabi ki [VAR_J] değerinin artırıldığını görebiliyoruz.
6. AŞAMA
Burada [L_PTR_INT] lokal değişkeninin fonksiyonun başında okuduğumuz [6]
INTEGER değerinin yazıldığı INTEGER ARRAY'inin başlangıç adresini işaret ettiğini
tekrar hatırlayalım.
6. AŞAMA
PSEUDO CODE
int girdi[6]
struct {
int ALAN_1
int ALAN_2
int next_item
} item;
item LISTE_BASI = 0X40304C
for(VAR_I=0;VAR_I<6;VAR_I++)
if (girdi[VAR_I] <= 0 || girdi[VAR_I] > 6)
HATALI_DENEME()
for(VAR_J=VAR_I+1; VAR_J<6;VAR_J++)
if(girdi[VAR_I]==girdi[VAR_J])
HATALI_DENEME()
for(VAR_I=0;VAR_I<6;VAR_I++)
item CURSOR = LISTE_BASI
for(VAR_J=1; VAR_J<girdi[VAR_I];VAR_J++)
CURSOR=CURSOR->NEXT_ITEM
6. AŞAMA
Veri yapılarına da bakarak bu karmaşık kod bölümünü anlamlandırmaya
çalıştığımızda bizim gireceğimiz INTEGER dizisindeki her bir rakam için zincir
listenin başından itibaren girilen rakam indeksine kadar ilerleneceği sonucuna
varabiliriz. Peki zincirin bu bileşenine gelindiğinde ne olarak, bunu analizimizin
devamında anlamayı ümit ediyoruz.
6. AŞAMA
Evet bu bölümler oldukça karmaşık, ancak odaklanarak dikkatli incelediğimizde
yeni oluşturulan bir lokal değişken array'inin ilgili [VAR_I] indeksi için mevcut
[CURSOR]'ümüzün değerinin yazıldığını anlayabiliriz.
6. AŞAMA
Bu nedenle [var_58] lokal değişkenine [OFFSET_ARRAY] adını verelim.
6. AŞAMA
PSEUDO CODE
int girdi[6]
struct {
int ALAN_1
int ALAN_2
int next_item
} item;
item LISTE_BASI = 0X40304C
for(VAR_I=0;VAR_I<6;VAR_I++)
if (girdi[VAR_I] <= 0 || girdi[VAR_I] > 6)
HATALI_DENEME()
for(VAR_J=VAR_I+1; VAR_J<6;VAR_J++)
if(girdi[VAR_I]==girdi[VAR_J])
HATALI_DENEME()
for(VAR_I=0;VAR_I<6;VAR_I++)
item CURSOR = LISTE_BASI
for(VAR_J=1; VAR_J<girdi[VAR_I];VAR_J++)
CURSOR=CURSOR->NEXT_ITEM
OFFSET_ARRAY[VAR_I]=CURSOR
6. AŞAMA [DONGU_3]'ü analiz ettik ve
bu sırada bir üst döngü olan
[DONGU_4]'ün eksik kalan kod
bölümünü de anlamlandırmış
olduk.
Bu nedenle [DONGU_3] kod
grubunu tekrar toplayabiliriz.
6. AŞAMA
[DONGU_4]'ü incelememiz de
bittiğine göre onu da
kapatabiliriz.
Şimdi sıra [DONGU_2]'de.
6. AŞAMA
[DONGU_2] grubunu açmak
için bu grubu seçerek sağ
klikleyip [Ungroup nodes]
seçeneğini tıklayalım.
6. AŞAMA
[DONGU_2] grubunda
[OFFSET_ARRAY]'in başlangıç
adresindeki değer önce
[LISTE_BASI] alanına yazılıyor,
nihai olarak da [CURSOR]
değişkenine yazılıyor.
Yani [CURSOR]
[OFFSET_ARRAY]'in ilk
bileşenini taşıyacak biçimde
yenileniyor.
[LISTE_BASI] değişkeni ise artık
[OFFSET_ARRAY]'in ilk
bileşenini içerecek biçimde
güncelleniyor.
6. AŞAMA
PSEUDO CODE
int girdi[6]
struct {
int ALAN_1
int ALAN_2
int next_item
} item;
item LISTE_BASI = 0X40304C
for(VAR_I=0;VAR_I<6;VAR_I++)
if (girdi[VAR_I] <= 0 || girdi[VAR_I] > 6)
HATALI_DENEME()
for(VAR_J=VAR_I+1; VAR_J<6;VAR_J++)
if(girdi[VAR_I]==girdi[VAR_J])
HATALI_DENEME()
for(VAR_I=0;VAR_I<6;VAR_I++)
item CURSOR = LISTE_BASI
for(VAR_J=1; VAR_J<girdi[VAR_I];VAR_J++)
CURSOR=CURSOR->NEXT_ITEM
OFFSET_ARRAY[VAR_I]=CURSOR
LISTE_BASI=OFFSET_ARRAY[0]
CURSOR=OFFSET_ARRAY[0]
6. AŞAMA
Bu döngüde [VAR_I] değişkeni
sayaç olarak kullanılıyor ve [1]
olarak initialize ediliyor.
Döngüden çıkış koşulu da
[VAR_I] değişkeninin [6]'dan
küçük olması (çünkü 5'ten
büyük olursa döngü devam
ediyor)
6. AŞAMA
PSEUDO CODE
int girdi[6]
struct {
int ALAN_1
int ALAN_2
int next_item
} item;
item LISTE_BASI = 0X40304C
for(VAR_I=0;VAR_I<6;VAR_I++)
if (girdi[VAR_I] <= 0 || girdi[VAR_I] > 6)
HATALI_DENEME()
for(VAR_J=VAR_I+1; VAR_J<6;VAR_J++)
if(girdi[VAR_I]==girdi[VAR_J])
HATALI_DENEME()
for(VAR_I=0;VAR_I<6;VAR_I++)
item CURSOR = LISTE_BASI
for(VAR_J=1; VAR_J<girdi[VAR_I];VAR_J++)
CURSOR=CURSOR->NEXT_ITEM
OFFSET_ARRAY[VAR_I]=CURSOR
LISTE_BASI=OFFSET_ARRAY[0]
CURSOR=OFFSET_ARRAY[0]
for(VAR_I=1;VAR_I<6;VAR_I++)
6. AŞAMA Biraz karmaşık olan son kod
bloğunda önce [CURSOR]
pointer'ı [EDX] register'ına
yazılıyor.
Daha sonra
[OFFSET_ARRAY]'inin [1]'den
başlatılmış olan [VAR_I] sayacı
kadar içerideki bileşenin
değeri [CURSOR]'ın işaret ettiği
zincir liste bileşeninin [8] byte
offset'ine yazılıyor.
Bu offset'in ne olduğunu daha
önce analiz etmiş ve
[Structures] penceresinde
tanımlamıştık. Bu tanımlamayı
buraya da aktaralım.
6. AŞAMA [8] rakamının üzerine tıklayıp
sağ klikleyerek bu veriyi
anlamlandırmak üzere
[VERI_YAPISI.NEXT_OFFSET]
seçeneğini klikleyelim.
6. AŞAMA Bu anlamlandırmayı yaptıktan
ve dikkatle inceledikten sonra
bu bölümde gerçekleşen
olayın [CURSOR] ile işaret
edilen zincir liste bileşeninin
[NEXT_OFFSET] alanının
[OFFSET_ARRAY]'deki bir
sonraki zincir bileşen adresi ile
güncellenmesi olduğunu
görebiliriz.
6. AŞAMA
PSEUDO CODE
int girdi[6]
struct {
int ALAN_1
int ALAN_2
int next_item
} item;
item LISTE_BASI = 0X40304C
for(VAR_I=0;VAR_I<6;VAR_I++)
if (girdi[VAR_I] <= 0 || girdi[VAR_I] > 6)
HATALI_DENEME()
for(VAR_J=VAR_I+1; VAR_J<6;VAR_J++)
if(girdi[VAR_I]==girdi[VAR_J])
HATALI_DENEME()
for(VAR_I=0;VAR_I<6;VAR_I++)
item CURSOR = LISTE_BASI
for(VAR_J=1; VAR_J<girdi[VAR_I];VAR_J++)
CURSOR=CURSOR->NEXT_ITEM
OFFSET_ARRAY[VAR_I]=CURSOR
LISTE_BASI=OFFSET_ARRAY[0]
CURSOR=OFFSET_ARRAY[0]
for(VAR_I=1;VAR_I<6;VAR_I++)
CURSOR->NEXT_ITEM=OFFSET_ARRAY[VAR_I]
6. AŞAMA Bu güncellemeden hemen
sonra da [CURSOR] işaret ettiği
zincir bileşeninin
[NEXT_OFFSET] adresi ile
güncelleniyor.
Bir başka alternatif de
[OFFSET_ARRAY]'den bu
adresin alınması olabilirdi.
6. AŞAMA
PSEUDO CODE
int girdi[6]
struct {
int ALAN_1
int ALAN_2
int next_item
} item;
item LISTE_BASI = 0X40304C
for(VAR_I=0;VAR_I<6;VAR_I++)
if (girdi[VAR_I] <= 0 || girdi[VAR_I] > 6)
HATALI_DENEME()
for(VAR_J=VAR_I+1; VAR_J<6;VAR_J++)
if(girdi[VAR_I]==girdi[VAR_J])
HATALI_DENEME()
for(VAR_I=0;VAR_I<6;VAR_I++)
item CURSOR = LISTE_BASI
for(VAR_J=1; VAR_J<girdi[VAR_I];VAR_J++)
CURSOR=CURSOR->NEXT_ITEM
OFFSET_ARRAY[VAR_I]=CURSOR
LISTE_BASI=OFFSET_ARRAY[0]
CURSOR=OFFSET_ARRAY[0]
for(VAR_I=1;VAR_I<6;VAR_I++)
CURSOR->NEXT_ITEM=OFFSET_ARRAY[VAR_I]
CURSOR=CURSOR->NEXT_ITEM
6. AŞAMA
Bu döngüyü de incelememiz
de bittiğine göre bu grubu da
kapatabiliriz.
Şimdi sıra [DONGU_1]'de.
6. AŞAMA
[DONGU_1] grubunu açmak
için bu grubu seçelim ve sağ
klikle açalım.
6. AŞAMA
[DONGU_1]'in başlarında
sayaç'ın sıfırlanmasından önce
[CURSOR]'ün işaret ettiği son
zincir bileşeni üzerinde bir
işlem daha yapıldığını
görüyoruz.
6. AŞAMA
[8] offset'ini işaretlediğimizde
benzer bir işlemin aşağı
bölümde de yapıldığını daha
rahat görebiliyoruz.
6. AŞAMA Bu kod bölümlerini daha
anlamlı hale getirmek için veri
yapısına referans verme
imkanımızı tekrar kullanıyoruz.
6. AŞAMA [CURSOR]'ün işaret ettiği son
zincir bileşeninin
[NEXT_OFFSET] alanına [0],
yani pek çok uygulama
dilindeki ifadesiyle [NULL]
atandığını görüyoruz. Bu zincir
listelerdeki son bileşen için
uygulanan tipik bir yöntem.
6. AŞAMA
PSEUDO CODE
int girdi[6]
struct {
int ALAN_1
int ALAN_2
int next_item
} item;
item LISTE_BASI = 0X40304C
for(VAR_I=0;VAR_I<6;VAR_I++)
if (girdi[VAR_I] <= 0 || girdi[VAR_I] > 6)
HATALI_DENEME()
for(VAR_J=VAR_I+1; VAR_J<6;VAR_J++)
if(girdi[VAR_I]==girdi[VAR_J])
HATALI_DENEME()
for(VAR_I=0;VAR_I<6;VAR_I++)
item CURSOR = LISTE_BASI
for(VAR_J=1; VAR_J<girdi[VAR_I];VAR_J++)
CURSOR=CURSOR->NEXT_ITEM
OFFSET_ARRAY[VAR_I]=CURSOR
LISTE_BASI=OFFSET_ARRAY[0]
CURSOR=OFFSET_ARRAY[0]
for(VAR_I=1;VAR_I<6;VAR_I++)
CURSOR->NEXT_ITEM=OFFSET_ARRAY[VAR_I]
CURSOR=CURSOR->NEXT_ITEM
CURSOR->NEXT_ITEM=NULL
6. AŞAMA Sonraki adımda [LISTE_BASI]
değişkeni [CURSOR]'a atanıyor.
Yeni liste başımız bizim
gireceğimiz [6] rakamdan
ilkinin işaret ettiği bileşendi ve
biz yeni sıralamayı
[OFFSET_ARRAY] aracılığı ile
oluşturmuştuk.
6. AŞAMA
PSEUDO CODE
int girdi[6]
struct {
int ALAN_1
int ALAN_2
int next_item
} item;
item LISTE_BASI = 0X40304C
for(VAR_I=0;VAR_I<6;VAR_I++)
if (girdi[VAR_I] <= 0 || girdi[VAR_I] > 6)
HATALI_DENEME()
for(VAR_J=VAR_I+1; VAR_J<6;VAR_J++)
if(girdi[VAR_I]==girdi[VAR_J])
HATALI_DENEME()
for(VAR_I=0;VAR_I<6;VAR_I++)
item CURSOR = LISTE_BASI
for(VAR_J=1; VAR_J<girdi[VAR_I];VAR_J++)
CURSOR=CURSOR->NEXT_ITEM
OFFSET_ARRAY[VAR_I]=CURSOR
LISTE_BASI=OFFSET_ARRAY[0]
CURSOR=OFFSET_ARRAY[0]
for(VAR_I=1;VAR_I<6;VAR_I++)
CURSOR->NEXT_ITEM=OFFSET_ARRAY[VAR_I]
CURSOR=CURSOR->NEXT_ITEM
CURSOR->NEXT_ITEM=NULL
CURSOR=LISTE_BASI
6. AŞAMA Bu döngüde sayaç olarak
[VAR_I] değişkeni kullanılıyor.
[0] ile initialize edilen [VAR_I]
değeri [4]'ü geçtiğinde içinde
bulunduğumuz [ASAMA_6]
fonksiyonunun sonuna
geliyoruz.
Döngünün en alt bloğunda da
[VAR_I] değişkeninin [1]
artırıldığını görebiliyoruz.
6. AŞAMA
PSEUDO CODE
int girdi[6]
struct {
int ALAN_1
int ALAN_2
int next_item
} item;
item LISTE_BASI = 0X40304C
for(VAR_I=0;VAR_I<6;VAR_I++)
if (girdi[VAR_I] <= 0 || girdi[VAR_I] > 6)
HATALI_DENEME()
for(VAR_J=VAR_I+1; VAR_J<6;VAR_J++)
if(girdi[VAR_I]==girdi[VAR_J])
HATALI_DENEME()
for(VAR_I=0;VAR_I<6;VAR_I++)
item CURSOR = LISTE_BASI
for(VAR_J=1; VAR_J<girdi[VAR_I];VAR_J++)
CURSOR=CURSOR->NEXT_ITEM
OFFSET_ARRAY[VAR_I]=CURSOR
LISTE_BASI=OFFSET_ARRAY[0]
CURSOR=OFFSET_ARRAY[0]
for(VAR_I=1;VAR_I<6;VAR_I++)
CURSOR->NEXT_ITEM=OFFSET_ARRAY[VAR_I]
CURSOR=CURSOR->NEXT_ITEM
CURSOR->NEXT_ITEM=NULL
CURSOR=LISTE_BASI
for(VAR_I=0;VAR_I<5;VAR_I++)
6. AŞAMA Döngümüzün yaptığı asıl test
bu bölümde gerçekleşiyor,
çünkü eğer hata yapmış isek
uygulama hata alarak
sonlanıyor.
Bu bölümde yapılan şey
[CURSOR]'ın o anda işaret
ettiği bileşenin ilk DWORD'ü
ile bu bileşenin [NEXT_OFFSET]
alanı ile referans verdiği
sonraki bileşenin ilk
DWORD'ünün karşılaştırılması
işlemi.
Eğer MEVCUT bileşenin [1.]
DWORD'ünün değeri listedeki
SONRAKİ bileşenin [1.]
DWORD'ünden DAHA BÜYÜK
ise [HATALI_DENEME]
fonksiyonu çağrılıyor.
6. AŞAMA
PSEUDO CODE
int girdi[6]
struct {
int ALAN_1
int ALAN_2
int next_item
} item;
item LISTE_BASI = 0X40304C
for(VAR_I=0;VAR_I<6;VAR_I++)
if (girdi[VAR_I] <= 0 || girdi[VAR_I] > 6)
HATALI_DENEME()
for(VAR_J=VAR_I+1; VAR_J<6;VAR_J++)
if(girdi[VAR_I]==girdi[VAR_J])
HATALI_DENEME()
for(VAR_I=0;VAR_I<6;VAR_I++)
item CURSOR = LISTE_BASI
for(VAR_J=1; VAR_J<girdi[VAR_I];VAR_J++)
CURSOR=CURSOR->NEXT_ITEM
OFFSET_ARRAY[VAR_I]=CURSOR
LISTE_BASI=OFFSET_ARRAY[0]
CURSOR=OFFSET_ARRAY[0]
for(VAR_I=1;VAR_I<6;VAR_I++)
CURSOR->NEXT_ITEM=OFFSET_ARRAY[VAR_I]
CURSOR=CURSOR->NEXT_ITEM
CURSOR->NEXT_ITEM=NULL
CURSOR=LISTE_BASI
for(VAR_I=0;VAR_I<5;VAR_I++)
if(CURSOR > CURSOR->NEXT_ITEM)
HATALI_DENEME()
6. AŞAMA
Döngünün son bloğunda zincir
bileşenlerinin [+8] offset'ine
bir başka referans daha var.
6. AŞAMA
Bu bölümü de anlamlandırmak
için veri yapısı referansımızı
kullanalım.
6. AŞAMA
PSEUDO CODE
int girdi[6]
struct {
int ALAN_1
int ALAN_2
int next_item
} item;
item LISTE_BASI = 0X40304C
for(VAR_I=0;VAR_I<6;VAR_I++)
if (girdi[VAR_I] <= 0 || girdi[VAR_I] > 6)
HATALI_DENEME()
for(VAR_J=VAR_I+1; VAR_J<6;VAR_J++)
if(girdi[VAR_I]==girdi[VAR_J])
HATALI_DENEME()
for(VAR_I=0;VAR_I<6;VAR_I++)
item CURSOR = LISTE_BASI
for(VAR_J=1; VAR_J<girdi[VAR_I];VAR_J++)
CURSOR=CURSOR->NEXT_ITEM
OFFSET_ARRAY[VAR_I]=CURSOR
LISTE_BASI=OFFSET_ARRAY[0]
CURSOR=OFFSET_ARRAY[0]
for(VAR_I=1;VAR_I<6;VAR_I++)
CURSOR->NEXT_ITEM=OFFSET_ARRAY[VAR_I]
CURSOR=CURSOR->NEXT_ITEM
CURSOR->NEXT_ITEM=NULL
CURSOR=LISTE_BASI
for(VAR_I=0;VAR_I<5;VAR_I++)
if(CURSOR > CURSOR->NEXT_ITEM)
HATALI_DENEME()
CURSOR=CURSOR->NEXT_ITEM
6. AŞAMA
Zincir listemizi daha önceden analiz etmiş ve offset'leri
çözerek tüm bileşenleri belirlemiştik.
[DONGU_1]'de bileşenlerin ilk alanlarındaki değerler
birbirleriyle karşılaştırılıyordu.
6. AŞAMA
İlk alanın değerlerini HEX gösterimden
ONDALIK gösterime geçirmek için
[ALAN_1]'in üzerine tıkladıktan sonra sağ
klikleyerek [Field
type][Number][Decimal] seçeneklerini
seçebiliriz.
Daha sonra bu veri yapısını tespit
ettiğimiz zincir liste ile ilişkilendireceğiz.
6. AŞAMA
[ALAN_1]'in veri tipini [DECIMAL] olarak belirledikten sonra
[VERI_YAPISI]'nın görüntüsü yukarıdaki gibi olacaktır.
6. AŞAMA
[VERI_YAPISI]'nın son DWORD'ünün de
bir başka [VERI_YAPISI]'na işaret eden bir
OFFSET olduğunu biliyoruz. Bu bilgiyi de
veri yapısı üzerine aktarmak için son alanı
tıklayıp sağ klikledikten sonra [Field
type][Offset][Offset (struct) ...]
seçeneğini seçiyoruz.
6. AŞAMA Karşımıza çıkan menüde tanımlanmış
olan tek veri yapısı olan [VERI_YAPISI]
çıkacaktır. Bu veri yapısını seçerek
offset'in işaret ettiği [Structure] tipini de
IDA'ya öğretmiş olacağız.
6. AŞAMA
[VERI_YAPISI]'nın son görüntüsü yukarıdaki gibi olacaktır.
ALT+Q
6. AŞAMA Veri alanlarını tanımladığımız veri yapıları
ile ilişkilendirmek için ilgili veri alanının
üzerinde tıkladıktan sonra [ALT+Q]
tuşlarına basabiliriz. Daha sonra karşımıza
çıkan [Structure] listesinden ilgili olanı
seçerek bu kalıbı veri alanı ile
ilişkilendirmiş oluruz.
6. AŞAMA
Zincir listemizi oluşturan bileşenleri ilgili [Structure] ile ilişkilendirdikten sonra
veri tipleri de [Structure] üzerinde tanımladığımız gibi görüntülenmiş olacaktır.
İlk alanları [DECIMAL] olarak tanımladığımız için şimdi ONDALIK olarak
görülebileceklerdir.
6. AŞAMA
Veri yapılarını ilk alanlarındaki değerlerine göre sıralarsak
[ASAMA_6] için girmemiz gereken dizi [2 4 1 6 3 5] olacaktır.
6. AŞAMA
NE ÖĞRENDİK
Karmaşık kod bloklarını analiz etme hakkında
• Kod bloklarını renklendirme
• Kod bloklarını gruplama
• İç içe döngüleri en içten başlayarak inceleme yöntemi
Veri yapılarını anlamlandırma ve kod okunabilirliğini artırma
hakkında
• IDA'da structure tanımı yapma
• Tespit edebildiğimiz veri yapısı bileşenlerinin formatlarını
structure içinde tanımlama
• Structure bilgisini kod içine verilen referanslara aktarma
• Structure bilgisini veri blokları üzerine aktarma
BTRisk X86 Tersine Mühendislik Eğitim Sunumu - Bölüm-3

Contenu connexe

Tendances

Beyaz Şapkalı Hacker CEH Eğitimi - Bölüm 13, 14, 15
Beyaz Şapkalı Hacker CEH Eğitimi - Bölüm 13, 14, 15Beyaz Şapkalı Hacker CEH Eğitimi - Bölüm 13, 14, 15
Beyaz Şapkalı Hacker CEH Eğitimi - Bölüm 13, 14, 15BGA Cyber Security
 
Beyaz Şapkalı Hacker CEH Eğitimi - Bölüm 10, 11, 12
Beyaz Şapkalı Hacker CEH Eğitimi - Bölüm 10, 11, 12Beyaz Şapkalı Hacker CEH Eğitimi - Bölüm 10, 11, 12
Beyaz Şapkalı Hacker CEH Eğitimi - Bölüm 10, 11, 12BGA Cyber Security
 
Beyaz Şapkalı Hacker CEH Eğitimi - Bölüm 4, 5, 6
Beyaz Şapkalı Hacker CEH Eğitimi - Bölüm 4, 5, 6Beyaz Şapkalı Hacker CEH Eğitimi - Bölüm 4, 5, 6
Beyaz Şapkalı Hacker CEH Eğitimi - Bölüm 4, 5, 6BGA Cyber Security
 
Web Servislerine Yönelik Sızma Testleri
Web Servislerine Yönelik Sızma TestleriWeb Servislerine Yönelik Sızma Testleri
Web Servislerine Yönelik Sızma TestleriBGA Cyber Security
 
Sql, Sql Injection ve Sqlmap Kullanımı
Sql, Sql Injection ve Sqlmap KullanımıSql, Sql Injection ve Sqlmap Kullanımı
Sql, Sql Injection ve Sqlmap KullanımıBGA Cyber Security
 
Siber Güvenlik ve Etik Hacking Sunu - 10
Siber Güvenlik ve Etik Hacking Sunu - 10Siber Güvenlik ve Etik Hacking Sunu - 10
Siber Güvenlik ve Etik Hacking Sunu - 10Murat KARA
 
SIZMA TESTLERİNDE BİLGİ TOPLAMA
SIZMA TESTLERİNDE BİLGİ TOPLAMASIZMA TESTLERİNDE BİLGİ TOPLAMA
SIZMA TESTLERİNDE BİLGİ TOPLAMABGA Cyber Security
 
Beyaz Şapkalı Hacker CEH Eğitimi - Bölüm 19
Beyaz Şapkalı Hacker CEH Eğitimi - Bölüm 19Beyaz Şapkalı Hacker CEH Eğitimi - Bölüm 19
Beyaz Şapkalı Hacker CEH Eğitimi - Bölüm 19BGA Cyber Security
 
Sızma Testlerinde Armitage Kullanımı
Sızma Testlerinde Armitage KullanımıSızma Testlerinde Armitage Kullanımı
Sızma Testlerinde Armitage KullanımıBGA Cyber Security
 
Zararlı Yazılım Analizi Eğitimi Lab Kitabı
Zararlı Yazılım Analizi Eğitimi Lab KitabıZararlı Yazılım Analizi Eğitimi Lab Kitabı
Zararlı Yazılım Analizi Eğitimi Lab KitabıBGA Cyber Security
 
Siber Güvenlik ve Etik Hacking Sunu - 11
Siber Güvenlik ve Etik Hacking Sunu - 11Siber Güvenlik ve Etik Hacking Sunu - 11
Siber Güvenlik ve Etik Hacking Sunu - 11Murat KARA
 
Snort IPS(Intrusion Prevention System) Eğitimi
Snort IPS(Intrusion Prevention System) EğitimiSnort IPS(Intrusion Prevention System) Eğitimi
Snort IPS(Intrusion Prevention System) EğitimiBGA Cyber Security
 
Beyaz Şapkalı Hacker CEH Eğitimi - Bölüm 7, 8, 9
Beyaz Şapkalı Hacker CEH Eğitimi - Bölüm 7, 8, 9Beyaz Şapkalı Hacker CEH Eğitimi - Bölüm 7, 8, 9
Beyaz Şapkalı Hacker CEH Eğitimi - Bölüm 7, 8, 9BGA Cyber Security
 
Hacker’ların Yeni Gozdesi - PowerShell
Hacker’ların Yeni Gozdesi - PowerShellHacker’ların Yeni Gozdesi - PowerShell
Hacker’ların Yeni Gozdesi - PowerShellAdeo Security
 

Tendances (20)

Uygulamali Sizma Testi (Pentest) Egitimi Sunumu - 3
Uygulamali Sizma Testi (Pentest) Egitimi Sunumu - 3Uygulamali Sizma Testi (Pentest) Egitimi Sunumu - 3
Uygulamali Sizma Testi (Pentest) Egitimi Sunumu - 3
 
Beyaz Şapkalı Hacker CEH Eğitimi - Bölüm 13, 14, 15
Beyaz Şapkalı Hacker CEH Eğitimi - Bölüm 13, 14, 15Beyaz Şapkalı Hacker CEH Eğitimi - Bölüm 13, 14, 15
Beyaz Şapkalı Hacker CEH Eğitimi - Bölüm 13, 14, 15
 
BTRisk Zararlı Yazılım Analizi Eğitimi Sunumu - Bölüm 1
BTRisk Zararlı Yazılım Analizi Eğitimi Sunumu - Bölüm 1BTRisk Zararlı Yazılım Analizi Eğitimi Sunumu - Bölüm 1
BTRisk Zararlı Yazılım Analizi Eğitimi Sunumu - Bölüm 1
 
Beyaz Şapkalı Hacker CEH Eğitimi - Bölüm 10, 11, 12
Beyaz Şapkalı Hacker CEH Eğitimi - Bölüm 10, 11, 12Beyaz Şapkalı Hacker CEH Eğitimi - Bölüm 10, 11, 12
Beyaz Şapkalı Hacker CEH Eğitimi - Bölüm 10, 11, 12
 
Beyaz Şapkalı Hacker CEH Eğitimi - Bölüm 4, 5, 6
Beyaz Şapkalı Hacker CEH Eğitimi - Bölüm 4, 5, 6Beyaz Şapkalı Hacker CEH Eğitimi - Bölüm 4, 5, 6
Beyaz Şapkalı Hacker CEH Eğitimi - Bölüm 4, 5, 6
 
VERİTABANI SIZMA TESTLERİ
VERİTABANI SIZMA TESTLERİVERİTABANI SIZMA TESTLERİ
VERİTABANI SIZMA TESTLERİ
 
Web Servislerine Yönelik Sızma Testleri
Web Servislerine Yönelik Sızma TestleriWeb Servislerine Yönelik Sızma Testleri
Web Servislerine Yönelik Sızma Testleri
 
Sql, Sql Injection ve Sqlmap Kullanımı
Sql, Sql Injection ve Sqlmap KullanımıSql, Sql Injection ve Sqlmap Kullanımı
Sql, Sql Injection ve Sqlmap Kullanımı
 
Siber Güvenlik ve Etik Hacking Sunu - 10
Siber Güvenlik ve Etik Hacking Sunu - 10Siber Güvenlik ve Etik Hacking Sunu - 10
Siber Güvenlik ve Etik Hacking Sunu - 10
 
SIZMA TESTLERİNDE BİLGİ TOPLAMA
SIZMA TESTLERİNDE BİLGİ TOPLAMASIZMA TESTLERİNDE BİLGİ TOPLAMA
SIZMA TESTLERİNDE BİLGİ TOPLAMA
 
Beyaz Şapkalı Hacker CEH Eğitimi - Bölüm 19
Beyaz Şapkalı Hacker CEH Eğitimi - Bölüm 19Beyaz Şapkalı Hacker CEH Eğitimi - Bölüm 19
Beyaz Şapkalı Hacker CEH Eğitimi - Bölüm 19
 
Sızma Testlerinde Armitage Kullanımı
Sızma Testlerinde Armitage KullanımıSızma Testlerinde Armitage Kullanımı
Sızma Testlerinde Armitage Kullanımı
 
Zararlı Yazılım Analizi Eğitimi Lab Kitabı
Zararlı Yazılım Analizi Eğitimi Lab KitabıZararlı Yazılım Analizi Eğitimi Lab Kitabı
Zararlı Yazılım Analizi Eğitimi Lab Kitabı
 
BackTrack Linux-101 Eğitimi
BackTrack Linux-101 EğitimiBackTrack Linux-101 Eğitimi
BackTrack Linux-101 Eğitimi
 
Web Uygulama Pentest Eğitimi
Web Uygulama Pentest EğitimiWeb Uygulama Pentest Eğitimi
Web Uygulama Pentest Eğitimi
 
Siber Güvenlik ve Etik Hacking Sunu - 11
Siber Güvenlik ve Etik Hacking Sunu - 11Siber Güvenlik ve Etik Hacking Sunu - 11
Siber Güvenlik ve Etik Hacking Sunu - 11
 
Snort IPS(Intrusion Prevention System) Eğitimi
Snort IPS(Intrusion Prevention System) EğitimiSnort IPS(Intrusion Prevention System) Eğitimi
Snort IPS(Intrusion Prevention System) Eğitimi
 
Beyaz Şapkalı Hacker CEH Eğitimi - Bölüm 7, 8, 9
Beyaz Şapkalı Hacker CEH Eğitimi - Bölüm 7, 8, 9Beyaz Şapkalı Hacker CEH Eğitimi - Bölüm 7, 8, 9
Beyaz Şapkalı Hacker CEH Eğitimi - Bölüm 7, 8, 9
 
BTRisk Android Mobil Uygulama Denetimi Eğitimi
BTRisk Android Mobil Uygulama Denetimi EğitimiBTRisk Android Mobil Uygulama Denetimi Eğitimi
BTRisk Android Mobil Uygulama Denetimi Eğitimi
 
Hacker’ların Yeni Gozdesi - PowerShell
Hacker’ların Yeni Gozdesi - PowerShellHacker’ların Yeni Gozdesi - PowerShell
Hacker’ların Yeni Gozdesi - PowerShell
 

Similaire à BTRisk X86 Tersine Mühendislik Eğitim Sunumu - Bölüm-3

Veri̇ tabani oluşturma ve yapilandirma
Veri̇ tabani oluşturma ve yapilandirmaVeri̇ tabani oluşturma ve yapilandirma
Veri̇ tabani oluşturma ve yapilandirmaoktaygokgol
 
İleri Seviye T-SQL Programlama - Chapter 02
İleri Seviye T-SQL Programlama - Chapter 02İleri Seviye T-SQL Programlama - Chapter 02
İleri Seviye T-SQL Programlama - Chapter 02Cihan Özhan
 
İleri Seviye T-SQL Programlama - Chapter 21
İleri Seviye T-SQL Programlama - Chapter 21İleri Seviye T-SQL Programlama - Chapter 21
İleri Seviye T-SQL Programlama - Chapter 21Cihan Özhan
 
Temel Düzeyde MySQL ve PHP Eğitimleri 2
Temel Düzeyde MySQL ve PHP Eğitimleri 2Temel Düzeyde MySQL ve PHP Eğitimleri 2
Temel Düzeyde MySQL ve PHP Eğitimleri 2Univerist
 
Diziler C#
Diziler C#Diziler C#
Diziler C#Batu54
 
Sql egitim-cd-si
Sql egitim-cd-siSql egitim-cd-si
Sql egitim-cd-sisersld61
 
Introduction to iOS Programming && About XMPPFramework
Introduction to iOS Programming && About XMPPFrameworkIntroduction to iOS Programming && About XMPPFramework
Introduction to iOS Programming && About XMPPFrameworkAnıl Sözeri
 
İleri Seviye T-SQL Programlama - Chapter 09
İleri Seviye T-SQL Programlama - Chapter 09İleri Seviye T-SQL Programlama - Chapter 09
İleri Seviye T-SQL Programlama - Chapter 09Cihan Özhan
 
Sql egitimi-adana
Sql egitimi-adanaSql egitimi-adana
Sql egitimi-adanasersld61
 
Stored procedure
Stored procedureStored procedure
Stored procedureoktaygokgol
 
progressokulu.com Advanced Business Language Slide 4
progressokulu.com Advanced Business Language Slide 4progressokulu.com Advanced Business Language Slide 4
progressokulu.com Advanced Business Language Slide 4kaan verdioglu
 
Sql kursu-ucretleri
Sql kursu-ucretleriSql kursu-ucretleri
Sql kursu-ucretlerisersld61
 
Android'e Giriş Eğitimleri 1_2
Android'e Giriş Eğitimleri 1_2Android'e Giriş Eğitimleri 1_2
Android'e Giriş Eğitimleri 1_2Univerist
 

Similaire à BTRisk X86 Tersine Mühendislik Eğitim Sunumu - Bölüm-3 (20)

Veri̇ tabani oluşturma ve yapilandirma
Veri̇ tabani oluşturma ve yapilandirmaVeri̇ tabani oluşturma ve yapilandirma
Veri̇ tabani oluşturma ve yapilandirma
 
İleri Seviye T-SQL Programlama - Chapter 02
İleri Seviye T-SQL Programlama - Chapter 02İleri Seviye T-SQL Programlama - Chapter 02
İleri Seviye T-SQL Programlama - Chapter 02
 
Typescript
TypescriptTypescript
Typescript
 
İleri Seviye T-SQL Programlama - Chapter 21
İleri Seviye T-SQL Programlama - Chapter 21İleri Seviye T-SQL Programlama - Chapter 21
İleri Seviye T-SQL Programlama - Chapter 21
 
Temel ABAP eğitim kılavuzu
Temel ABAP eğitim kılavuzuTemel ABAP eğitim kılavuzu
Temel ABAP eğitim kılavuzu
 
Temel Düzeyde MySQL ve PHP Eğitimleri 2
Temel Düzeyde MySQL ve PHP Eğitimleri 2Temel Düzeyde MySQL ve PHP Eğitimleri 2
Temel Düzeyde MySQL ve PHP Eğitimleri 2
 
Diziler C#
Diziler C#Diziler C#
Diziler C#
 
Sql egitim-cd-si
Sql egitim-cd-siSql egitim-cd-si
Sql egitim-cd-si
 
Introduction to iOS Programming && About XMPPFramework
Introduction to iOS Programming && About XMPPFrameworkIntroduction to iOS Programming && About XMPPFramework
Introduction to iOS Programming && About XMPPFramework
 
İleri Seviye T-SQL Programlama - Chapter 09
İleri Seviye T-SQL Programlama - Chapter 09İleri Seviye T-SQL Programlama - Chapter 09
İleri Seviye T-SQL Programlama - Chapter 09
 
Hayrettin kunuk
Hayrettin kunukHayrettin kunuk
Hayrettin kunuk
 
Templates
Templates Templates
Templates
 
Sunu algo02
Sunu algo02Sunu algo02
Sunu algo02
 
Sql egitimi-adana
Sql egitimi-adanaSql egitimi-adana
Sql egitimi-adana
 
Stored procedure
Stored procedureStored procedure
Stored procedure
 
Sunu
SunuSunu
Sunu
 
progressokulu.com Advanced Business Language Slide 4
progressokulu.com Advanced Business Language Slide 4progressokulu.com Advanced Business Language Slide 4
progressokulu.com Advanced Business Language Slide 4
 
SQL Injection
SQL InjectionSQL Injection
SQL Injection
 
Sql kursu-ucretleri
Sql kursu-ucretleriSql kursu-ucretleri
Sql kursu-ucretleri
 
Android'e Giriş Eğitimleri 1_2
Android'e Giriş Eğitimleri 1_2Android'e Giriş Eğitimleri 1_2
Android'e Giriş Eğitimleri 1_2
 

Plus de BTRisk Bilgi Güvenliği ve BT Yönetişim Hizmetleri

Plus de BTRisk Bilgi Güvenliği ve BT Yönetişim Hizmetleri (19)

BTRisk - Siber Olay Tespit ve Mudahale Egitimi
BTRisk - Siber Olay Tespit ve Mudahale EgitimiBTRisk - Siber Olay Tespit ve Mudahale Egitimi
BTRisk - Siber Olay Tespit ve Mudahale Egitimi
 
BTRisk Zararlı Yazılım Analizi Eğitimi Sunumu - Bölüm 2
BTRisk Zararlı Yazılım Analizi Eğitimi Sunumu - Bölüm 2BTRisk Zararlı Yazılım Analizi Eğitimi Sunumu - Bölüm 2
BTRisk Zararlı Yazılım Analizi Eğitimi Sunumu - Bölüm 2
 
Yazıcı Güvenliği
Yazıcı GüvenliğiYazıcı Güvenliği
Yazıcı Güvenliği
 
BTRISK ISO27001 UYGULAMA EGITIMI SUNUMU
BTRISK ISO27001 UYGULAMA EGITIMI SUNUMUBTRISK ISO27001 UYGULAMA EGITIMI SUNUMU
BTRISK ISO27001 UYGULAMA EGITIMI SUNUMU
 
Sizma testi bilgi toplama
Sizma testi bilgi toplamaSizma testi bilgi toplama
Sizma testi bilgi toplama
 
Kali Linux Hakkında Herşey
Kali Linux Hakkında HerşeyKali Linux Hakkında Herşey
Kali Linux Hakkında Herşey
 
BTRisk iOS Mobil Uygulama Denetimi Eğitimi
BTRisk iOS Mobil Uygulama Denetimi EğitimiBTRisk iOS Mobil Uygulama Denetimi Eğitimi
BTRisk iOS Mobil Uygulama Denetimi Eğitimi
 
Unix Denetim Dokümanı
Unix Denetim DokümanıUnix Denetim Dokümanı
Unix Denetim Dokümanı
 
BTRisk Yazılım Güvenliği Yönetimi Eğitimi
BTRisk Yazılım Güvenliği Yönetimi EğitimiBTRisk Yazılım Güvenliği Yönetimi Eğitimi
BTRisk Yazılım Güvenliği Yönetimi Eğitimi
 
BTRisk Android Uygulamalara Malware Yerleştirme Sunumu
BTRisk Android Uygulamalara Malware Yerleştirme SunumuBTRisk Android Uygulamalara Malware Yerleştirme Sunumu
BTRisk Android Uygulamalara Malware Yerleştirme Sunumu
 
BTRisk ISO 27001:2013 Bilgilendirme ve İç Denetim Eğitimi Sunumu
BTRisk ISO 27001:2013 Bilgilendirme ve İç Denetim Eğitimi SunumuBTRisk ISO 27001:2013 Bilgilendirme ve İç Denetim Eğitimi Sunumu
BTRisk ISO 27001:2013 Bilgilendirme ve İç Denetim Eğitimi Sunumu
 
BTRİSK Web Uygulama Güvenliği Denetimi Eğitim Sunumu
BTRİSK Web Uygulama Güvenliği Denetimi Eğitim SunumuBTRİSK Web Uygulama Güvenliği Denetimi Eğitim Sunumu
BTRİSK Web Uygulama Güvenliği Denetimi Eğitim Sunumu
 
Bilgi Güvenliği Farkındalık Eğitimi Sunumu
Bilgi Güvenliği Farkındalık Eğitimi SunumuBilgi Güvenliği Farkındalık Eğitimi Sunumu
Bilgi Güvenliği Farkındalık Eğitimi Sunumu
 
BTRisk Adli Bilişim Eğitimi Sunumu
BTRisk Adli Bilişim Eğitimi SunumuBTRisk Adli Bilişim Eğitimi Sunumu
BTRisk Adli Bilişim Eğitimi Sunumu
 
BTRİSK Web Uygulama Güvenliği Denetimi Eğitimi
BTRİSK Web Uygulama Güvenliği Denetimi EğitimiBTRİSK Web Uygulama Güvenliği Denetimi Eğitimi
BTRİSK Web Uygulama Güvenliği Denetimi Eğitimi
 
BTRWATCH ISO27001 Yazılımı
BTRWATCH ISO27001 YazılımıBTRWATCH ISO27001 Yazılımı
BTRWATCH ISO27001 Yazılımı
 
Jmeter ile uygulama katmanında yük testi gerçekleştirme
Jmeter ile uygulama katmanında yük testi gerçekleştirmeJmeter ile uygulama katmanında yük testi gerçekleştirme
Jmeter ile uygulama katmanında yük testi gerçekleştirme
 
ISO 27001:2013 versiyonu ile gelen değişiklikler
ISO 27001:2013 versiyonu ile gelen değişikliklerISO 27001:2013 versiyonu ile gelen değişiklikler
ISO 27001:2013 versiyonu ile gelen değişiklikler
 
Android Uygulamaların Tersine Mühendislik Yöntemi ile İncelenmesi
Android Uygulamaların Tersine Mühendislik Yöntemi ile İncelenmesiAndroid Uygulamaların Tersine Mühendislik Yöntemi ile İncelenmesi
Android Uygulamaların Tersine Mühendislik Yöntemi ile İncelenmesi
 

BTRisk X86 Tersine Mühendislik Eğitim Sunumu - Bölüm-3

  • 3. İÇ İÇE DÖNGÜLER • İç içe döngülerin analizini kolaylaştırmak için renklendirme ve gruplama yöntemlerinden faydalanabiliriz. • Gruplama ve Analiz Metodu Önerisi  Kalın mavi çizgiyi bul (döngü çizgisi)  Kalın çizginin ok başından geriye doğru takip et o Eğer bunu yaparken bir başka kalın mavi çizgiye rastlarsan önce iç döngüyü grupla  Döngüyü grupla  Tüm döngüler gruplandıktan sonra fonksiyonun başından itibaren analiz etmeye başla o Pseudo Code ile tespitleri not et o Tekrar grupla ve analize devam et ÖN BİLGİ
  • 4. VERİ YAPILARI [STRUCTURES] • Assembly kodu içinde belli bir adresin offset'ine erişim gözlendiğinde bu bir veri yapısı [structure] kullanımına işaret olabilir. • Bu durumda okunabilirliği artırmak için IDA'nın veri yapıları imkanından faydalanabiliriz. • İç içe döngüler ile birlikte bu konuyla ilgili uygulama örneğini gerçekleştireceğiz. ÖN BİLGİ
  • 5. VERİ YAPILARI [STRUCTURES] ÖN BİLGİ Veri yapılarının anlamlandırılmasıyla ilgili aşağıdaki kod parçasının Assembly'ye dönüşümü ve veri yapısını IDA'da modelledikten sonra bunu koda yansıtma örneğini görebilirsiniz.
  • 6. ÖN BİLGİ İÇ İÇE DÖNGÜLER VE VERİ YAPILARI DEMO #include <stdio.h> typedef struct veriYapisi { int rakam; int faktoriyel; struct veriYapisi *sonraki; } bilesen; bilesen bilesen1 = { 5, 0, NULL }; bilesen bilesen2 = { 7, 0, &bilesen1 }; bilesen bilesen3 = { 3, 0, &bilesen2 }; bilesen bilesen4 = { 4, 0, &bilesen3 }; bilesen bilesen5 = { 2, 0, &bilesen4 }; bilesen bilesen6 = { 8, 0, &bilesen5 }; int main() { int i,j; bilesen *cursor = &bilesen6; int rakam; for (i = 1; i<=6; i++) { cursor->faktoriyel = 1; for (j = 1; j <= cursor->rakam; j++) { cursor- >faktoriyel = cursor->faktoriyel * j; } cursor = cursor->sonraki; } cursor = &bilesen6; for (i = 1; i<=6; i++) { printf("%d faktoriyel = %dn", cursor- >rakam, cursor->faktoriyel); cursor = cursor->sonraki; } getchar(); return 0; } Örnek olarak inceleyeceğimiz kodumuzda içinde [2] INTEGER ve bir [STRUCT POINTER] barındıran bir veri yapısını kullanacağız. Bu veri yapılarından oluşmuş bir dizi veriyi [GLOBAL] değişken olarak tanımladık ve [OFFSET]'leri bir zincir liste oluşturacak biçimde ayarladık.
  • 7. ÖN BİLGİ İÇ İÇE DÖNGÜLER VE VERİ YAPILARI DEMO Bir [CURSOR] kullanarak zincir liste [LINKED LIST] üzerinden gezerken [faktoriyel] alanlarına [rakam] verisinin faktoriyelini hesaplayarak yazıyoruz.
  • 8. ÖN BİLGİ İÇ İÇE DÖNGÜLER VE VERİ YAPILARI DEMO Derlenmiş kodumuzu IDA ile açalım.
  • 9. ÖN BİLGİ İÇ İÇE DÖNGÜLER VE VERİ YAPILARI DEMO Kodu sadeleştirmek için döngüleri gruplama yoluna gideceğiz. Bunun için daha önce de belirlediğimiz gibi önce iç içe döngülerde en iç döngülere yönlenmemiz lazım. Genel yaklaşım olarak fonksiyonun sonuna en yakın döngüden gruplamaya başlayabiliriz. Kodun sonundaki döngüyü oluşturan 3 bloğu [CTRL] tuşunu basılı tutarak seçelim.
  • 10. ÖN BİLGİ İÇ İÇE DÖNGÜLER VE VERİ YAPILARI DEMO Seçtiğimiz blokları aynı renge boyamak için sağ klikleyerek [Set node color] seçeneğini seçelim.
  • 11. ÖN BİLGİ İÇ İÇE DÖNGÜLER VE VERİ YAPILARI DEMO Seçtiğimiz blokları renklendirelim.
  • 12. ÖN BİLGİ İÇ İÇE DÖNGÜLER VE VERİ YAPILARI DEMO Blokları gruplayıp tek bir kutu şeklinde ifade etmek için sağ klikleyip [Group nodes] seçeneğini seçelim.
  • 13. ÖN BİLGİ İÇ İÇE DÖNGÜLER VE VERİ YAPILARI DEMO Grubumuza [DONGU_1] adını verebiliriz.
  • 14. ÖN BİLGİ İÇ İÇE DÖNGÜLER VE VERİ YAPILARI DEMO [DONGU_1] grubunun toplanmış hali soldaki gibi olacaktır.
  • 15. ÖN BİLGİ İÇ İÇE DÖNGÜLER VE VERİ YAPILARI DEMO Kalan bölümdeki kodları incelediğimizde iç içe 2 döngü olduğunu görebiliriz. Bunlardan içte olanını oluşturan blokları seçip renklendirelim.
  • 16. ÖN BİLGİ İÇ İÇE DÖNGÜLER VE VERİ YAPILARI DEMO Yeni grubumuza [DONGU_2] adını verebiliriz.
  • 17. ÖN BİLGİ İÇ İÇE DÖNGÜLER VE VERİ YAPILARI DEMO Bu grubu da toplayarak kodu sadeleştirmeye devam edelim.
  • 18. ÖN BİLGİ İÇ İÇE DÖNGÜLER VE VERİ YAPILARI DEMO Son olarak dıştaki döngüyü oluşturan blokları seçelim ve renklendirelim.
  • 19. ÖN BİLGİ İÇ İÇE DÖNGÜLER VE VERİ YAPILARI DEMO Son grubumuzu da [DONGU_3] olarak adlandırıp toplayalım. Görüleceği gibi kod analiz için oldukça sadeleşti, şimdi sıra kod bloklarının oluşturduğu grupları adım adım açarak anlamlandırmakta.
  • 20. ÖN BİLGİ İÇ İÇE DÖNGÜLER VE VERİ YAPILARI DEMO Demo uygulamamızı diğer örneklerde olduğu gibi detaylı olarak incelemeyeceğiz. Ancak [var_C] değişkenine atanan offset adresine çift tıklayarak bu alanda bulunan verilere göz atalım.
  • 21. ÖN BİLGİ İÇ İÇE DÖNGÜLER VE VERİ YAPILARI DEMO IDA için bu [.data] section'ında bulunan bu alanın özel bir anlamı yok, o nedenle BYTE BYTE görüntülüyor veriyi.
  • 22. ÖN BİLGİ İÇ İÇE DÖNGÜLER VE VERİ YAPILARI DEMO Diyelimki detaylı bir analiz yaptık ve bu veri yapısının [3] adet DWORD'den oluştuğu kanaatine vardık. Bu durumda veri alanları üzerinde [d] tuşuna [3] defa basarak veriyi [DWORD – dd] formatına çevirebiliriz.
  • 23. ÖN BİLGİ İÇ İÇE DÖNGÜLER VE VERİ YAPILARI DEMO Oluşturduğumuz ilk veri yapısı bloğunun son alanındaki offset bilgisinden faydalanarak zincir listeyi oluşturan diğer veri yapısı alanlarını da ortaya çıkarabiliriz.
  • 24. ÖN BİLGİ İÇ İÇE DÖNGÜLER VE VERİ YAPILARI DEMO Detaylı kod analizi ve veri yapılarını inceleyerek ortaya çıkardığımız bilgileri koda yansıtabilmek ve kodun okunabilirliğini artırabilmek için önce IDA'ya bir veri yapısı tanımı yapmamız gerekir.
  • 25. ÖN BİLGİ İÇ İÇE DÖNGÜLER VE VERİ YAPILARI DEMO [INSERT] tuşuna basarak yeni oluşturacağımız veri yapısının adını [VERI_YAPISI] verelim.
  • 26. ÖN BİLGİ İÇ İÇE DÖNGÜLER VE VERİ YAPILARI DEMO [d] tuşuna basarak veri yapısını oluşturan alanları tanımlayalım ve [d] tuşuna 2 defa daha basarak bu veri alanlarının büyüklüklerini [DWORD]'e dönüştürelim.
  • 27. ÖN BİLGİ İÇ İÇE DÖNGÜLER VE VERİ YAPILARI DEMO Kodu detaylı olarak incelediğimizi, [var_C] lokal değişkeninde bulunan veri yapısı adresinin önce [EAX] register'ına aktarıldığını ve bunun [+4] byte offset'inde de tespit ettiğimiz bir alanın var olduğunu bildiğimizi varsayalım.
  • 28. ÖN BİLGİ İÇ İÇE DÖNGÜLER VE VERİ YAPILARI DEMO [4] rakamını tıkladıktan sonra sağ klikleyerek context menü'yü açalım. Burada tanımladığımız veri yapısını seçerek kodun anlaşılabilirliğini artıralım.
  • 29. ÖN BİLGİ İÇ İÇE DÖNGÜLER VE VERİ YAPILARI DEMO Kod yanda görüldüğü gibi bir veri yapısının içindeki bir bileşene referans verildiğini belirtecek hale gelerek anlaşılırlığı artacaktır.
  • 30. 6. AŞAMA Ana fonksiyonda 4. aşama olarak tahmin ettiğimiz fonksiyonun içine girelim.
  • 31. 6. AŞAMA Bu fonksiyon diğerlerine nazaran oldukça kompleks ve çok sayıda döngü içeriyor. Bu döngülerin bazıları da iç içe [nested] döngüler gibi görünüyor. NOT: IDA'nın döngüleri daha belirgin hale getirmek için KOYU MAVİ çizgiler kullandığından daha önce bahsetmiştik.
  • 32. 6. AŞAMA Karmaşık bir kodla karşı karşıya olduğumuzda, ki iç içe döngüler içeren bir kod karmaşık olabilir, belli kod bölümlerini renklendirerek diğer bölümlerden ayrıştırmak isteyebiliriz. İç içe döngüleri daha anlaşılabilir hale getirmek için yapılabilecek bir diğer uygulama döngüleri oluşturan kod bölümlerini gruplamak ve bu grupları kapatmak olabilir
  • 33. 6. AŞAMA İç içe döngüleri kapatmaya en içteki döngülerden başlamalıyız. Bir genelleme yapamayız ancak en içteki döngülerin sıklıkla bulundukları bölüm fonksiyondan çıkış noktasına yakın olan alanlardır. Öyleyse [RETN] instruction'ına yakın olan döngüye bir göz atabilir ve bu kod alanlarını renklendirebiliriz.
  • 34. 6. AŞAMA En içteki döngüyü oluşturan kod bloklarını renklendirelim. Renklendirmeye [CMP] instruction'ını barındıran test bölümünden başlayıp sayacın artırıldığı kod bölümüne kadar devam edelim.
  • 35. 6. AŞAMA Döngümüze test bloğundan önce gelen "initialization" bloğunu da ekleyelim. Bu kod karmaşasında bu bölümü bulmak zor olsa da kod akış kollarını takip ederek ve sayaç olarak kullanılan lokal değişken veya register'ı highlight ederek bu bloğu da bulabiliriz.
  • 36. 6. AŞAMA Döngü kod bloklarını gruplamadan önce [CTRL] tuşuna basılı tutarak blokları seçelim. Blokların başlık bölümlerinin griye dönmesi seçme işleminin başarılı olduğunu gösterir.
  • 37. 6. AŞAMA Seçilen tüm kod bloklarını gruplamadan önce [SAĞ KLİK]leyerek context menü'nün açılmasını sağlayalım ve [Group nodes] seçeneğini seçelim.
  • 38. 6. AŞAMA Oluşturacağımız gruba bir isim vermemiz gerekiyor. Döngüler üzerinde çalıştığımız için bu grubu [DONGU_1] olarak isimlendirebiliriz.
  • 39. 6. AŞAMA Bu kod bloğunu grupladığımızda kodun anlaşılabilirliğine katkıda bulunmuş olduk.
  • 40. 6. AŞAMA İç içe döngüleri basitleştirmek için içten dışa doğru bir yaklaşımın doğru olacağını söylemiştik. Şimdi [DONGU_1]'in bir dışındaki döngüyü gruplamaya çalışalım. Renklendirmeyi kullanmak blokları ayrıştırmak için duyduğumuz ihtiyaca bağlı, ancak biz tüm döngüleri netleştirmek için boyamaya devam edebiliriz.
  • 41. 6. AŞAMA Yine [CTRL] tuşunu basılı tutarken grubun parçası olan kutuları seçebiliriz ve sağ klik ile gelen Context Menü'den faydalanarak bu kutuları [node] gruplayabiliriz.
  • 42. 6. AŞAMA Bu grubu da [DONGU_2] olarak isimlendirebiliriz.
  • 43. 6. AŞAMA 2. döngüyü de gruplandırdıktan sonra bir üst döngünün daha olduğunu görebiliriz. Ancak sol taraftaki kod bloklarına baktığımızda bu bacakta da iç içe döngüler var gibi görünüyor. Önce iç döngüleri gruplama prensibimiz gereği üst seviyedeki döngüye geçmeden önce [DONGU_2] seviyesindeki diğer alanları da sadeleştirmemizde fayda var.
  • 44. 6. AŞAMA Sol taraftaki döngünün bileşenlerini tespit etmeye çalışalım.
  • 45. 6. AŞAMA Bu grubu da daha kolay ayrıştırmak için farklı bir renge boyayalım. Döngüleri gruplarken "initialization" kutularını da dahil ettiğimize dikkat edin.
  • 46. 6. AŞAMA Bu grubumuza da [DONGU_3] adını verelim.
  • 47. 6. AŞAMA Döngüleri grupladıkça kodun nasıl daha kolay anlaşılabilir hale geldiğine dikkat edin. Elbette hatalı grupladığımız veya yanlış yerden başladığımız durumlar olabilir, ancak bu grupları tekrar oluşturma imkanımız var. [DONGU_3]'ü grupladıktan sonra bu grubu da içine alan bir başka döngü olduğunu görebiliyoruz.
  • 48. 6. AŞAMA [DONGU_3] 'ü de içine alan döngü bloğunu renklendirelim.
  • 49. 6. AŞAMA Son grubumuza da [DONGU_4] adını verelim.
  • 50. 6. AŞAMA Yeni bir iç döngüyü belirleyelim. Döngüleri sunum sayfasında incelemek daha zor, IDA ekranında daha rahat biçimde analizimizi gerçekleştirebiliriz.
  • 51. 6. AŞAMA Yeni grubumuzu renklendirelim.
  • 52. 6. AŞAMA Bu gruba da [DONGU_5] adını verelim.
  • 53. 6. AŞAMA [DONGU_5]'i de içine alan bir üst döngüyü belirleyelim.
  • 54. 6. AŞAMA Yeni grubumuzu renklendirelim.
  • 55. 6. AŞAMA Bu gruba da [DONGU_6] adını verelim.
  • 56. 6. AŞAMA Tüm döngüleri gruplandırdıktan sonra kod çok basit bir hale geldi. Şimdi yeri geldikçe grupları açarak nasıl bir algoritma barındırdıklarını incelemeye geçebiliriz.
  • 57. 6. AŞAMA Fonksiyonumuz başlarında [var_C] değişkenimize bir offset adresi atanıyor.
  • 58. 6. AŞAMA Bu offset'e geldiğimizde anlamlı bir bilgi göremiyoruz, en azından bize anlam ifade edebilecek ASCII bir veri barındırmıyor bu alan.
  • 59. 6. AŞAMA Bu offset'in ne olduğunu bilmesek de [var_C] lokal değişkenine erişilen diğer noktalarda bu değişkenin bir adres bilgisi barındırdığını belirtmemizde fayda var.
  • 60. 6. AŞAMA Bu değişkeni [BILINMEYEN_OFFSET] olarak isimlendirebiliriz.
  • 61. 6. AŞAMA Bu bloktaki çağrılan fonksiyonlara göz attığımızda daha önceden analiz ettiğimiz bir fonksiyona rastlıyoruz. Fonksiyonun işlevini hatırlamak için tekrar [ALTI_INT_OKU] fonksiyonunu ziyaret edelim.
  • 62. 6. AŞAMA Bu fonksiyon kendisine verilen bir string'in içinden okuduğu 6 INTEGER değeri 2. parametre olarak aldığı adres ve sonrasındaki alanlara yazıyordu.
  • 63. 6. AŞAMA [ASAMA_6] fonksiyonumuz tek parametre alıyor görünüyor.
  • 64. 6. AŞAMA Kodu anlamlandırmak amacıyla bu parametrenin adını [PRM_GIRDI] olarak düzenleyelim.
  • 65. 6. AŞAMA Fonksiyon parametresi ile verilen değerin [ALTI_INT_OKU] fonksiyonu çağrılmadan hemen önce atandığı lokal değişkenin adını [L_PRM_GIRDI] olarak düzenleyebiliriz. Bu alan aynı zamanda [ALTI_INT_OKU] fonksiyonuna verilen 1. parametre.
  • 66. 6. AŞAMA [ALTI_INT_OKU] fonksiyonu ile ilgili 2 parametre aldığı ve 2. parametrenin de okunan 6 INTEGER'ın yazılması için kullanılacağını biliyoruz. Bu nedenle stack'te bu adresin yazılacağı alana [L_PTR_INT_GECICI] adını verebiliriz.
  • 67. 6. AŞAMA Stack'te [ALTI_INT_OKU] fonksiyonuna verilen adresin kendisi ise [var_38] alanının adresi. Bu alanı da [L_PTR_INT] olarak adlandırabiliriz. Bu adres okunan INTEGER değerlerinin arka arkaya yazılacağı alanın başlangıç adresi.
  • 68. 6. AŞAMA [DONGU_6] grubunu açtığımızda döngünün sayacı olarak [var_5C] alanının kullanıldığını rahatlıkla görebiliyoruz.
  • 69. 6. AŞAMA Bu alanı anlamlandırmak için adını [VAR_I] olarak değiştirelim. Burada sayacın [0] ile initialize edildiğini, [5] ve daha altı olduğu durumlarda (yani <6) döngüde kalmaya devam edildiğini görebiliyoruz.
  • 70. 6. AŞAMA Grubun en altındaki blokta sayacımızın "1" artırıldığını [INC] görebiliyoruz.
  • 71. 6. AŞAMA PSEUDO CODE (yani kod benzeri deyimlerle ifade etme) yaklaşımı ile analiz ettiğimiz algoritmanın netleştirilmesi yöntemini daha önce de kullanmıştık. Bu yönteme bu fonksiyon gibi çok karmaşık fonksiyonlarda daha da fazla ihtiyacımız var. O nedenle algoritmanın analiz ettiğimiz bölümleri için bu yöntemi kullanacağız. PSEUDO CODE int girdi[6] for(VAR_I=0;VAR_I<6;VAR_I++) { ... }
  • 72. 6. AŞAMA Eklediğimiz yorum satırında da görüldüğü gibi okunan INTEGER'lar [0] veya daha küçük olamazlar.
  • 73. 6. AŞAMA Hemen aşağıdaki blokta da okunan INTEGER değerlerinin [6]'dan büyük olamayacaklarını görebiliyorz.
  • 74. 6. AŞAMA PSEUDO CODE int girdi[6] for(VAR_I=0;VAR_I<6;VAR_I++) if (girdi[VAR_I] <= 0 || girdi[VAR_I] > 6) HATALI_DENEME()
  • 75. 6. AŞAMA [DONGU_6] içinde [DONGU_5]'i barındırıyor. Dış döngüyü analiz ettikten sonra onun içindeki döngüye geçebiliriz.
  • 76. 6. AŞAMA [DONGU_5]'in sayacı olarak [var_60] lokal değişkeninin kullanıldığını görüyoruz. [var_60] önce "[VAR_I]+1" ile initialize ediliyor. [6]'dan küçük olduğu müddetçe de iç döngüde kalmaya devam ediyor uygulama.
  • 77. 6. AŞAMA Kodu daha okunur hale getirebilmek için [var_60] değişkeninin adını [VAR_J] olarak değiştirelim.
  • 78. 6. AŞAMA Daha önce de bahsettiğimiz [VAR_J] değişkeninin bir üst döngünün sayacı olan [VAR_I] sayacına [1] eklenerek initialize edildiği kod bölümü.
  • 79. 6. AŞAMA Yine daha önce bahsettiğimiz [VAR_J] değişkeninin [5]'in üzerine çıkması halinde döngüden çıktığı kod bölümü.
  • 80. 6. AŞAMA Dıştaki döngü [6] INTEGER değerinin üzerinden dönerken, içteki döngü de incelenmekte olan INTEGER değerinden sonra gelen değerler üzerinden dönüyor. Eğer bu değerler birbirleri ile aynı ise oyun sonlanıyor. Dolayısıyla girilen [6] INTEGER'ın birbirlerinden farklı olmak zorunda olduğunu söyleyebiliriz.
  • 81. 6. AŞAMA [VAR_J] sayacımızın artırıldığı (VAR_J++] kod bölümü.
  • 82. 6. AŞAMA PSEUDO CODE int girdi[6] for(VAR_I=0;VAR_I<6;VAR_I++) if (girdi[VAR_I] <= 0 || girdi[VAR_I] > 6) HATALI_DENEME() for(VAR_J=VAR_I+1; VAR_J<6;VAR_J++) if(girdi[VAR_I]==girdi[VAR_J]) HATALI_DENEME()
  • 83. 6. AŞAMA [DONGU_5] kod grubunu incelememiz bittiğine göre kod karmaşıklığını azaltmak üzere tekrar geriye toplayabiliriz.
  • 84. 6. AŞAMA Aynı şekilde [DONGU_6] grubunu da geriye toplayabiliriz. Sıra [DONGU_4] grubunda.
  • 85. 6. AŞAMA [DONGU_6] grubu toplandıktan sonra IDA yine eskisi gibi görünecek.
  • 86. 6. AŞAMA Şimdi [DONGU_4]'ü [Ungroup] ederek incelemeye başlayabiliriz.
  • 87. 6. AŞAMA Şimdi [DONGU_4]'ü [Ungroup] ederek incelemeye başlayabiliriz. Derleyicimiz sayaç olarak yine [VAR_I]'yı kullanmayı uygun görmüş. Bu döngüde de benzer biçimde [VAR_I] [0] ile initialize ediliyor , sayaç her döngüde [1] artırılıyor ve indeks [6]'dan küçük ise döngüde kalmaya devam ediliyor.
  • 88. 6. AŞAMA PSEUDO CODE int girdi[6] for(VAR_I=0;VAR_I<6;VAR_I++) if (girdi[VAR_I] <= 0 || girdi[VAR_I] > 6) HATALI_DENEME() for(VAR_J=VAR_I+1; VAR_J<6;VAR_J++) if(girdi[VAR_I]==girdi[VAR_J]) HATALI_DENEME() for(VAR_I=0;VAR_I<6;VAR_I++)
  • 89. 6. AŞAMA Bu haliyle döngünün son bloğunu anlamlandıramıyoruz, [var_10] ve [var_58] lokal değişkenlerinin ne için kullanıldığına dair bir fikrimiz yok. O yüzden iç döngü olan [DONGU_3] döngüsünü incelemeye başlayabiliriz.
  • 90. 6. AŞAMA [DONGU_3]'ün içinde [BILINMEYEN_OFFSET] adresi tekrar karşımıza çıktı. [var_10] lokal değişkenine atanan adres de bu offset adresi. Bu yüzden bu offset'teki verinin ne olduğunu anlamaya çalışırsak iyi olur.
  • 91. 6. AŞAMA Tekrar hatırlamak için [BILINMEYEN_OFFSET] lokal değişkenine ilgili adresin ilk atandığı fonksiyonun başlarındaki kod bölümüne göz atabiliriz.
  • 92. 6. AŞAMA [0x40304C] adresini tekrar ziyaret edelim. Daha önce de bu alanın byte'lara bölünmüş halde pek bir anlam ifade etmediğini değerlendirmiştik. Ancak aşağıya ve yukarıya doğru offset adreslerine benzer veriler olduğunu görebiliyoruz.
  • 93. 6. AŞAMA [BILINMEYEN_OFFSET] lokal değişkeninin değeri [var_10] lokal değişkenine atandıktan sonra bu değişkene referans veren diğer kod bölümlerine göz atalım.
  • 94. 6. AŞAMA Kodun alt bölümlerinde [var_10] lokal değişkeninde bulunan adresin [+8] offset'inde bulunan bir DWORD değerin [EAX] register'ına atandığını ve bunun da tekrar [var_10] lokal değişkenine atandığını görüyoruz. Bu durumda [BILINMEYEN_OFFSET] adresindeki verileri DWORD değerlerine dönüştürmeyi düşünebiliriz.
  • 95. 6. AŞAMA Veri tipinin üzerine tıkladıktan sonra [d] tuşuna [2] defa basarak byte'ları DOUBLE WORD'lere [dd] dönüştürebiliriz. Art arda 3 DWORD verisi oluşturduğumuzda son DWORD'ün bir başka offset'in adresini içerdiğini görebiliyoruz.
  • 96. 6. AŞAMA Şimdi aynı işlemi ortaya çıkardığımız offset olan [0x403040] adresine atlayarak gerçekleştirelim.
  • 97. 6. AŞAMA Bu adresteki 3. DWORD değeri de [0x403034] değerini içeriyor. Bu da bir adrese benziyor. Aynı işlemi bu adreste de gerçekleştirelim.
  • 98. 6. AŞAMA Aynı işlemi gerçekleştirdiğimiz 6. alanda son DWORD değeri [0] olarak karşımıza çıkıyor. Bu noktadan sonra tekrar aynı işlemi uygulayamıyoruz.
  • 99. 6. AŞAMA Son incelemelerimizden sonra bir veri yapısıyla [STRUCTURE] karşı karşıya olduğumuzu söyleyebiliriz. IDA PRO, kodu daha anlaşılır hale getirebilmek için veri yapılarını ifade edebileceğimiz bir imkan sağlıyor. Bu imkanı kullanabilmek için [Structures] penceresine geçelim.
  • 100. 6. AŞAMA Yeni bir veri yapısı eklemek için [INSERT] tuşuna basalım.
  • 101. 6. AŞAMA Yeni bir veri yapımızın adını [VERI_YAPISI] olarak verelim.
  • 102. 6. AŞAMA [VERI_YAPISI] isimli veri yapımız ekranda ortaya çıktı. Şimdi veri yapımızın içeriğini tanımlayalım.
  • 103. 6. AŞAMA Açıkçası veri yapısının alanlarını henüz net olarak anlayamadık. Ancak her bir veri yapısının 3 adet [DWORD] içerdiğini düşünüyoruz. Bir [DATA veri yapısı bileşeni oluşturmak için [D] tuşuna basalım.
  • 104. 6. AŞAMA [DATA] alanının büyüklüğünün [DWORD] olduğunu belirtmek için veri alanını [D] tuşu ile oluşturduktan sonra 2 defa [d] tuşuna basalım ve bu alanı [dd] olarak belirleyelim. Daha sonra ne amaçla kullanıldığını henüz bilmediğimiz bu alana üzerine tıkladıktan ve [N] tuşuna bastıktan sonra [ALAN_1] adını verelim.
  • 105. 6. AŞAMA Yeni veri alanlarını eklemek için ALTTAKİ [VERI_YAPISI] adına tıkladıktan sonra [D] tuşuna basalım. Bu şekilde 3 [DWORD] alan tanımladıktan sonra son alana [NEXT_OFFSET] adını verelim. Çünkü bu alanın bir offset adresi barındırdığından eminiz ve son veri yapısının 3. DWORD alanında [0] yani [NULL] değerinin bulunması da karşımızda bir zincir liste [LINKED LIST] olma ihtimalini güçlendirdi.
  • 106. 6. AŞAMA Bu offset'in veri yapısının bir alanı olduğunu belirtmek için [8] rakamına tıkladıktan sonra sağ klikleyerek context menü'sünü açalım ve [VERI_YAPISI.NEST_OFFSET] seçeneğini tıklayalım.
  • 107. 6. AŞAMA Bu işlemden sonra kod daha okunaklı hale gelecek ve aktarılan verinin bir veri yapısının bir bileşeni olduğunu daha rahat anlayabileceğiz.
  • 108. 6. AŞAMA Bu noktada ilk offset'in bir zincir listenin ilk zinciri olduğunu varsayabiliriz.
  • 109. 6. AŞAMA Bu nedenle [BILINMEYEN_OFFSET] lokal değişken adını [LISTE_BASI] olarak değiştirelim.
  • 110. 6. AŞAMA PSEUDO CODE int girdi[6] struct { int ALAN_1 int ALAN_2 int next_item } item; item LISTE_BASI = 0X40304C for(VAR_I=0;VAR_I<6;VAR_I++) if (girdi[VAR_I] <= 0 || girdi[VAR_I] > 6) HATALI_DENEME() for(VAR_J=VAR_I+1; VAR_J<6;VAR_J++) if(girdi[VAR_I]==girdi[VAR_J]) HATALI_DENEME() for(VAR_I=0;VAR_I<6;VAR_I++)
  • 111. 6. AŞAMA [LISTE_BASI] adresi [var_10] lokal değişkenine atandıktan sonra her bir döngüde zincir liste içindeki bir sonraki bileşenin [NEXT_OFFSET] adresinin [var_10] adresine atandığını görebiliyoruz.
  • 112. 6. AŞAMA Yazılımlarda genellikle zincir listenin üzerinde çalışılan bileşeninin adresinin tutulduğu değişkene [CURSOR] adı verilir. Biz de [var_10] lokal değişkenini bu şekilde adlandırabiliriz.
  • 113. 6. AŞAMA PSEUDO CODE int girdi[6] struct { int ALAN_1 int ALAN_2 int next_item } item; item LISTE_BASI = 0X40304C for(VAR_I=0;VAR_I<6;VAR_I++) if (girdi[VAR_I] <= 0 || girdi[VAR_I] > 6) HATALI_DENEME() for(VAR_J=VAR_I+1; VAR_J<6;VAR_J++) if(girdi[VAR_I]==girdi[VAR_J]) HATALI_DENEME() for(VAR_I=0;VAR_I<6;VAR_I++) item CURSOR = LISTE_BASI
  • 114. 6. AŞAMA Bu döngüde daha önceden [VAR_J] olarak adlandırdığımız sayacın kullanıldığını, önce [1] değeri ile initialize edildiğini, her döngüde girdi olarak verilen INTEGER ARRAY'inin [VAR_I] indeksindeki değerin [VAR_J] değeri ile karşılaştırıldığını , bu değer [VAR_J] değerini aşıncaya kadar [CURSOR]'ün bir sonraki bileşene işaret edecek şekilde ilerletildiğini ve tabi ki [VAR_J] değerinin artırıldığını görebiliyoruz.
  • 115. 6. AŞAMA Burada [L_PTR_INT] lokal değişkeninin fonksiyonun başında okuduğumuz [6] INTEGER değerinin yazıldığı INTEGER ARRAY'inin başlangıç adresini işaret ettiğini tekrar hatırlayalım.
  • 116. 6. AŞAMA PSEUDO CODE int girdi[6] struct { int ALAN_1 int ALAN_2 int next_item } item; item LISTE_BASI = 0X40304C for(VAR_I=0;VAR_I<6;VAR_I++) if (girdi[VAR_I] <= 0 || girdi[VAR_I] > 6) HATALI_DENEME() for(VAR_J=VAR_I+1; VAR_J<6;VAR_J++) if(girdi[VAR_I]==girdi[VAR_J]) HATALI_DENEME() for(VAR_I=0;VAR_I<6;VAR_I++) item CURSOR = LISTE_BASI for(VAR_J=1; VAR_J<girdi[VAR_I];VAR_J++) CURSOR=CURSOR->NEXT_ITEM
  • 117. 6. AŞAMA Veri yapılarına da bakarak bu karmaşık kod bölümünü anlamlandırmaya çalıştığımızda bizim gireceğimiz INTEGER dizisindeki her bir rakam için zincir listenin başından itibaren girilen rakam indeksine kadar ilerleneceği sonucuna varabiliriz. Peki zincirin bu bileşenine gelindiğinde ne olarak, bunu analizimizin devamında anlamayı ümit ediyoruz.
  • 118. 6. AŞAMA Evet bu bölümler oldukça karmaşık, ancak odaklanarak dikkatli incelediğimizde yeni oluşturulan bir lokal değişken array'inin ilgili [VAR_I] indeksi için mevcut [CURSOR]'ümüzün değerinin yazıldığını anlayabiliriz.
  • 119. 6. AŞAMA Bu nedenle [var_58] lokal değişkenine [OFFSET_ARRAY] adını verelim.
  • 120. 6. AŞAMA PSEUDO CODE int girdi[6] struct { int ALAN_1 int ALAN_2 int next_item } item; item LISTE_BASI = 0X40304C for(VAR_I=0;VAR_I<6;VAR_I++) if (girdi[VAR_I] <= 0 || girdi[VAR_I] > 6) HATALI_DENEME() for(VAR_J=VAR_I+1; VAR_J<6;VAR_J++) if(girdi[VAR_I]==girdi[VAR_J]) HATALI_DENEME() for(VAR_I=0;VAR_I<6;VAR_I++) item CURSOR = LISTE_BASI for(VAR_J=1; VAR_J<girdi[VAR_I];VAR_J++) CURSOR=CURSOR->NEXT_ITEM OFFSET_ARRAY[VAR_I]=CURSOR
  • 121. 6. AŞAMA [DONGU_3]'ü analiz ettik ve bu sırada bir üst döngü olan [DONGU_4]'ün eksik kalan kod bölümünü de anlamlandırmış olduk. Bu nedenle [DONGU_3] kod grubunu tekrar toplayabiliriz.
  • 122. 6. AŞAMA [DONGU_4]'ü incelememiz de bittiğine göre onu da kapatabiliriz. Şimdi sıra [DONGU_2]'de.
  • 123. 6. AŞAMA [DONGU_2] grubunu açmak için bu grubu seçerek sağ klikleyip [Ungroup nodes] seçeneğini tıklayalım.
  • 124. 6. AŞAMA [DONGU_2] grubunda [OFFSET_ARRAY]'in başlangıç adresindeki değer önce [LISTE_BASI] alanına yazılıyor, nihai olarak da [CURSOR] değişkenine yazılıyor. Yani [CURSOR] [OFFSET_ARRAY]'in ilk bileşenini taşıyacak biçimde yenileniyor. [LISTE_BASI] değişkeni ise artık [OFFSET_ARRAY]'in ilk bileşenini içerecek biçimde güncelleniyor.
  • 125. 6. AŞAMA PSEUDO CODE int girdi[6] struct { int ALAN_1 int ALAN_2 int next_item } item; item LISTE_BASI = 0X40304C for(VAR_I=0;VAR_I<6;VAR_I++) if (girdi[VAR_I] <= 0 || girdi[VAR_I] > 6) HATALI_DENEME() for(VAR_J=VAR_I+1; VAR_J<6;VAR_J++) if(girdi[VAR_I]==girdi[VAR_J]) HATALI_DENEME() for(VAR_I=0;VAR_I<6;VAR_I++) item CURSOR = LISTE_BASI for(VAR_J=1; VAR_J<girdi[VAR_I];VAR_J++) CURSOR=CURSOR->NEXT_ITEM OFFSET_ARRAY[VAR_I]=CURSOR LISTE_BASI=OFFSET_ARRAY[0] CURSOR=OFFSET_ARRAY[0]
  • 126. 6. AŞAMA Bu döngüde [VAR_I] değişkeni sayaç olarak kullanılıyor ve [1] olarak initialize ediliyor. Döngüden çıkış koşulu da [VAR_I] değişkeninin [6]'dan küçük olması (çünkü 5'ten büyük olursa döngü devam ediyor)
  • 127. 6. AŞAMA PSEUDO CODE int girdi[6] struct { int ALAN_1 int ALAN_2 int next_item } item; item LISTE_BASI = 0X40304C for(VAR_I=0;VAR_I<6;VAR_I++) if (girdi[VAR_I] <= 0 || girdi[VAR_I] > 6) HATALI_DENEME() for(VAR_J=VAR_I+1; VAR_J<6;VAR_J++) if(girdi[VAR_I]==girdi[VAR_J]) HATALI_DENEME() for(VAR_I=0;VAR_I<6;VAR_I++) item CURSOR = LISTE_BASI for(VAR_J=1; VAR_J<girdi[VAR_I];VAR_J++) CURSOR=CURSOR->NEXT_ITEM OFFSET_ARRAY[VAR_I]=CURSOR LISTE_BASI=OFFSET_ARRAY[0] CURSOR=OFFSET_ARRAY[0] for(VAR_I=1;VAR_I<6;VAR_I++)
  • 128. 6. AŞAMA Biraz karmaşık olan son kod bloğunda önce [CURSOR] pointer'ı [EDX] register'ına yazılıyor. Daha sonra [OFFSET_ARRAY]'inin [1]'den başlatılmış olan [VAR_I] sayacı kadar içerideki bileşenin değeri [CURSOR]'ın işaret ettiği zincir liste bileşeninin [8] byte offset'ine yazılıyor. Bu offset'in ne olduğunu daha önce analiz etmiş ve [Structures] penceresinde tanımlamıştık. Bu tanımlamayı buraya da aktaralım.
  • 129. 6. AŞAMA [8] rakamının üzerine tıklayıp sağ klikleyerek bu veriyi anlamlandırmak üzere [VERI_YAPISI.NEXT_OFFSET] seçeneğini klikleyelim.
  • 130. 6. AŞAMA Bu anlamlandırmayı yaptıktan ve dikkatle inceledikten sonra bu bölümde gerçekleşen olayın [CURSOR] ile işaret edilen zincir liste bileşeninin [NEXT_OFFSET] alanının [OFFSET_ARRAY]'deki bir sonraki zincir bileşen adresi ile güncellenmesi olduğunu görebiliriz.
  • 131. 6. AŞAMA PSEUDO CODE int girdi[6] struct { int ALAN_1 int ALAN_2 int next_item } item; item LISTE_BASI = 0X40304C for(VAR_I=0;VAR_I<6;VAR_I++) if (girdi[VAR_I] <= 0 || girdi[VAR_I] > 6) HATALI_DENEME() for(VAR_J=VAR_I+1; VAR_J<6;VAR_J++) if(girdi[VAR_I]==girdi[VAR_J]) HATALI_DENEME() for(VAR_I=0;VAR_I<6;VAR_I++) item CURSOR = LISTE_BASI for(VAR_J=1; VAR_J<girdi[VAR_I];VAR_J++) CURSOR=CURSOR->NEXT_ITEM OFFSET_ARRAY[VAR_I]=CURSOR LISTE_BASI=OFFSET_ARRAY[0] CURSOR=OFFSET_ARRAY[0] for(VAR_I=1;VAR_I<6;VAR_I++) CURSOR->NEXT_ITEM=OFFSET_ARRAY[VAR_I]
  • 132. 6. AŞAMA Bu güncellemeden hemen sonra da [CURSOR] işaret ettiği zincir bileşeninin [NEXT_OFFSET] adresi ile güncelleniyor. Bir başka alternatif de [OFFSET_ARRAY]'den bu adresin alınması olabilirdi.
  • 133. 6. AŞAMA PSEUDO CODE int girdi[6] struct { int ALAN_1 int ALAN_2 int next_item } item; item LISTE_BASI = 0X40304C for(VAR_I=0;VAR_I<6;VAR_I++) if (girdi[VAR_I] <= 0 || girdi[VAR_I] > 6) HATALI_DENEME() for(VAR_J=VAR_I+1; VAR_J<6;VAR_J++) if(girdi[VAR_I]==girdi[VAR_J]) HATALI_DENEME() for(VAR_I=0;VAR_I<6;VAR_I++) item CURSOR = LISTE_BASI for(VAR_J=1; VAR_J<girdi[VAR_I];VAR_J++) CURSOR=CURSOR->NEXT_ITEM OFFSET_ARRAY[VAR_I]=CURSOR LISTE_BASI=OFFSET_ARRAY[0] CURSOR=OFFSET_ARRAY[0] for(VAR_I=1;VAR_I<6;VAR_I++) CURSOR->NEXT_ITEM=OFFSET_ARRAY[VAR_I] CURSOR=CURSOR->NEXT_ITEM
  • 134. 6. AŞAMA Bu döngüyü de incelememiz de bittiğine göre bu grubu da kapatabiliriz. Şimdi sıra [DONGU_1]'de.
  • 135. 6. AŞAMA [DONGU_1] grubunu açmak için bu grubu seçelim ve sağ klikle açalım.
  • 136. 6. AŞAMA [DONGU_1]'in başlarında sayaç'ın sıfırlanmasından önce [CURSOR]'ün işaret ettiği son zincir bileşeni üzerinde bir işlem daha yapıldığını görüyoruz.
  • 137. 6. AŞAMA [8] offset'ini işaretlediğimizde benzer bir işlemin aşağı bölümde de yapıldığını daha rahat görebiliyoruz.
  • 138. 6. AŞAMA Bu kod bölümlerini daha anlamlı hale getirmek için veri yapısına referans verme imkanımızı tekrar kullanıyoruz.
  • 139. 6. AŞAMA [CURSOR]'ün işaret ettiği son zincir bileşeninin [NEXT_OFFSET] alanına [0], yani pek çok uygulama dilindeki ifadesiyle [NULL] atandığını görüyoruz. Bu zincir listelerdeki son bileşen için uygulanan tipik bir yöntem.
  • 140. 6. AŞAMA PSEUDO CODE int girdi[6] struct { int ALAN_1 int ALAN_2 int next_item } item; item LISTE_BASI = 0X40304C for(VAR_I=0;VAR_I<6;VAR_I++) if (girdi[VAR_I] <= 0 || girdi[VAR_I] > 6) HATALI_DENEME() for(VAR_J=VAR_I+1; VAR_J<6;VAR_J++) if(girdi[VAR_I]==girdi[VAR_J]) HATALI_DENEME() for(VAR_I=0;VAR_I<6;VAR_I++) item CURSOR = LISTE_BASI for(VAR_J=1; VAR_J<girdi[VAR_I];VAR_J++) CURSOR=CURSOR->NEXT_ITEM OFFSET_ARRAY[VAR_I]=CURSOR LISTE_BASI=OFFSET_ARRAY[0] CURSOR=OFFSET_ARRAY[0] for(VAR_I=1;VAR_I<6;VAR_I++) CURSOR->NEXT_ITEM=OFFSET_ARRAY[VAR_I] CURSOR=CURSOR->NEXT_ITEM CURSOR->NEXT_ITEM=NULL
  • 141. 6. AŞAMA Sonraki adımda [LISTE_BASI] değişkeni [CURSOR]'a atanıyor. Yeni liste başımız bizim gireceğimiz [6] rakamdan ilkinin işaret ettiği bileşendi ve biz yeni sıralamayı [OFFSET_ARRAY] aracılığı ile oluşturmuştuk.
  • 142. 6. AŞAMA PSEUDO CODE int girdi[6] struct { int ALAN_1 int ALAN_2 int next_item } item; item LISTE_BASI = 0X40304C for(VAR_I=0;VAR_I<6;VAR_I++) if (girdi[VAR_I] <= 0 || girdi[VAR_I] > 6) HATALI_DENEME() for(VAR_J=VAR_I+1; VAR_J<6;VAR_J++) if(girdi[VAR_I]==girdi[VAR_J]) HATALI_DENEME() for(VAR_I=0;VAR_I<6;VAR_I++) item CURSOR = LISTE_BASI for(VAR_J=1; VAR_J<girdi[VAR_I];VAR_J++) CURSOR=CURSOR->NEXT_ITEM OFFSET_ARRAY[VAR_I]=CURSOR LISTE_BASI=OFFSET_ARRAY[0] CURSOR=OFFSET_ARRAY[0] for(VAR_I=1;VAR_I<6;VAR_I++) CURSOR->NEXT_ITEM=OFFSET_ARRAY[VAR_I] CURSOR=CURSOR->NEXT_ITEM CURSOR->NEXT_ITEM=NULL CURSOR=LISTE_BASI
  • 143. 6. AŞAMA Bu döngüde sayaç olarak [VAR_I] değişkeni kullanılıyor. [0] ile initialize edilen [VAR_I] değeri [4]'ü geçtiğinde içinde bulunduğumuz [ASAMA_6] fonksiyonunun sonuna geliyoruz. Döngünün en alt bloğunda da [VAR_I] değişkeninin [1] artırıldığını görebiliyoruz.
  • 144. 6. AŞAMA PSEUDO CODE int girdi[6] struct { int ALAN_1 int ALAN_2 int next_item } item; item LISTE_BASI = 0X40304C for(VAR_I=0;VAR_I<6;VAR_I++) if (girdi[VAR_I] <= 0 || girdi[VAR_I] > 6) HATALI_DENEME() for(VAR_J=VAR_I+1; VAR_J<6;VAR_J++) if(girdi[VAR_I]==girdi[VAR_J]) HATALI_DENEME() for(VAR_I=0;VAR_I<6;VAR_I++) item CURSOR = LISTE_BASI for(VAR_J=1; VAR_J<girdi[VAR_I];VAR_J++) CURSOR=CURSOR->NEXT_ITEM OFFSET_ARRAY[VAR_I]=CURSOR LISTE_BASI=OFFSET_ARRAY[0] CURSOR=OFFSET_ARRAY[0] for(VAR_I=1;VAR_I<6;VAR_I++) CURSOR->NEXT_ITEM=OFFSET_ARRAY[VAR_I] CURSOR=CURSOR->NEXT_ITEM CURSOR->NEXT_ITEM=NULL CURSOR=LISTE_BASI for(VAR_I=0;VAR_I<5;VAR_I++)
  • 145. 6. AŞAMA Döngümüzün yaptığı asıl test bu bölümde gerçekleşiyor, çünkü eğer hata yapmış isek uygulama hata alarak sonlanıyor. Bu bölümde yapılan şey [CURSOR]'ın o anda işaret ettiği bileşenin ilk DWORD'ü ile bu bileşenin [NEXT_OFFSET] alanı ile referans verdiği sonraki bileşenin ilk DWORD'ünün karşılaştırılması işlemi. Eğer MEVCUT bileşenin [1.] DWORD'ünün değeri listedeki SONRAKİ bileşenin [1.] DWORD'ünden DAHA BÜYÜK ise [HATALI_DENEME] fonksiyonu çağrılıyor.
  • 146. 6. AŞAMA PSEUDO CODE int girdi[6] struct { int ALAN_1 int ALAN_2 int next_item } item; item LISTE_BASI = 0X40304C for(VAR_I=0;VAR_I<6;VAR_I++) if (girdi[VAR_I] <= 0 || girdi[VAR_I] > 6) HATALI_DENEME() for(VAR_J=VAR_I+1; VAR_J<6;VAR_J++) if(girdi[VAR_I]==girdi[VAR_J]) HATALI_DENEME() for(VAR_I=0;VAR_I<6;VAR_I++) item CURSOR = LISTE_BASI for(VAR_J=1; VAR_J<girdi[VAR_I];VAR_J++) CURSOR=CURSOR->NEXT_ITEM OFFSET_ARRAY[VAR_I]=CURSOR LISTE_BASI=OFFSET_ARRAY[0] CURSOR=OFFSET_ARRAY[0] for(VAR_I=1;VAR_I<6;VAR_I++) CURSOR->NEXT_ITEM=OFFSET_ARRAY[VAR_I] CURSOR=CURSOR->NEXT_ITEM CURSOR->NEXT_ITEM=NULL CURSOR=LISTE_BASI for(VAR_I=0;VAR_I<5;VAR_I++) if(CURSOR > CURSOR->NEXT_ITEM) HATALI_DENEME()
  • 147. 6. AŞAMA Döngünün son bloğunda zincir bileşenlerinin [+8] offset'ine bir başka referans daha var.
  • 148. 6. AŞAMA Bu bölümü de anlamlandırmak için veri yapısı referansımızı kullanalım.
  • 149. 6. AŞAMA PSEUDO CODE int girdi[6] struct { int ALAN_1 int ALAN_2 int next_item } item; item LISTE_BASI = 0X40304C for(VAR_I=0;VAR_I<6;VAR_I++) if (girdi[VAR_I] <= 0 || girdi[VAR_I] > 6) HATALI_DENEME() for(VAR_J=VAR_I+1; VAR_J<6;VAR_J++) if(girdi[VAR_I]==girdi[VAR_J]) HATALI_DENEME() for(VAR_I=0;VAR_I<6;VAR_I++) item CURSOR = LISTE_BASI for(VAR_J=1; VAR_J<girdi[VAR_I];VAR_J++) CURSOR=CURSOR->NEXT_ITEM OFFSET_ARRAY[VAR_I]=CURSOR LISTE_BASI=OFFSET_ARRAY[0] CURSOR=OFFSET_ARRAY[0] for(VAR_I=1;VAR_I<6;VAR_I++) CURSOR->NEXT_ITEM=OFFSET_ARRAY[VAR_I] CURSOR=CURSOR->NEXT_ITEM CURSOR->NEXT_ITEM=NULL CURSOR=LISTE_BASI for(VAR_I=0;VAR_I<5;VAR_I++) if(CURSOR > CURSOR->NEXT_ITEM) HATALI_DENEME() CURSOR=CURSOR->NEXT_ITEM
  • 150. 6. AŞAMA Zincir listemizi daha önceden analiz etmiş ve offset'leri çözerek tüm bileşenleri belirlemiştik. [DONGU_1]'de bileşenlerin ilk alanlarındaki değerler birbirleriyle karşılaştırılıyordu.
  • 151. 6. AŞAMA İlk alanın değerlerini HEX gösterimden ONDALIK gösterime geçirmek için [ALAN_1]'in üzerine tıkladıktan sonra sağ klikleyerek [Field type][Number][Decimal] seçeneklerini seçebiliriz. Daha sonra bu veri yapısını tespit ettiğimiz zincir liste ile ilişkilendireceğiz.
  • 152. 6. AŞAMA [ALAN_1]'in veri tipini [DECIMAL] olarak belirledikten sonra [VERI_YAPISI]'nın görüntüsü yukarıdaki gibi olacaktır.
  • 153. 6. AŞAMA [VERI_YAPISI]'nın son DWORD'ünün de bir başka [VERI_YAPISI]'na işaret eden bir OFFSET olduğunu biliyoruz. Bu bilgiyi de veri yapısı üzerine aktarmak için son alanı tıklayıp sağ klikledikten sonra [Field type][Offset][Offset (struct) ...] seçeneğini seçiyoruz.
  • 154. 6. AŞAMA Karşımıza çıkan menüde tanımlanmış olan tek veri yapısı olan [VERI_YAPISI] çıkacaktır. Bu veri yapısını seçerek offset'in işaret ettiği [Structure] tipini de IDA'ya öğretmiş olacağız.
  • 155. 6. AŞAMA [VERI_YAPISI]'nın son görüntüsü yukarıdaki gibi olacaktır.
  • 156. ALT+Q 6. AŞAMA Veri alanlarını tanımladığımız veri yapıları ile ilişkilendirmek için ilgili veri alanının üzerinde tıkladıktan sonra [ALT+Q] tuşlarına basabiliriz. Daha sonra karşımıza çıkan [Structure] listesinden ilgili olanı seçerek bu kalıbı veri alanı ile ilişkilendirmiş oluruz.
  • 157. 6. AŞAMA Zincir listemizi oluşturan bileşenleri ilgili [Structure] ile ilişkilendirdikten sonra veri tipleri de [Structure] üzerinde tanımladığımız gibi görüntülenmiş olacaktır. İlk alanları [DECIMAL] olarak tanımladığımız için şimdi ONDALIK olarak görülebileceklerdir.
  • 158. 6. AŞAMA Veri yapılarını ilk alanlarındaki değerlerine göre sıralarsak [ASAMA_6] için girmemiz gereken dizi [2 4 1 6 3 5] olacaktır.
  • 160. NE ÖĞRENDİK Karmaşık kod bloklarını analiz etme hakkında • Kod bloklarını renklendirme • Kod bloklarını gruplama • İç içe döngüleri en içten başlayarak inceleme yöntemi Veri yapılarını anlamlandırma ve kod okunabilirliğini artırma hakkında • IDA'da structure tanımı yapma • Tespit edebildiğimiz veri yapısı bileşenlerinin formatlarını structure içinde tanımlama • Structure bilgisini kod içine verilen referanslara aktarma • Structure bilgisini veri blokları üzerine aktarma