SlideShare a Scribd company logo
1 of 242
ZARARLI YAZILIM
ANALİZİ EĞİTİMİ
BÖLÜM 2
İSTANBUL
blog.btrisk.com @btrisk /btrisktv /btrisk
BTRİSK HAKKINDA
TANIŞMA
Pentest & BT Denetimi
ISO27001 Danışmanlık
Hizmetleri
BG Operasyon
Hizmetleri
ANALİZ
STATİK ANALİZ [Import Address Table]
Bir uygulamanın Import
ettiği fonksiyonlar o
uygulamanın
fonksiyonalitesine ilişkin
bize fikir verebilirler
ANALİZ
STATİK ANALİZ [Import Address Table]
Import edilen fonksiyon adlarını
kopyalayarak bir şüpheli fonksiyon
listesiyle karşılaştırabilmek için IDA
Pro'nun Imports penceresinde sağ
klikleyerek Copy seçeneğini seçelim
ANALİZ
STATİK ANALİZ [Import Address Table]
Kopyaladığımız listeyi
Notepad++'a yapıştırarak
arama yapabiliriz
ANALİZ
STATİK ANALİZ [Import Address Table]
Şüpheli API listemizle Import
adres tablosunu karşılaştırmak
için MS Excel'in VLOOKUP
fonksiyonunu da kullanabiliriz
ANALİZ
STATİK ANALİZ [Import Address Table]
Bunun için fonksiyon adlarını
ayrı kolona bölmek amacıyla
Text to Columns özelliğini
kullanalım ve delimiter olarak
"Space"i seçelim
ŞÜPHELİ WINDOWS API'LERİ
Windows API Fonksiyonları
• Windows API fonksiyonlarına baktığımızda bazılarının “A” ile,
bazılarının ise “W” ile bittiğini görürüz. Bu fonksiyonlardan A ile
bitenler “string” veri tipinde aldıkları parametreleri ANSI (ASCII
değil) string’leri olarak, W ile bitenler ise Unicode (Wide
Character) string’leri olarak kabul ederler.
• Bazı fonksiyonların sonu da “Ex” olarak bitmektedir (bu
fonksiyonlarda da W ve A ekleri görülebilir, yani “Ex” ekinden
sonra W veya A gelebilir). Bu fonksiyonlar da benzer isimli
önceki fonksiyonların yerini almış ancak eski fonksiyonların
sahip oldukları fonksiyonaliteyi de destekleyen “Extended”
fonksiyonlardır.
ŞÜPHELİ WINDOWS API'LERİ
Şüphe Doğurabilecek API’ler
• Zararlı yazılımların genellikle ihtiyaç duydukları ve bu yüzden
şüpheli olabilecek API’lere sonraki sayfalardaki örnekleri
verebiliriz. Elbette API’lerin birden fazla kullanım amacı olabilir
ve liste daha da genişletilebilir, ancak kullanım amaçları ile ilgili
fikir vermesi için bu şekilde bir gruplama yapılmıştır.
• Elbette zararlının özel amaçları doğrultusunda ihtiyaç duyacağı
başka API’ler de olabilir. Tüm Windows API’lerine erişmek için
MSDN’den faydalanabilirsiniz.
ŞÜPHELİ WINDOWS API'LERİ
Ağ Erişimiyle İlgili API’ler
İhtiyaç: Zararlı yazılımlar veriyi dışarı sızdırmak, bir sunucuyla tünel
bağlantısı kurmak, ikinci aşama payload’larını indirmek, v.b.
ihtiyaçlarla ağ erişim API’lerini kullanabilirler.
WinSock API
• WSAStartup
• getaddrinfo
• socket
• connect
• send
• recv
• WSAGetLastError
ŞÜPHELİ WINDOWS API'LERİ
Ağ Erişimiyle İlgili API’ler (devamı)
WinINet API
• InternetOpen
• InternetConnect
• InternetOpenURL
• InternetReadFile
• InternetWriteFile
• HTTPOpenRequest
• HTTPQueryInfo
• HTTPSendRequest
ŞÜPHELİ WINDOWS API'LERİ
Ağ Erişimiyle İlgili API’ler (devamı)
Kernel32 API
• ConnectNamedPipe
• PeekNamedPipe
Urlmon API
• URLDownloadToFile
Diğer
• FtpPutFile
• GetAdaptersInfo (Anti-Virtual Machine kontrolü için de
kullanılabilir)
İhtiyaç: Zararlı yazılımlar dosya drop etmek (resource
section’larındaki bir dosyayı diske yazmak), kendilerini başka bir
isimle saklamak, veri sızdırmak için dosyalara erişmek, indirdiği ve
ihtiyacı kalmayan dosyaları silmek v.b. amaçlarla dosya erişim
API’lerini kullanabilirler.
• CreateFile
• ReadFile
• WriteFile
• FindResource
• LoadResource
ŞÜPHELİ WINDOWS API'LERİ
Dosya Erişimiyle ve Dropper
Fonksiyonalitesiyle İlgili API’ler
ŞÜPHELİ WINDOWS API'LERİ
Registry Erişimiyle İlgili API’ler
İhtiyaç: Zararlı yazılımlar kalıcılıklarını sağlamak için Autorun
registry değerlerine yazmak, parola v.b. hassas verilere erişmek,
varsa hedeflediği bir uygulamanın kurulu olup olmadığını anlamak,
v.b. amaçlarla registry API’lerini kullanabilirler.
• RegOpenKeyEx
• RegSetValueEx
• RegGetValue
ŞÜPHELİ WINDOWS API'LERİ
Keylogger Fonksiyonalitesiyle İlgili API’ler
İhtiyaç: Zararlı yazılımın keylogger fonksiyonalitesi var ise bu
bilgileri elde etmelerine imkan veren API’lere erişebilirler.
• GetAsyncKeyState
• GetForegroundWindow
• GetKeyState
• SetWindowsHookEx
• CallNextHookEx
• AttachThreadInput
• MapVirtualKey
ŞÜPHELİ WINDOWS API'LERİ
Proses İşlemleri ile İlgili API’ler
İhtiyaç: Zararlı yazılımlar diğer proses’lerin adres space’lerinde kod çalıştırmak
için, anti-virüs v.d. proses’leri öldürmek için, dinamik analizi engellemek için v.d.
amaçlarla bu API’lere ihtiyaç duyabilirler.
• CreateToolhelp32Snapshot (process listesini belirlemek için kullanılır)
• Process32First/Process32Next
• Module32First/Module32Next
• OpenProcess
• VirtualAllocEx
• VirtualProtectEx (bellek erişim haklarının değiştirilmesi için kullanılır)
• WriteProcessMemory
• AdjustTokenPrivileges
• CreateRemoteThread
• EnumProcesses
• EnumProcessModules
• IsWoW64Process
• QueueUserAPC
ŞÜPHELİ WINDOWS API'LERİ
DLL Yükleme ve Fonksiyon Adresi Bulma
API’leri
İhtiyaç: Zararlı yazılımlar detaylı statik analizde tespit edilebilecek
olmalarına rağmen Import Address Table’larında kullandıkları
kütüphane ve API’lerin görünmemesi amacıyla dinamik olarak
kütüphane yükleme ve bunların Export ettikleri fonksiyonların
adreslerini bulmak için gerekli API’leri kullanabilirler.
• LoadLibrary
• GetProcAddress
• LdrLoadDll
ŞÜPHELİ WINDOWS API'LERİ
Debug Edilip Edilmediğini Tespit Etmek
için Kullanılan API’ler
İhtiyaç: Zararlı yazılımlar debug edildiklerini tespit etmek ve normal
davranışlarını sergilememek için çok çeşitli teknikler kullanırlar.
Bunlardan bir kısmı Windows’un sağladığı debugger tespit
imkanlarıdır.
• IsDebuggerPresent
• CheckRemoteDebuggerPresent
• FindWindow (örneğin Ollydbg uygulamasının aktif olup olmadığını anlamak
için)
• GetTickCount
• NtQueryInformationProcess
• OutputDebugString
Servislerle ve Scheduled Task’larla
Kalıcılığı Sağlamak için Kullanılabilecek
API’ler
ŞÜPHELİ WINDOWS API'LERİ
İhtiyaç: Zararlının kalıcılık için servis veya scheduled task
kullanması durumunda kullandığı API’ler
• CreateService
• ControlService
• OpenSCManager
• NetScheduleJobAdd
ŞÜPHELİ WINDOWS API'LERİ
Diğer Dosyalara Bulaşmak için Kullanılan
API’ler
İhtiyaç: Zararlının diğer dosyalara da kod eklemek için kullandığı
API’ler
• FindFirstFile
• FindNextFile
• NtQueryDirectoryFile
• CreateFileMapping (Disk üzerindeki PE dosyalarına kod inject etmek için
bunları belleğe yükleyerek ona erişmek için kullanılan API)
• MapViewOfFile
ŞÜPHELİ WINDOWS API'LERİ
COM Nesnelerini Kullanmak için
Kullanılan API’ler
İhtiyaç: Zararlı yazılım Windows işletim sistemi ile gelen COM
bileşenlerini kullanabilir. Bu durumda hangi COM nesnesinin ve
dolayısıyla hangi fonksiyonalitenin kullanıldığını anlamak için onun
class identifier’ını (CLSID) incelememiz gerekir.
• OleInitialize (COM nesneleri kullanılmadan önce çağrılır)
• CoInitializeEx (COM nesneleri kullanılmadan önce çağrılır)
ŞÜPHELİ WINDOWS API'LERİ
Veri Sızdırmak, Parola Çalmak için
Kullanılabilecek API’ler
İhtiyaç: Zararlı yazılım sistem üzerinde tanımlı kullanıcıların parola hash’lerini
SAM veritabanına erişerek, sisteme erişmiş kullanıcıların parolalarını bellekteki
verilere erişerek ele geçirmek isteyebilir, sisteme map’lenmiş paylaşımlar içinde
de veri arayabilir.
• LsaEnumerateLogonSessions (Credential çalan zararlılar tarafından sisteme logon
olmuş kullanıcıları tespit etmek için kullanılabilir)
• SamIConnect (SAM veritabanına erişmek ve parola hash’lerini dump etmek için
kullanılır)
• SamIGetPrivateData (SAM veritabanına erişmek ve parola hash’lerini dump etmek
için kullanılır)
• SamQueryInformationUse (SAM veritabanına erişmek ve parola hash’lerini dump
etmek için kullanılır)
ŞÜPHELİ WINDOWS API'LERİ
Veri Sızdırmak, Parola Çalmak için
Kullanılabilecek API’ler (devamı)
• NetShareEnum (SAM veritabanına erişmek ve parola hash’lerini dump etmek
için kullanılır)
• ReadProcessMemory
• Toolhelp32ReadProcessMemory
ŞÜPHELİ WINDOWS API'LERİ
Diğer API’ler
• CreateMutex (Aynı anda zararlı prosesin tek bir instance’ının çalışması için
kullanılabilen bir API’dir. Mutex bir kilit gibi davranır ve bu kilide sahip olmayan proses
diğerlerini bekler)
• CreateProcess
• ShellExecute
• WinExec
• System (zararlı proses drop ettiği başka bir uygulamayı veya sistem üzerindeki başka
bir uygulamayı başlatmak için bu API’leri kullanabilir)
• CryptAcquireContext (Kriptolama fonksiyonları zararlı tarafından çeşitli amaçlarla
kullanılabilir, crypt ile başlayan pek çok fonksiyon incelenebilir)
• EnableExecuteProtectionSupport (DEP kontrolünü ortadan kaldırmak için
kullanılan fonksiyondur)
ŞÜPHELİ WINDOWS API'LERİ
Diğer API’ler (devamı)
• NtSetInformationProcess (Proses haklarını yükseltmek veya DEP kontrolünü
ortadan kaldırmak için kullanılabilir)
• GetSystemDefaultLangId (Ransomware v.b. mesaj veren zararlılar tarafından
sistemin dil ayarlarını tespit etmek için kullanılır)
• GetTempPath (zararlı yazılım bir takım geçici dosyaları saklamak için bu alanı
kullanabilir)
• SetFileTime (zararlı yazılım aktivitelerini gizleyebilmek için kullanabilir)
• StartServiceCtrlDispatcher (Servis olarak başlayan bir proses’in ilk 30 sn.
içinde bu fonksiyonu çağırması gerekir. Bu API’nin gözlenmesi zararlının servis olarak
çalıştırılması gerektiği anlamına gelebilir.)
• IsNTAdmin
• IsUserAnAdmin (zararlı kullanıcının admin haklarına sahip olup olmadığını kontrol
etmek için bu API’leri kullanabilir)
ŞÜPHELİ WINDOWS API'LERİ
ÖNEMLİ
• Derleyiciler bazı fonksiyonları yazılımcı bu fonksiyonu doğrudan
kullanmamış olsa da uygulamaya ekleyebilmektedir. Örneğin
[IsDebuggerPresent] fonksiyonunu aslında yazılımcı böyle
bir kontrol yapmasa da bazı uygulamalarda mevcut olarak
gözlemleyebilirsiniz.
• Şüpheli bir API’nin tam olarak nasıl kullanıldığını anlayabilmek
için disassembly üzerinde aldığı parametreleri incelemek ve
binary debugger ile dinamik analiz ile izlemek gerekecektir.
Bunu yapabilmek için de X86 mimarisi, X86 Assembly, calling
conventions (fonksiyon çağırma yöntemleri) bilgilerine sahip
olmak gereklidir.
ANALİZ
STATİK ANALİZ [Import Address Table]
Oluşturduğumuz şüpheli API
adları listesini kopyalayarak A ve
W uzantılı adlarını da türetelim
ANALİZ
STATİK ANALİZ [Import Address Table]
MS Excel'in VLOOKUP fonksiyonunu kullanarak
zararlı yazılımın IAT'ından elde ettiğimiz liste ile
şüpheli API listemizi karşılaştıralım
ANALİZ
STATİK ANALİZ [Import Address Table]
Henüz X86 mimarisi ile ilgili teorik bir çalışma
yapmadık, ancak küçük bir tanışıklık için ilgimizi
çeken bir API için [ör: RegSetValueExW]
zararlımızı inceleyelim.
Dinamik analiz sırasında zararlının Autorun
registry key'lerine değer yazdığını görmüştük,
zararlı yazılımın bu davranışını biraz daha
yakından inceleyelim.
ANALİZ
STATİK ANALİZ [Import Address Table]
RegSetValueExW fonksiyonunun çağrıldığı yerleri
bulmak ve bu bölümleri inceleyebilmek için IDA
Pro'nun Imports penceresinden faydalanabiliriz.
Bunun için bu fonksiyonun üzerinde çift tıklayalım.
ANALİZ
STATİK ANALİZ [Import Address Table]
Buradan RegSetValueExW fonksiyonunun IAT'daki
yerine geliriz. Fonksiyon adına tıkladıktan sonra "X"
harfine basarsak IDA bize bu adresin kullanıldığı kod
bölümlerinin Cross (bu yüzden X) Reference
bilgilerini verir.
ANALİZ
STATİK ANALİZ [Import Address Table]
XREF listesinde seçtiğimiz bir satıra çift
tıkladığımızda ilgili kod için disassembly ekranına
geçeriz. Mouse'umuzu fonksiyon adı üzerine
getirdiğimizde fonksiyonun parametre yapısını
görebiliriz.
X86 hakkında daha detaylı çalışacağız, ancak fonksiyonların parametrelerini Stack'e yazılan
değerlerden aldığını söyleyelim. Disassembly üzerinden bu değerlerin neler olduğunu
anlamak güç, çünkü parametrelerin bir kısmı daha yukarıda yapılan hesaplamalar ve diğer
işlemler sonucunda belirlenerek stack'e yazılıyor (push ediliyor).
ANALİZ
STATİK ANALİZ [Import Address Table]
Windows API'leri ve bu
fonksiyonların alabilecekleri
parametre değerleri ile ilgil
detaylı bilgiyi MSDN v.d.
kaynaklardan bulabilirsiniz.
ANALİZ
DİNAMİK ANALİZ [Import Address Table]
RegSetValueExW fonksiyonuna
verilen parametreleri statik
olarak analiz etmek zor olduğu
için Immunity Debugger ile
dinamik analiz yapalım ve bu
fonksiyon çağrılmadan önce
Stack'te bulunacak parametreleri
inceleyelim.
ANALİZ
DİNAMİK ANALİZ [Import Address Table]
Uygulamanın ASLR destekli olması nedeniyle unpack edilmiş olan uygulamada da hata
alıyoruz [uzun incelemeler sonrasında ulaştığım bu sonuç hakkında bana güvenin!]
Ancak bu hata yüzünden olmasa da yine de ASLR desteğini kaldırmamız gerekecekti,
yoksa IDA'da öğrendiğimiz adresi bellekte aynı adreste bulamayacaktık
ANALİZ
DİNAMİK ANALİZ [Import Address Table]
Unpack edilmiş zararlı yazılımımıza PEView ile göz attığımızda Image Optional Header içinde
bulunan DLL Characteristics alanında ASLR desteği bulunduğunu görebiliriz [Dynamic Base
özelliği]
OS Loader bu özelliği dikkate alarak uygulamayı ASLR ile belleğe yükler. Bundan kaçınmak için
uygulamanın ASLR'ı desteklemediğini belirtmemiz lazım. Bu alanın dosya içindeki offset'inin
0x176 byte'ta olduğunu PEView'ın pFile adres formatı ile görebiliriz.
ANALİZ
DİNAMİK ANALİZ [Import Address Table]
Uygulama dosyasını yamalamak için
010 Editör'le dosyayı açmadan önce
Immunity Debugger ve PEView'ı
kapatalım, aksi takdirde dosya Read
Only olarak açılacaktır
DLL Characteristics
alanının mevcut değeri
40 81 (PEView'da little
endian formatta
gösterilmiştir)
ANALİZ
DİNAMİK ANALİZ [Import Address Table]
40 değerini 00 ile değiştirerek
dosyamızı Save edelim
ANALİZ
DİNAMİK ANALİZ [Import Address Table]
Yamamızdan sonra unpacked
zararlı yazılım uygulamamızın
ASLR (Dynamic Base) desteğinin
kalktığını görebiliriz
ANALİZ
DİNAMİK ANALİZ [Import Address Table]
Uygulamamızı bu defa sorunsuz başlatabiliriz.
RegSetValueExW fonksiyonunun tam
çağrıldığı noktada breakpoint koymak için [b
40298f] komutunu kullanabiliriz.
ANALİZ
DİNAMİK ANALİZ [Import Address Table]
Imminuty Debugger'ın [b] düğmesiyle erişilen
Breakpoints ekranına göz attığımızda
breakpoint'imizin başarı ile konup
konmadığını gözleyebiliriz.
ANALİZ
DİNAMİK ANALİZ [Import Address Table]
Normalde çalışan
uygulamamız Immunity
Debugger ile çalıştırdığımızda
[Division by zero] hatası aldı
Shift+F9 ile kontrolü
uygulamaya iade ettiğimizde
de herhangi bir ilerleme
gözlemleyemedik
EAX register'ının hata
anındaki değeri [0]
ANALİZ
DİNAMİK ANALİZ [Import Address Table]
DIV instruction'ının açıklamasına
baktığımızda EDX:EAX
register'larındaki değerin EAX
register'ı ile bölme işlemini
gerçekleştirdiğini görebiliriz
DİNAMİK ANALİZ [Import Address Table]
ANALİZ
Hata aldığımız noktanın öncesini
Immunity Debugger'ın
Disassembly penceresinden de
inceleyebiliriz, ama incelememizi
IDA'da yapmak istersek [Jump to
address] aracılığıyla ilgili adrese
gidebiliriz
DİNAMİK ANALİZ [Import Address Table]
ANALİZ
Hatanın alındığı
[0x401D8A] adresine
gidelim
DİNAMİK ANALİZ [Import Address Table]
ANALİZ
[div eax] instruction'ından hemen önceki satıra bakarsak [xor eax, eax]
instruction'ı ile EAX register'ının değerinin 0'landığını görebiliriz. Bu bilgi
0'a bölme hatasının kasten oluşturulduğu şüphesini doğuruyor. Bu
satırdan hemen önce de yeni bir Exception Handler belirlenmiş.
Uygulama çalışırken bu handler hatayı ele alıyor olmalı, ancak Immunity
kontrolü uygulamaya devrettiğinde aynı durum gerçekleşmiyor.
HATA ALDIRMA ÖRNEĞİ
ANTI-DEBUGGING YÖNTEMLERİ
ImmunityDebugger'ın Options /
Debugging options / Exceptions
penceresinde istediğimiz hata
kodları için kontrolün otomatik
olarak uygulamaya devredilmesi
ayarını yapabiliriz
HATA ALDIRMA ÖRNEĞİ
ANTI-DEBUGGING YÖNTEMLERİ
Tam hata kodunu öğrenmek için bu
ekrandaki "Add last exception"
düğmesini kullanabiliriz, veya bir
aralık tanımlayarak 0 – FFFFFFFF
aralığındaki tüm exception'ları göz
ardı ettirebiliriz.
HATA ALDIRMA ÖRNEĞİ
ANTI-DEBUGGING YÖNTEMLERİ
ImmunityDebugger'ın bu özelliğini
kullanarak Exception'ı uygulamaya
aktarma denememiz başarılı olamadı.
ANTI-DEBUGGING YÖNTEMLERİ
AMAÇ
• Anti-Debugging yöntemleri ile zararlı yazılım geliştiren taraf
dinamik analizi zorlaştırmak ister.
• Ancak hemen her durumda bu kontrolün tespiti ve uygulama
yamalanarak (debug kontrolü yapan instruction'ların NOP
instruction'ları ile etkisiz hale getirilmesiyle) atlatılması
mümkündür.
• Bu kontrollerin uygulandığı noktalar tespit edildikten sonra
dinamik analiz sırasında bu noktalarda registry değerleri veya
belleğe manuel müdahale etme veya bu debugger'ların
sağladığı bazı atlatma imkanlarının kullanılması da anti-
debugging engellerini atlatmak için kullanılabilir.
ANTI-DEBUGGING YÖNTEMLERİ
ÖRNEKLER
API Metodları
• [IsDebuggerPresent()] – PEB bloğundaki BeingDebugged byte'ının
değerini kontrol eder
• [CheckRemoteDebuggerPresent(GetCurrentProcess(),
&isDebuggerPresent)] – Mevcut proses'imizin handle'ını kullarak debug
edilip edilmediğini test eder
• [NtQueryInformationProcess(...)] – Debug Flag'lerini verilen
değişken referansına döndürür
• [OutputDebugString(L"test")/GetLastError()] – proses debug
edilmiyorsa GetLastError ile dönen hata kodu değişecektir
• [DebugActiveProcess(pid)] – Eğer proses zaten debug ediliyorsa hata
döndürecektir
ANTI-DEBUGGING YÖNTEMLERİ
ÖRNEKLER
Manuel Kontrol Yöntemleri
• Debugger uygulama varlığını arama:
[FindWindow(L"OLLYDBG",0)] fonksiyonu ile aktif uygulamaların
adlarını inceleme, registry 'yi veya dosya sistemini debugger
varlığını keşfetmek için tarama
• Manuel olarak PEB bloğu içindeki BeingDebugged değerini
arama
ANTI-DEBUGGING YÖNTEMLERİ
ÖRNEKLER
Breakpoint Arama ve Kod Bütünlüğünü Test Etme
• Software breakpoint ve yama tespiti: Belli bir kod bölümünün
byte'larını basit bir biçimde bir byte'lık bir değişkene ekleyerek
hesaplanan değer önceden hesaplanmış bir değerle
karşılaştırılabilir. Veya her bir byte bir değerle XOR'lanarak 0xCC
olup olmadığı test edilebilir (ör: [0xCC XOR 0x55 == 0x99])
• Hardware breakpoint tespiti: [GetThreadContext(hnd, &ctx)]
fonksiyonuyla DR0, DR1, DR2, DR3 register değerlerini içeren
context veri yapısı incelenebilir.
ANTI-DEBUGGING YÖNTEMLERİ
ÖRNEKLER
Zaman Aralıklarını Ölçme
• [GetTickCount() ], [timeGetTime()] gibi fonksiyonlarla art arda
ölçülen zaman değerleri arasındaki fark test edilerek proses'in
debug edilip edilmediği anlaşılmaya çalışılır.
ANTI-DEBUGGING YÖNTEMLERİ
UYGULAMANIN YAMALANMASI
Debug etmemizi engelleyen bu durumu aşmak için hata alan satırı NOP
instruction'ı ile yamalayacağız.
Bunun için önce Options / IDA Options / Disassembly menüsünde "Number of
opcode bytes" değerini 8 yaparak Opcode'ların görünür olmasını sağlayalım.
ANTI-DEBUGGING YÖNTEMLERİ
UYGULAMANIN YAMALANMASI
"div eax" instruction'ının opcode'larının "F7 F0" olduğunu
görebiliyoruz. Bu instruction'ın VA adresi de 0x401D8A
ANTI-DEBUGGING YÖNTEMLERİ
UYGULAMANIN YAMALANMASI
Hex View'a geçtiğimizde
seçtiğimiz instruction'ı
Hex veriler arasında da
görebiliriz
ANTI-DEBUGGING YÖNTEMLERİ
UYGULAMANIN YAMALANMASI
IDA Pro'nun güncel versiyonunda disk
üzerindeki dosyanın yamalanması imkanı var.
Ne yazık ki ücretsiz versiyon olan IDA Pro 5'te
"Patch program" seçeneği bulunmuyor.
ANTI-DEBUGGING YÖNTEMLERİ
UYGULAMANIN YAMALANMASI
Uygulamayı IDA'da yamalayamadığımız için VA ve
dosya offset dönüşümünü PEView ile yapmaya
çalışacağız. Bunun için önce VA adresi olarak
0x401D8A adresinin bulunduğu yeri bulalım.
Yamalanacak olan [F7 F0] byte'ları işaretlenen satırın
11. ve 12. byte'ları.
ANTI-DEBUGGING YÖNTEMLERİ
UYGULAMANIN YAMALANMASI
PEView'ın adres formatını File Offset'e getirdiğimizde
yamalayacağımız adresin 0x118A'da bulunduğunu
görebiliriz.
ANTI-DEBUGGING YÖNTEMLERİ
UYGULAMANIN YAMALANMASI
Yamayı 010 Editör'le veya
farklı bir Hex editörle
uygulayabiliriz.
ANTI-DEBUGGING YÖNTEMLERİ
UYGULAMANIN YAMALANMASI
Yamalanacak [F7 F0]
byte'larını [90 90] yani
NOP NOP instruction'ları
ile yamalayalım.
ANTI-DEBUGGING YÖNTEMLERİ
UYGULAMANIN YAMALANMASI
Değişikliğimizi dosyaya
yansıtmak için Save
edelim.
ANTI-DEBUGGING YÖNTEMLERİ
UYGULAMANIN YAMALANMASI
Yamalanmış uygulamayı
tekrar IDA Pro'da açarak
yamayı gerçekleştirdiğimiz
adrese gidelim.
ANTI-DEBUGGING YÖNTEMLERİ
UYGULAMANIN YAMALANMASI
Daha önce "div eax" instruction'ının bulunduğu yerde
"nop nop" instruction'larının bulunduğunu görebiliriz.
ANALİZ
DİNAMİK ANALİZ [Import Address Table]
ANALİZ
DİNAMİK ANALİZ [Import Address Table]
Uygulama sonlandı ancak
registry değerinin atandığı
instruction çalışmadı. Böyle bir
durum zararlının daha önce bu
sistem üzerinde çalışmış olması
nedeniyle tekrar sisteme
bulaşmamak istemesinden
kaynaklanmış olabilir. Bu
nedenle infection öncesi
SnapShot'a dönerek
uygulamayı tekrar denemekte
fayda var.
ANALİZ
DİNAMİK ANALİZ [Import Address Table]
Kurban sistemi kurulumlar
sonrası aldığımız snapshot'a
döndürdüğümüzde üzerinde
çalıştığımız ve yamaladığımız
zararlı kopyalarını da
kaybedeceğiz. Bunun için
snapshot'a dönmeden önce
yamayı uyguladığımız
fatura_pdf-decompress.exe
dosyasını Host bilgisayarımıza
kopyalayalım.
ANALİZ
DİNAMİK ANALİZ [Import Address Table]
Kurban sistemimizi "Kurulum
Sonrası" snapshot'umuza
döndürelim.
ANALİZ
DİNAMİK ANALİZ [Import Address Table]
Kurban sistemimiz kurulumlar
sonrasında henüz zararlı
yazılımı çalıştırmadan önceki
haline dönecektir.
ANALİZ
DİNAMİK ANALİZ [Import Address Table]
Host bilgisayarımıza aldığımız Anti-Debug
amaçlı kod bölümünü yamaladığımız
"fatura_pdf-decompress.exe" dosyasını
Host bilgisayardan kopyalayalım.
ANALİZ
DİNAMİK ANALİZ [Import Address Table]
"fatura_pdf-decompress.exe"
dosyamızı kurban bilgisayara
kopyalayalım.
ANALİZ
DİNAMİK ANALİZ [Import Address Table]
"fatura_pdf-decompress.exe"
dosyasını Immunity Debugger
ile başlatalım. Başlatır
başlatmaz da 0x40298F
adresine breakpoint koyalım.
ANALİZ
DİNAMİK ANALİZ [Import Address Table]
Uygulamayı devam ettirdiğimizde PDF
dosyasının görüntülendiğini
görüyoruz. Bu davranış son
denememizden farklı, muhtemelen
uygulama daha önceden bulaşmadığı
bir sistem üzerinde bu şekilde
davranıyor. Uygulama tanımladığımız
breakpoint adresinde durdu.
ANALİZ
DİNAMİK ANALİZ [Import Address Table]
RegSetValueExW fonksiyonu
çağrılmadan hemen önce Stack'te bu
fonksiyona verilen parametreleri
görebiliriz. Bunlardan "ValueName"
parametresi Registry değerini ifade
ediyor
ANALİZ
DİNAMİK ANALİZ [Import Address Table]
MSDN'den edindiğimiz bilgiye göre RegSetValueEx fonksiyonuna verilen 5.
parametre Registry değerine atanacak veriye işaret eden bir pointer
ANALİZ
DİNAMİK ANALİZ [Import Address Table]
ImmunityDebugger'ın Buffer olarak adlandırdığı
bu alanda belirtilen adrese giderek atanan veriyi
gözlemlemek için sol alt bölümdeki Memory
Dump alanında sağ klikleyerek "Go to" /
"Expression" seçeneğini seçelim.
ANALİZ
DİNAMİK ANALİZ [Import Address Table]
Buffer'ın stack'te tutulduğu
adresi çıkan kutuya yazalım
ANALİZ
DİNAMİK ANALİZ [Import Address Table]
Bu adreste bulunan Unicode
string'i biraz daha rahat
gözlemleyebilmek için dump
alanında sağ klikleyerek
"Hex / UNICODE (16 bytes)"
seçeneğini işaretleyelim.
ANALİZ
DİNAMİK ANALİZ [Import Address Table]
Bu alanda bir exe dosya adı
görüyoruz.
SORU: Burada gözlemlediğimiz dosya adını daha
önce nerede gözlemlemiştik?
ANALİZ
DİNAMİK ANALİZ [Import Address Table]
hKey handle'ının hangi registry key'ine
ait olduğunu anlamak için daha
yukarıda çağrılan RegOpenKeyExW
fonksiyonunun çağrıldığı yere
breakpoint koymamız lazım.
Tabi bunun için sanal makinemizi yine
kurulumlar sonrası snapshot'ımıza
döndürmeyi unutmamalıyız.
EGZERSİZ
DİNAMİK ANALİZ [Import Address Table]
• Import Address Table'da ilginç bulduğunuz fonksiyonlar için
Immunity Debugger ile benzer analizleri yapınız.
• Fonksiyonun çağrıldığı adrese breakpoint koyunuz ve stack'te
fonksiyon için hazırlanmış olan parametreleri inceleyiniz.
Parametreler hakkında detaylı bilgi için MSDN'e başvurunuz.
• Tespitlerinizi bu noktaya kadar yapmış olduğumuz strings
analizleri ve capturebat ile yaptığımız dinamik analiz sonuçları
ile birlikte değerlendiriniz.
• Daha ileri statik ve dinamik analiz yapabilmek için gerekli X86
temel bilgileri üzerinde sonraki bölümde durulacaktır.
X86 MİMARİSİNE GİRİŞ
İNCELEYECEĞİMİZ UYGULAMA
PE dosya formatını da inceleme için
kullandığımız bu basit C
uygulamasından derlenmiş kodu
Immunity Debugger üzerinde
incelerken temel X86 bilgilerine
değineceğiz.
X86 MİMARİSİNE GİRİŞ
ANA KONULAR VE KAVRAMLAR
Daha Önce Değindiklerimiz
• Derleme ve linkleme
• OS Loader'ın uygulamayı belleğe yüklemesi
• Executable imajı, DLL modülleri, Stack ve Heap
alanlarının bellekteki konumları [ASLR konusuyla
bağlantıları]
• Virtual Address kavramı
X86 MİMARİSİNE GİRİŞ
ANA KONULAR VE KAVRAMLAR (DEVAMI)
Bu Bölümde Değineceklerimiz
• Register'lar ve kullanım amaçları
• X86 instruction set'i
• Stack alanının kullanımı [fonksiyon çağırma, fonksiyon
içindeki ve fonksiyondan çıkış işlemleri sırasındaki
olaylar]
• Calling conventions [fonksiyon çağırma sırasında
parametrelerin fonksiyona aktarım yöntemleri,
fonksiyon dönüşünde stack'i temizleme görevleri]
X86 MİMARİSİNE GİRİŞ
X86 hakkındaki teorik bilgiler
üzerinde daha sonrak konuşmak
üzere, öncelikle uygulamamızın
Makine Kodu seviyesindeki
işleyişini inceleyelim.
Öncelikle main() fonksiyonu
içindeki ilk instruction'ın adresini
öğrenmek için Visual Studio'nun
"Go To Assembly" özelliğini
kullanacağız.
X86 MİMARİSİNE GİRİŞ
Visual Studio'da Disassembly view'ına
geçtiğimizde derleyicinin üreteceği
Assembly kodlarının yanı sıra bunların
adreslerini de görüyoruz.
Bu bilgiye şu nedenle ihtiyacımız var:
Derleyiciler kod üretmeye doğrudan
main() fonksiyonundan başlamazlar ve
Address of Entry Point'te main()
fonksiyonuna işaret etmez. Ancak bizim
X86 mimarisini anlama amaçlı
incelememizi main() fonksiyonundan
başlatmamız lazım.
İlk instruction olan "push ebp"
instruction'ının adresi 0x401060
X86 MİMARİSİNE GİRİŞ
Uygulama belleğe yüklendiğinde de
bu adreste olacağından emin
olabilmek için ASLR'ı bu ayarlarla
etkisiz hale getirdik.
X86 MİMARİSİNE GİRİŞ
Address of Entry Point'e koyduğumuz
breakpoint [0x401060] sonrası bir kaç
defa F9 tuşuna basılarak main()
fonksiyonunun başına geliyoruz.
X86 MİMARİSİNE GİRİŞ
main() fonksiyonunun ilk instruction'ları
"function prologue" adı da verilen önceki
fonksiyon frame pointer'ın saklanması ve
mevcut stack pointer'ın yeni fonksiyonun
frame pointer'ı olarak belirlenmesidir.
X86 MİMARİSİNE GİRİŞ
Stack ve Registry Değişim Özeti
0x0018FF88 [EBP]
STACK
DEĞİŞEN
REGISTER'LAR
ESP 0x0018FF40
ESP
Yüksek Adres
Düşük Adres
Buradaki stack gösterimimiz ile Immunity
Debugger'ın stack penceresindeki büyüme
yönleri farklı, bu nedenle biraz kafanız
karışabilir !
X86 MİMARİSİNE GİRİŞ
"function prologue"un ikinci adımında
mevcut stack pointer [ESP] main()
fonksiyonunun stack base pointer'ı [EBP]
olarak atanıyor.
X86 MİMARİSİNE GİRİŞ
Stack ve Registry Değişim Özeti
0x0018FF88 [EBP]
STACK EBP 0x0018FF40
ESP
DEĞİŞEN
REGISTER'LAR
Yüksek Adres
Düşük Adres
X86 MİMARİSİNE GİRİŞ
main() fonksiyonunun lokal değişkenleri için
stack'te 12 byte'lık [0x0C] yer ayrılıyor.
X86 MİMARİSİNE GİRİŞ
Stack ve Registry Değişim Özeti
0x0018FF88 [EBP]
XXXXXXXX
XXXXXXXX
XXXXXXXX
STACK ESP 0x0018FF34
ESP
DEĞİŞEN
REGISTER'LAR
Yüksek Adres
Düşük Adres
X86 MİMARİSİNE GİRİŞ
[EBP-8] adresindeki lokal değişkene 10
[0x0A] değeri atanıyor.
X86 MİMARİSİNE GİRİŞ
Stack ve Registry Değişim Özeti
0x0018FF88 [EBP]
XXXXXXXX
0x0000000A
XXXXXXXX
STACK ESP
DEĞİŞEN
REGISTER'LAR
Yüksek Adres
Düşük Adres
X86 MİMARİSİNE GİRİŞ
[EBP-4] adresindeki lokal değişkene 20
[0x14] değeri atanıyor.
X86 MİMARİSİNE GİRİŞ
Stack ve Registry Değişim Özeti
0x0018FF88 [EBP]
0x00000014
0x0000000A
XXXXXXXX
STACK ESP
DEĞİŞEN
REGISTER'LAR
Yüksek Adres
Düşük Adres
X86 MİMARİSİNE GİRİŞ
[EBP-4] adresindeki lokal değişken EAX
register'ına atanıyor.
X86 MİMARİSİNE GİRİŞ
Stack ve Registry Değişim Özeti
0x0018FF88 [EBP]
0x00000014
0x0000000A
XXXXXXXX
STACK ESP
EAX 0x00000014
DEĞİŞEN
REGISTER'LAR
Yüksek Adres
Düşük Adres
X86 MİMARİSİNE GİRİŞ
EAX register'ının değeri Stack'e push
ediliyor. Bu değer "add" fonksiyonu için bir
parametre olarak kullanılacak.
X86 MİMARİSİNE GİRİŞ
Stack ve Registry Değişim Özeti
0x0018FF88 [EBP]
0x00000014
0x0000000A
XXXXXXXX
0x00000014 [Arg 2]STACK
ESP
ESP 0x0018FF30
DEĞİŞEN
REGISTER'LAR
Yüksek Adres
Düşük Adres
X86 MİMARİSİNE GİRİŞ
[EBP-8] adresindeki lokal değişken ECX
register'ına atanıyor.
X86 MİMARİSİNE GİRİŞ
Stack ve Registry Değişim Özeti
0x0018FF88 [EBP]
0x00000014
0x0000000A
XXXXXXXX
0x00000014 [Arg 2]STACK
ESP
ECX 0x0000000A
DEĞİŞEN
REGISTER'LAR
Yüksek Adres
Düşük Adres
X86 MİMARİSİNE GİRİŞ
ECX register'ının değeri Stack'e push
ediliyor. Bu değer "add" fonksiyonu için bir
diğer parametre olarak kullanılacak.
X86 MİMARİSİNE GİRİŞ
Stack ve Registry Değişim Özeti
0x0018FF88 [EBP]
0x00000014
0x0000000A
XXXXXXXX
0x00000014 [Arg 2]
0x0000000A [Arg 1]
STACK
ESP
ESP 0x0018FF2C
DEĞİŞEN
REGISTER'LAR
Yüksek Adres
Düşük Adres
X86 MİMARİSİNE GİRİŞ
Immunity Debugger debug sembollerine
sahip olduğu bir executable için bize
fonksiyon adı ve bu fonksiyona verilen
parametrelerle ilgili bilgi sağlıyor.
X86 MİMARİSİNE GİRİŞ
"call add" instruction'ı çalıştığında EIP
değeri add fonksiyonuna işaret edecek
şekilde değişiyor, ancak main() fonksiyonu
içindeki bir sonraki instruction'ın adresi
stack'e yazılıyor.
X86 MİMARİSİNE GİRİŞ
Stack ve Registry Değişim Özeti
0x0018FF88 [EBP]
0x00000014
0x0000000A
XXXXXXXX
0x00000014 [Arg 2]
0x0000000A [Arg 1]
0x00401081 [EIP]
STACK
ESP
ESP 0x0018FF28
DEĞİŞEN
REGISTER'LAR
Yüksek Adres
Düşük Adres
X86 MİMARİSİNE GİRİŞ
add() fonksiyonunun prologue'unın ilk
instruction'ı çalıştığında main()
fonksiyonunun stack base pointer'ı stack'e
yazılıyor.
X86 MİMARİSİNE GİRİŞ
Stack ve Registry Değişim Özeti
0x0018FF88 [EBP]
0x00000014
0x0000000A
XXXXXXXX
0x00000014 [Arg 2]
0x0000000A [Arg 1]
0x00401081 [EIP]
0x0018FF40 [EBP]
STACK
ESP
ESP 0x0018FF24
DEĞİŞEN
REGISTER'LAR
Yüksek Adres
Düşük Adres
X86 MİMARİSİNE GİRİŞ
add() fonksiyonunun prologue'unın ikinci
instruction'ı çalıştığında ESP register'ının
değeri add() fonksiyonunun stack base
pointer'ına [EBP] yazılıyor.
X86 MİMARİSİNE GİRİŞ
Stack ve Registry Değişim Özeti
0x0018FF88 [EBP]
0x00000014
0x0000000A
XXXXXXXX
0x00000014 [Arg 2]
0x0000000A [Arg 1]
0x00401081 [EIP]
0x0018FF40 [EBP]
STACK
ESP
EBP 0x0018FF24
DEĞİŞEN
REGISTER'LAR
Yüksek Adres
Düşük Adres
X86 MİMARİSİNE GİRİŞ
add() fonksiyonu lokal değişkenler için
sadece 4 byte'lık bir alan kullandığından
"push ecx" instruction'ı ile stack'te yeterli
alan ayrılmış oluyor.
X86 MİMARİSİNE GİRİŞ
Stack ve Registry Değişim Özeti
0x0018FF88 [EBP]
0x00000014
0x0000000A
XXXXXXXX
0x00000014 [Arg 2]
0x0000000A [Arg 1]
0x00401081 [EIP]
0x0018FF40 [EBP]
XXXXXXXX
STACK
ESP
ESP 0x0018FF20
DEĞİŞEN
REGISTER'LAR
Yüksek Adres
Düşük Adres
X86 MİMARİSİNE GİRİŞ
add() fonksiyonunun stack'te hazır bulunan
birinci parametresi [EAX] register'ına
atanıyor.
X86 MİMARİSİNE GİRİŞ
Stack ve Registry Değişim Özeti
0x0018FF88 [EBP]
0x00000014
0x0000000A
XXXXXXXX
0x00000014 [Arg 2]
0x0000000A [Arg 1]
0x00401081 [EIP]
0x0018FF40 [EBP]
XXXXXXXX
STACK
ESP
EAX 0x0000000A
DEĞİŞEN
REGISTER'LAR
Yüksek Adres
Düşük Adres
X86 MİMARİSİNE GİRİŞ
add() fonksiyonunun stack'te hazır bulunan
ikinci parametresi [EAX] register'ına [add]
instruction'ı ile ekleniyor.
X86 MİMARİSİNE GİRİŞ
Stack ve Registry Değişim Özeti
0x0018FF88 [EBP]
0x00000014
0x0000000A
XXXXXXXX
0x00000014 [Arg 2]
0x0000000A [Arg 1]
0x00401081 [EIP]
0x0018FF40 [EBP]
XXXXXXXX
STACK
ESP
EAX 0x0000001E
DEĞİŞEN
REGISTER'LAR
Yüksek Adres
Düşük Adres
X86 MİMARİSİNE GİRİŞ
[EAX] register'ının değeri stack'te add()
fonksiyonu için ayrılmış 4 byte'lık lokal
değişken alanına atanıyor. Uygulamamızı
optimizasyon ayarları ile derlemiş olsaydık
muhtemelen bu adımı görmeyecektik. Çünkü
zaten return değeri [EAX] register'ı ile
döndürülecek.
X86 MİMARİSİNE GİRİŞ
Stack ve Registry Değişim Özeti
0x0018FF88 [EBP]
0x00000014
0x0000000A
XXXXXXXX
0x00000014 [Arg 2]
0x0000000A [Arg 1]
0x00401081 [EIP]
0x0018FF40 [EBP]
0x0000001E
STACK
ESP
DEĞİŞEN
REGISTER'LAR
Yüksek Adres
Düşük Adres
X86 MİMARİSİNE GİRİŞ
Bu adımda gereksiz bir biçimde lokal
değişken tekrar [EAX] register'ına atanıyor.
Ancak register değeri zaten aynı olduğu için
değişmiyor.
X86 MİMARİSİNE GİRİŞ
Stack ve Registry Değişim Özeti
0x0018FF88 [EBP]
0x00000014
0x0000000A
XXXXXXXX
0x00000014 [Arg 2]
0x0000000A [Arg 1]
0x00401081 [EIP]
0x0018FF40 [EBP]
0x0000001E
STACK
ESP
DEĞİŞEN
REGISTER'LAR
Yüksek Adres
Düşük Adres
X86 MİMARİSİNE GİRİŞ
add() fonksiyonun epilogue'unun ilk
adımında add() fonksiyonunun stack base
pointer'ı [ESP] register'ına atanıyor. Bu
adımda add() fonksiyonu için stack'ten
almış olduğumuz alan geri veriliyor.
X86 MİMARİSİNE GİRİŞ
Stack ve Registry Değişim Özeti
0x0018FF88 [EBP]
0x00000014
0x0000000A
XXXXXXXX
0x00000014 [Arg 2]
0x0000000A [Arg 1]
0x00401081 [EIP]
0x0018FF40 [EBP]
0x0000001E
STACK ESP 0x0018FF24
ESP
DEĞİŞEN
REGISTER'LAR
Yüksek Adres
Düşük Adres
X86 MİMARİSİNE GİRİŞ
add() fonksiyonun epilogue'unun ikinci
adımında main() fonksiyonunun stack'te
saklanmış olan [EBP] register değeri tekrar
yükleniyor. pop instruction'ı ile birlikte stack
de 4 byte daha azaltılmış oluyor.
X86 MİMARİSİNE GİRİŞ
Stack ve Registry Değişim Özeti
0x0018FF88 [EBP]
0x00000014
0x0000000A
XXXXXXXX
0x00000014 [Arg 2]
0x0000000A [Arg 1]
0x00401081 [EIP]
0x0018FF40 [EBP]
0x0000001E
STACK EBP 0x0018FF40
ESP 0x0018FF28
ESP
DEĞİŞEN
REGISTER'LAR
Yüksek Adres
Düşük Adres
X86 MİMARİSİNE GİRİŞ
"retn" instruction'ı çalıştığında stack'in en
üstünde bulunan saklanmış [EIP] değeri
"pop" edilecek ve uygulama akışı bu
adresten devam edecektir.
X86 MİMARİSİNE GİRİŞ
"retn" instruction'ı çalıştığında sadece
saklanmış EIP değerine atlamıyoruz aynı
zamanda stack'de 4 byte küçültülmüş
oluyor.
X86 MİMARİSİNE GİRİŞ
Stack ve Registry Değişim Özeti
0x0018FF88 [EBP]
0x00000014
0x0000000A
XXXXXXXX
0x00000014 [Arg 2]
0x0000000A [Arg 1]
0x00401081 [EIP]
0x0018FF40 [EBP]
0x0000001E
STACK ESP 0x0018FF2C
ESP
DEĞİŞEN
REGISTER'LAR
Yüksek Adres
Düşük Adres
X86 MİMARİSİNE GİRİŞ
"add esp, 8" instruction'ı ile stack'te add()
fonksiyon parametreleri için kullanmış
olduğumuz 8 byte'lık alanı geri veriyoruz. Bu
işlemde çağıran [caller] stack'i temizliyor.
X86 MİMARİSİNE GİRİŞ
Stack ve Registry Değişim Özeti
0x0018FF88 [EBP]
0x00000014
0x0000000A
XXXXXXXX
0x00000014 [Arg 2]
0x0000000A [Arg 1]
0x00401081 [EIP]
0x0018FF40 [EBP]
0x0000001E
STACK ESP 0x0018FF34
ESP
DEĞİŞEN
REGISTER'LAR
Yüksek Adres
Düşük Adres
X86 MİMARİSİNE GİRİŞ
[EAX] register'ında bulunan toplama işlemi
sonucu main() fonksiyonunun lokal
değişkenine atanıyor.
X86 MİMARİSİNE GİRİŞ
Stack ve Registry Değişim Özeti
0x0018FF88 [EBP]
0x00000014
0x0000000A
0x0000001E
0x00000014 [Arg 2]
0x0000000A [Arg 1]
0x00401081 [EIP]
0x0018FF40 [EBP]
0x0000001E
STACK ESP
DEĞİŞEN
REGISTER'LAR
Yüksek Adres
Düşük Adres
X86 MİMARİSİNE GİRİŞ
Lokal değişkenimizde bulunan toplama
sonucu [EDX] register'ına atanıyor.
X86 MİMARİSİNE GİRİŞ
Stack ve Registry Değişim Özeti
0x0018FF88 [EBP]
0x00000014
0x0000000A
0x0000001E
0x00000014 [Arg 2]
0x0000000A [Arg 1]
0x00401081 [EIP]
0x0018FF40 [EBP]
0x0000001E
STACK EDX 0x0000001E
ESP
DEĞİŞEN
REGISTER'LAR
Yüksek Adres
Düşük Adres
X86 MİMARİSİNE GİRİŞ
Optimizasyon uygulamadığımız için printf()
fonksiyonunun ikinci parametresi olarak
(parametreler yine sağdan sola doğru
stack'e yazılıyor) [EDX] register'ında
bulunan toplam değerini stack'e yazıyoruz
(halbuki bu değer zaten stack'te mevcuttu)
X86 MİMARİSİNE GİRİŞ
Stack ve Registry Değişim Özeti
0x0018FF88 [EBP]
0x00000014
0x0000000A
0x0000001E
0x0000001E [Arg 2]
0x0000000A [Arg 1]
0x00401081 [EIP]
0x0018FF40 [EBP]
0x0000001E
STACK ESP 0x0018FF30
ESP
DEĞİŞEN
REGISTER'LAR
Yüksek Adres
Düşük Adres
Buradaki Arg 2 printf()'in ikinci
parametresi
X86 MİMARİSİNE GİRİŞ
Bu instruction'da printf() fonksiyonu için
format string'in bulunduğu adresi stack'e
yazıyoruz. Stack penceresinde bu değerin
Sonuc = "%d" olduğunu görebiliriz.
X86 MİMARİSİNE GİRİŞ
Stack ve Registry Değişim Özeti
0x0018FF88 [EBP]
0x00000014
0x0000000A
0x0000001E
0x0000001E [Arg 2]
0x00403000 [Arg 1]
0x00401081 [EIP]
0x0018FF40 [EBP]
0x0000001E
STACK ESP 0x0018FF2C
ESP
DEĞİŞEN
REGISTER'LAR
Yüksek Adres
Düşük Adres
X86 MİMARİSİNE GİRİŞ
printf() fonksiyonu çağrılmadan önce
konsol penceresini görünteleyelim ve
henüz birşey yazılmadığını görelim.
X86 MİMARİSİNE GİRİŞ
printf fonksiyonunun içine girmeden "step over" şeklinde bu
fonksiyonu çalıştırıyoruz, çünkü bu API fonksiyonunu
incelemek istemiyoruz. Bu çağrıdan sonra Sonuc = 30
ifadesini görmemizin yanında ilginç olan bir nokta [EAX],
[ECX] ve [EDX] register'larımızın değişmiş olması.
X86 MİMARİSİNE GİRİŞ
Stack ve Registry Değişim Özeti
0x0018FF88 [EBP]
0x00000014
0x0000000A
0x0000001E
0x0000001E [Arg 2]
0x00403000 [Arg 1]
0x00401081 [EIP]
0x0018FF40 [EBP]
0x0000001E
STACK EAX 0x0018FF2C
ECX 0x0018FF2C
EDX 0x0018FF2CESP
DEĞİŞEN
REGISTER'LAR
Yüksek Adres
Düşük Adres
"caller saved" registers kavramına
"calling conventions" bölümünde
değineceğiz.
X86 MİMARİSİNE GİRİŞ
printf() fonksiyonuna verilen parametreler
için tüketilen stack alanı geri veriliyor.
X86 MİMARİSİNE GİRİŞ
Stack ve Registry Değişim Özeti
0x0018FF88 [EBP]
0x00000014
0x0000000A
0x0000001E
0x0000001E [Arg 2]
0x00403000 [Arg 1]
0x00401081 [EIP]
0x0018FF40 [EBP]
0x0000001E
STACK ESP 0x0018FF34
ESP
DEĞİŞEN
REGISTER'LAR
Yüksek Adres
Düşük Adres
X86 MİMARİSİNE GİRİŞ
getchar() API fonksiyonunun
çalışabilmesi için konsol penceresinden
bir girdi vermemiz gerekecek. Bu
yüzden "step over" komutu ile bir
instruction daha atlamaya çalıştıktan
sonra konsolu tekrar ön plana alalım.
X86 MİMARİSİNE GİRİŞ
Konsol penceresinde "Enter" tuşuna
bastıktan sonra getchar() fonksiyonu
tamamlanarak dönüyor. [ECX] ve [EDX]
register'larının değiştiğini gözlemliyoruz.
X86 MİMARİSİNE GİRİŞ
Stack ve Registry Değişim Özeti
0x0018FF88 [EBP]
0x00000014
0x0000000A
0x0000001E
0x0000001E [Arg 2]
0x00403000 [Arg 1]
0x00401081 [EIP]
0x0018FF40 [EBP]
0x0000001E
STACK ECX 0x683D60B0
EDX 0x0000000A
ESP
DEĞİŞEN
REGISTER'LAR
Yüksek Adres
Düşük Adres
X86 MİMARİSİNE GİRİŞ
main() fonksiyonundan çıkmadan önce
[EAX] register'ı return değeri olarak
"0"lanmak amacıyla kendisiyle XOR'lanıyor.
X86 MİMARİSİNE GİRİŞ
Stack ve Registry Değişim Özeti
0x0018FF88 [EBP]
0x00000014
0x0000000A
0x0000001E
0x0000001E [Arg 2]
0x00403000 [Arg 1]
0x00401081 [EIP]
0x0018FF40 [EBP]
0x0000001E
STACK EAX 0x00000000
ESP
DEĞİŞEN
REGISTER'LAR
Yüksek Adres
Düşük Adres
X86 MİMARİSİNE GİRİŞ
main() fonksiyonundan çıkmadan önce
epilogue adımlarından main() fonksiyonu
için alınmış olan stack alanını geri veren
"mov esp, ebp" instruction'ı çalıştırılıyor.
X86 MİMARİSİNE GİRİŞ
Stack ve Registry Değişim Özeti
0x0018FF88 [EBP]
0x00000014
0x0000000A
0x0000001E
0x0000001E [Arg 2]
0x00403000 [Arg 1]
0x00401081 [EIP]
0x0018FF40 [EBP]
0x0000001E
STACK ESP 0x0018FF40
ESP
DEĞİŞEN
REGISTER'LAR
Yüksek Adres
Düşük Adres
X86 MİMARİSİNE GİRİŞ
main() fonksiyonu 2. epilogue adımında
main() fonksiyonunu çağıran bir üst
fonksiyonun [EBP] register'ı restore ediliyor.
X86 MİMARİSİNE GİRİŞ
Stack ve Registry Değişim Özeti
0x0018FF88 [EBP]
0x00000014
0x0000000A
0x0000001E
0x0000001E [Arg 2]
0x00403000 [Arg 1]
0x00401081 [EIP]
0x0018FF40 [EBP]
0x0000001E
STACK EBP 0x0018FF88
ESP 0x0018FF44
ESP
DEĞİŞEN
REGISTER'LAR
Yüksek Adres
Düşük Adres
X86 MİMARİSİNE GİRİŞ
main() fonksiyonunun sonunda "retn"
instruction'ı çalıştığında saklanmış olan
[EIP] adresinden uygulama akışı devam
ediyor.
X86 MİMARİSİNE GİRİŞ
Uygulamanın devam etmesine izin
verdiğimizde "0" exit değeri ile
sonlandığını görüyoruz.
X86 MİMARİSİNE GİRİŞ
İNCELEYEDİĞİMİZ UYGULAMA
Assembly kodlarının üzerinden
geçtikten sonra kaynak kodumuzu
tekrar hatırlamak isteyebilirsiniz.
(Aslında her aşamada bu kaynak koda
göz atmak disassembly'yi anlamak için
size yardımcı olabilir.)
X86 MİMARİSİNE GİRİŞ
REGISTER'LAR VE KULLANIM AMAÇLARI
EIP [Extended Instruction Pointer]
Bir sonra çalışacak olan instruction’ın adresi (sadece makine tarafından değiştirilir)
EBP [Extended Base Pointer] ve ESP [Extended Stack Pointer]
İçinde bulunulan fonksiyonun stack frame’inin taban ve tavan adreslerini
barındıran register’lar
EAX, EBX, ECX, EDX, ESI, EDI
Genel amaçlı register’lar (ancak geleneksel olarak belli amaçlarla kullanılabilirler)
EFLAGS
Çeşitli instruction’lar tarafından etkilenen ve kullanılan bayrakları barındıran 32
bit’lik bir register
X86 MİMARİSİNE GİRİŞ
REGISTER'LAR VE KULLANIM AMAÇLARI
• EAX – Accumulator Register: Genellikle fonsiyonların return değerlerini tutar.
Hesaplamaların sonuçları da genellikle bu register'da tutulur.
• EBX – Base Register: Genellikle belli bir özel amaç için kullanılmaz.
• ECX – Counter Register: Genellikle döngülerde ve string işlemlerinde sayaç
değişkenini (yani meşhur "i" değerini) tutmak için kullanılır.
• EDX – Data Register: Çarpma ve bölme gibi işlemlerde EAX'in yetersiz kalması
nedeniyle işlem sonuçlarının most significant bit'lerini tutmak için kullanılır.
• ESI – Source Index: Genellikle string yazma işlemlerinde kopyalanacak string'den
okunacak adresi tutar (read pointer).
• EDI – Destination Index: Genellikle string yazma işlemlerinde yazılacak adresi tutar
(write pointer).
Önemli: ESP ve EBP register'ları ile birlikte yukarıdaki genel amaçlı register'lar assembly
yazan uygulama geliştirici veya derleyici tarafından istenildiği gibi kullanılabilir. Ancak
yukarıda belirtilen kullanımlar geleneksel kullanımlardır.
X86 MİMARİSİNE GİRİŞ
REGISTER'LAR VE KULLANIM AMAÇLARI
EAX
EBX
ECX
EDX
AX
BX
CX
DX
078151631
32 Bit
Register'lar
16 Bit
Register'lar
8 Bit
Register'lar
Bu bölümleme sadece EAX,
EBX, ECX ve EDX'e özeldir
X86 MİMARİSİNE GİRİŞ
X86 ASSEMBLY GİRİŞ
Assembly Syntax'ları
Intel AT&T
Prefix'ler mov eax, 1 movl $1, %eax
Operand yönü instr dest, source instr source, dest
Bellek operand'ları mov eax, [ebx] movl (%ebx), %eax
Suffix'ler mov al, bl movb %bl, %al
X86 MİMARİSİNE GİRİŞ
X86 ASSEMBLY GİRİŞ
Bellek adresleme yöntemleri
Instruction Anlamı
mov eax, [ebx] EBX register'ının içerdiği adresteki 4 byte'lık değeri EAX
register'ına atama
mov [var], ebx EBX register'ının değerini 32bit'lik bir değişkenin içerdiği adrese
yazma
mov eax, [esi-4] ESI + (-4) adresindeki 4 byte'lık değeri EAX register'ına atama
mov [esi+eax], cl CL register'ının taşıdığı bir byte'lık değeri ESI+EAX adresine
yazma
mov edx, [esi+4*ebx] ESI+4*EBX adresinde bulunan 4 byte'lık değeri EDX register'ına
atama
X86 MİMARİSİNE GİRİŞ
X86 ASSEMBLY GİRİŞ
Size Directive'leri
Register adlarının geçtiği instruction'lardan okunacak ve/veya yazılacak verinin
büyüklüğü anlaşılabilir. Ancak immediate (sabit) verilerin yazıldığı durumlarda
yazılacak verinin kaplayacağı alanın belirtilmesi gerekir.
Instruction Anlamı
mov BYTE PTR [ebx], 2 2 sabit değerini EBX register'ında saklı adresteki 1 byte'lık
alan yaz
mov WORD PTR [ebx], 2 2 sabit değerinin 16 bit'lik gösterimini EBX register'ında saklı
adresten başlayan 2 byte'lık alana yaz
mov DWORD PTR [ebx], 2 2 sabit değerinin 32 bit'lik gösterimini EBX register'ında saklı
adresten başlayan 2 byte'lık alana yaz
X86 MİMARİSİNE GİRİŞ
X86 ASSEMBLY GİRİŞ
Instruction'lar
Şu ana kadar pek çok assembly instruction'ı ile karşılaştık. Açıkçası belli bir
instruction set'i kullanılan veya derleyicilerin ürettiği assembly kodlarının önemli
bir bölümünü kapsar.
Bu bölümde daha önce de karşılaştığımız çok kullanılan Assembly
Instruction'larının üzerinden geçeceğiz.
X86 MİMARİSİNE GİRİŞ
X86 ASSEMBLY GİRİŞ
Instruction'lar [Data Movement Instruction'ları]
mov
Move (Opcodes: 88, 89, 8A, 8B, 8C, 8E, ...)
Bellekten belleğe mov instruction'ı ile veri kopyalamak mümkün değildir.
Syntax
mov <reg>,<reg>
mov <reg>,<mem>
mov <mem>,<reg>
mov <reg>,<imm>
mov <mem>,<imm>
X86 MİMARİSİNE GİRİŞ
X86 ASSEMBLY GİRİŞ
Instruction'lar [Data Movement Instruction'ları]
push
Push stack (Opcodes: FF, 89, 8A, 8B, 8C, 8E, ...)
Syntax
push <reg32>
push <mem>
push <imm32>
X86 MİMARİSİNE GİRİŞ
X86 ASSEMBLY GİRİŞ
Instruction'lar [Data Movement Instruction'ları]
pop
Pop stack
Syntax
pop <reg32>
pop <mem>
X86 MİMARİSİNE GİRİŞ
X86 ASSEMBLY GİRİŞ
Instruction'lar [Data Movement Instruction'ları]
lea
Load effective address
Bu instruction diğerlerine nazaran biraz kafa karıştırıcı olabilir. "lea"
instruction'ın da kaynak değer mutlaka köşeli parantezler arasındadır, ancak
"mov" instruction'ı için bu köşeli parantezler arasında adresi bulunan bellek
alanındaki değer anlamına gelirken "lea" instruction'ı doğrudan adres değerini
kullanır. Bu imkan zaman zaman adres bilgisini kullanmaktan ziyade hesaplama
amacıyla kullanılmaktadır.
Örnek
lea edi, [ebx+4*esi] - EBX+4*ESI hesaplamasının sonucu EDI register'ına atanır
X86 MİMARİSİNE GİRİŞ
X86 ASSEMBLY GİRİŞ
Instruction'lar [Aritmetik ve Mantık Instruction'ları]
add
Integer Addition
Toplama instruction'ında en fazla bir operand bellek alanı olabilir.
Syntax
add <reg>,<reg>
add <reg>,<mem>
add <mem>,<reg>
add <reg>,<imm>
add <mem>,<imm>
X86 MİMARİSİNE GİRİŞ
X86 ASSEMBLY GİRİŞ
Instruction'lar [Aritmetik ve Mantık Instruction'ları]
sub
Integer Subtraction
Toplama instruction'ında olduğu gibi çıkarma instruction'ında da en fazla bir
operand bellek alanı olabilir.
Syntax
sub <reg>,<reg>
sub <reg>,<mem>
sub <mem>,<reg>
sub <reg>,<imm>
sub <mem>,<imm>
X86 MİMARİSİNE GİRİŞ
X86 ASSEMBLY GİRİŞ
Instruction'lar [Aritmetik ve Mantık Instruction'ları]
inc, dec
Increment, Decrement
Artırma instruction'ı registry veya bellek alanını bir artırırken azaltma
instruction'ı da tam tersini gerçekleştirir.
Syntax
inc <reg>
inc <mem>
dec <reg>
dec <mem>
X86 MİMARİSİNE GİRİŞ
X86 ASSEMBLY GİRİŞ
Instruction'lar [Aritmetik ve Mantık Instruction'ları]
imul
Integer Multiplication
2 veya 3 operand'la çalışır. 2 operand'lı kullanımda iki değer çarpılıp sonuç
birinci operand'da saklanır. 3 operand'lı kullanımda 2. ve 3. operand'lar çarpılıp
sonuç birinci operand'da saklanır. Birinci operand (destination) her zaman
registry olmak zorundadır, 3 operand'lı kullanımda 3. operand her zaman bir
immediate (sabit) değer olmak zorundadır.
Syntax
imul <reg32>,<reg32>
imul <reg32>,<mem>
imul <reg32>,<reg32>,<imm>
imul <reg32>,<mem>,<imm>
X86 MİMARİSİNE GİRİŞ
X86 ASSEMBLY GİRİŞ
Instruction'lar [Aritmetik ve Mantık Instruction'ları]
idiv
Integer Division
EDX:EAX registerlarında bulunan 64 bit'lik integer değeri operand değerine
böler. Bölüm EAX'e kalan ise EDX register'ına yazılır.
Syntax
idiv <reg32>
idiv <mem>
X86 MİMARİSİNE GİRİŞ
X86 ASSEMBLY GİRİŞ
Instruction'lar [Aritmetik ve Mantık Instruction'ları]
and, or, xor
Bitwise logical and, or and exclusive or
Operand'lar üzerinde belirtilen işlemleri gerçekleştirdikten sonra sonucu birinci
operand'a yazarlar.
Syntax
and <reg>,<reg>
and <reg>,<mem>
and <mem>,<reg>
and <reg>,<imm>
and <mem>,<imm>
or <reg>,<reg>
or <reg>,<mem>
or <mem>,<reg>
or <reg>,<imm>
or <mem>,<imm>
xor <reg>,<reg>
xor <reg>,<mem>
xor <mem>,<reg>
xor <reg>,<imm>
xor <mem>,<imm>
X86 MİMARİSİNE GİRİŞ
X86 ASSEMBLY GİRİŞ
Instruction'lar [Aritmetik ve Mantık Instruction'ları]
shl, shr
Shift Left, Shift Right
Birinci operand'ı sola veya sağa kaydırırken boşalan bit pozisyonlarına 0 yazılır.
Kaç bit kaydırma yapılacağı 8 bit'lik bir immediate değerde veya CL register'ı ile
verilir.
Syntax
shl <reg>,<imm8>
shl <mem>,<imm8>
shl <reg>,<cl>
shl <mem>,<cl>
shr <reg>,<imm8>
shr <mem>,<imm8>
shr <reg>,<cl>
shr <mem>,<cl>
X86 MİMARİSİNE GİRİŞ
X86 ASSEMBLY GİRİŞ
Instruction'lar [Akış Kontrol Instruction'ları]
jmp
Jump
Uygulama akışını koşulsuz olarak operand ile belirtilen adrese yönlendirir.
Syntax
jmp <label>
X86 MİMARİSİNE GİRİŞ
X86 ASSEMBLY GİRİŞ
Instruction'lar [Akış Kontrol Instruction'ları]
jcondition (Conditional Jump)
EFLAGS register'ında tutulan ve son aritmetik işlemin (bunlar add, sub gibi instruction'lar olabileceği
gibi cmp ve test gibi çıkarma işleminin türevleri olan karşılaştırma instruction'ları da olabilir)
sonuçlarına bağlı olarak uygulama akışını operand'da belirtilen adrese yönlendirir veya akışın bir
sonraki instruction'dan devam etmesine izin verir. ZF - zero flag yapılan işlem veya karşılaştırmanın
sonucu "0" ise "1" değerini alır. SF - sign flag yapılan işlemin sonucu negatif ise "1" değerini alır.
Syntax
je <label> (jump when equal)
jne <label> (jump when not equal)
jz <label> (jump when last result was zero)
jg <label> (jump when greater than)
jge <label> (jump when greater than or equal to)
jl <label> (jump when less than)
jle <label> (jump when less than or equal to)
X86 MİMARİSİNE GİRİŞ
X86 ASSEMBLY GİRİŞ
Instruction'lar [Akış Kontrol Instruction'ları]
cmp
Compare
CMP instruction'ı SUB instruction'ına benzer ancak çıkartma işleminin sonucu
birinci operand'a yazılmaz, sadece işlemin sonucu negatif ise Sign Flag "1" olarak
işaretlenir.
Syntax
cmp <reg>,<reg>
cmp <reg>,<mem>
cmp <mem>,<reg>
cmp <reg>,<imm>
X86 MİMARİSİNE GİRİŞ
X86 ASSEMBLY GİRİŞ
Instruction'lar [Akış Kontrol Instruction'ları]
call, ret (Subroutine call and return)
CALL instruction'ı operand ile verilen adrese uygulama akışını yönlendirirken bir yandan da
kendisinden bir sonra gelen instruction'ın adresini STACK'e yazar, JMP instruction'ından temel farkı
da budur.
RET instruction'ı ise önce STACK'in o anda en üstünde bulunan adres değerini restore eder, yani
uygulama akışını daha önce CALL instruction'ı ile saklanmış olan adrese yönlendirir. Dolayısıyla RET
instruction'ından önce function epilog bölümü gerçekleştirilerek çalıştırılan fonksiyon için STACK'te
ayrılmış olan tüm alanın SUB ESP, 0x??? instruction'ı veya benzeri bir işlem ile geri verilmiş olması
gerekir.
Syntax
call <label>
ret
X86 MİMARİSİNE GİRİŞ
STACK ALANININ KULLANIMI
Stack Alanının Çalışma Mekanizması
• Stack yüksek bir adresten düşük adreslere doğru büyür.
• Stack'e veri yazma (PUSH) ve bu veriyi bir register'a okuyarak silme (POP)
işlemi LIFO (Last In First Out) yöntemiyle stack'e veri yazılması ve silinmesine
yol açar. Bu stack'teki herhangi bir alan okunarak (MOV instruction'ı ile) bir
register'a atanamaz ve tam tersi şekilde bir register veya immediate değeri
stack'e yazılamaz anlamına gelmez, LIFO yöntemi ile sadece stack'in alan
tüketimi ve iadesine ilişkin yöntemi ifade ediyoruz.
• Stack sadece PUSH instruction'ı ile büyümez ve POP instruction'ı ile
küçülmez. [SUB ESP, 0x20] benzeri instruction'larla ESP register değeri
küçültülerek büyüyebilir ve [ADD ESP, 0x20] benzeri instruction'larla ESP
değeri artırılarak küçülebilir.
• Stack ASLR uygulanırsa her yüklemede farklı bir adresten başlatılır.
X86 MİMARİSİNE GİRİŞ
STACK ALANININ KULLANIMI
Stack'te Saklanan Veriler
• Fonksiyon parametreleri: fastcall gibi calling convention'larda
register'lar da fonksiyonlara parametre vermek için kullanılabilmekle
birlikte diğer convention'larda ve bu iş için ayrılmış register'ların
sayısının yetmediği durumlarda parametreler "CALL" instruction'ı ile
fonksiyon çağrılmadan önce stack'e yazılır. Parametreler genellikle
sağdan sola doğru stack'e PUSH edilir ("printf" gibi değişken sayıda
parametre kabul eden fonksiyonlar için format string parametresinde
olduğu gibi diğer parametreleri tanımlayan bir string başta olduğundan
bu yaklaşım oldukça mantıklıdır).
X86 MİMARİSİNE GİRİŞ
STACK ALANININ KULLANIMI
Stack'te Saklanan Veriler [devamı]
• Fonksiyon dönüş adresi: "CALL" instruction'ı çalıştığı anda bu
instruction'dan bir sonraki instruction adresi fonksiyondan "RET"
instruction'ı ile dönüldüğünde EIP register'ına atanmak üzere stack'te
saklanır. Bellek taşma açıklıklarında uygulama akışını manipüle etmek
için hedef alınan başlıca pointer değeri bu değerdir (diğerlerine SEH
pointer değeri, lokal değişken olarak saklanan object veri yapılarının ilk
alanında bulunan Virtual Table pointer değeri örnek verilebilir).
X86 MİMARİSİNE GİRİŞ
STACK ALANININ KULLANIMI
Stack'te Saklanan Veriler [devamı]
• Bir önceki fonksiyon frame pointer'ı: Fonksiyon "prolog"larında daha
önce de gördüğümüz gibi ilk yapılan işlem mevcut frame pointer
değeri (EBP) yeni fonksiyonun frame pointer değeri ile ezileceği için
"PUSH EBP" instruction'ı ile stack'e yazılır. Bu değer fonksiyon
"epilog"unda "POP EBP" instruction'ı ile EBP pointer'ını eski frame
pointer'ı haline getirmek için kullanılır.
• Fonksiyon lokal değişkenleri: Fonksiyon "prolog"undan sonra
genellikle fonksiyon lokal değişkenleri için ESP değeri düşürülerek yer
ayrılır. Daha sonra lokal değişkenler için ayrılan bu alana lokal
değişkenler yazılmaya ve bu alandan gerektiğinde okunmaya başlanır.
X86 MİMARİSİNE GİRİŞ
CALLING CONVENTIONS
CALLING CONVENTION'LARI NEDEN ANLAMALIYIZ?
Calling convention'lar çağıranın mı çağrılanın mı parametreler için
kullanılan alanı geri vereceği ve hangi register'ların korunmasının
kimin sorumluluğunda olduğu ile ilgilidir.
İyi Niyetli Cevap
Bu sorunun iyi niyetli cevabı farklı compiler'ların ürettikleri kodların
bir arada uyum içinde çalışabilmeleri için stack yönetimi ve
register'ların korunması için aynı yaklaşımları izleme ihtiyacıdır.
X86 MİMARİSİNE GİRİŞ
CALLING CONVENTIONS
CALLING CONVENTION'LARI NEDEN ANLAMALIYIZ? [devamı]
Kötü Niyetli Cevap
Inline assembly ile bir kod yazarken veya virüs benzeri bir kodu
mevcut bir uygulamaya yerleştirirken assembly içinden çağrılan
Windows API'lerinin calling convention'ına uygun olarak hareket
edilmezse Stack yapısının düzeni bozulacak, dolayısıyla da
uygulama stack frame'i ile ilgili bu düzensizlikten dolayı hata alarak
sonlanacaktır.
Windows API'leri için "stdcall" convention'ına uygun bir biçimde
stack'teki parametreleri yönetmezsek kodumuzun içinde çalıştığı
proses hata alacaktır.
X86 MİMARİSİNE GİRİŞ
CALLING CONVENTIONS
stdcall
Adının çağrıştırabileceğinin aksine aslında tüm derleyiciler için standart
convention değildir ve Microsoft Win32 API tarafından kullanılır. İlk olarak bu
convention'dan söz etmemizin sebebi de budur.
• Stack'in temizlenmesinden çağırılan (callee) sorumludur. Yani çağıran (caller)
parametreleri stack'e push eder, ancak temizleme işlemini gerçekleştirmez.
• Parametreler stack'e sağdan sola doğru push edilir.
• EAX, ECX ve EDX register'ları fonksiyon içinde kullanılır, dolayısıyla
fonksiyondan geri dönüldüğünde farklılaşmış olma ihtimalleri yüksektir. Yani
bunlar caller saved register'lardır.
• Fonksiyon return değeri EAX register'ına yazılır.
X86 MİMARİSİNE GİRİŞ
CALLING CONVENTIONS
cdecl
C declaration'ın kısaltması olan bu convention çoğu C derleyicileri tarafından
kullanılır.
• Stack'in temizlenmesinden çağıran (caller) sorumludur. Bu yaklaşım
stdcall'unkinden farklıdır.
• Parametreler stack'e sağdan sola doğru push edilir.
• EAX, ECX ve EDX register'ları fonksiyon içinde kullanılır, dolayısıyla
fonksiyondan geri dönüldüğünde farklılaşmış olma ihtimalleri yüksektir. Yani
bunlar caller saved register'lardır.
• Fonksiyon return değeri EAX register'ına yazılır.
X86 MİMARİSİNE GİRİŞ
CALLING CONVENTIONS
Microsoft fastcall
Parametre aktarımında register kullanımına da bir örnek olması amacıyla fastcall
convention'ından da bahsedelim. Bir fonksiyonun bu convention'a göre
derlenmesi için __fastcall anahtar kelimesinin kullanılması gerekir.
• Soldan sağa ilk iki parametre ECX ve EDX register'larında aktarılır.
• Diğer parametreler (bu defa sağdan sola) stack'e yazılır.
• Stack'in temizlenmesinden stdcall'da olduğu gibi çağırılan (callee)
sorumludur.
ANALİZ
STATİK ANALİZ [Disassembly]
• X86 mimarisi ve assembly hakkında daha fazla bilgiye sahip
olduğumuza göre biraz daha detaylı bir statik analiz
gerçekleştirebiliriz.
• İlk dinamik analiz çalışmalarımız sırasında uygulamanın bir HTTP
isteğinde bulunduğunu gözlemlemiştik. Tabi bu gözlemi zararlı
yazılıma herhangi bir internet erişimi vermeden gözlemlediğimiz
için aslında indireceği [paket.bin] dosyasında ne olduğunu
henüz bilmiyoruz.
• Ancak ilginç olan konu uygulamanın Import ettiği API
fonksiyonları içinde herhangi bir network veya HTTP API'sinin
bulunmaması.
ANALİZ
STATİK ANALİZ [Disassembly]
Yeniden hatırlamak gerekirse Import edilen API'lerden ilgimizi
çekenlerin listesini aşağıda bulabilirsiniz (aralarında bir network
API'si yok!):
AdjustTokenPrivileges
CreateFileW
CreateRemoteThread
CreateToolhelp32Snapshot
FindNextFileW
FindResourceW
GetProcAddress
IsDebuggerPresent
LoadResource
OpenProcess
Process32FirstW
Process32NextW
ReadFile
RegOpenKeyExW
RegSetValueExW
ShellExecuteW
VirtualAllocEx
WriteFile
WriteProcessMemory
ANALİZ
STATİK ANALİZ [Disassembly]
Bu API'lerden VirtualAllocEx farklı bir proses'in adres alanında yer
ayırma işlevine sahip. Bu metodun çağrıldığı yeri biraz inceleyelim.
AdjustTokenPrivileges
CreateFileW
CreateRemoteThread
CreateToolhelp32Snapshot
FindNextFileW
FindResourceW
GetProcAddress
IsDebuggerPresent
LoadResource
OpenProcess
Process32FirstW
Process32NextW
ReadFile
RegOpenKeyExW
RegSetValueExW
ShellExecuteW
VirtualAllocEx
WriteFile
WriteProcessMemory
ANALİZ
STATİK ANALİZ [Disassembly]
VirtualAllocEx metodunun kullanıldığı
yerleri tespit etmek için IDA Pro'nun
Imports view'ında bu metodu bularak
çift tıklayalım.
ANALİZ
STATİK ANALİZ [Disassembly]
Import Address Table'da VirtualAllocEx
fonksiyonuyla ilgili alana geçiyoruz.
Burada VirtualAllocEx fonksiyon isminin
üzerinde tıkladıktan sonra "x" tuşuna
tıklayarak bu adrese referans verilen
yerleri gözlemleyelim.
ANALİZ
STATİK ANALİZ [Disassembly]
VirtualAllocEx fonksiyonuna tek bir noktada referans
verildiğini görüyoruz. Bu referans'a çift tıklayarak .text
section'ındaki ilgili instruction'a geçelim.
ANALİZ
STATİK ANALİZ [Disassembly]
Bu alana ulaştığımızda biraz aşağıda WriteProcessMemory fonksiyonunun
da çağrıldığını görebiliyoruz.
VirtualAllocEx fonksiyonunun return değerinin "mov ebx, eax" instruction'ı
ile "ebx" register'ına aktarıldığını görüyoruz.
ANALİZ
STATİK ANALİZ [Disassembly]
WriteProcessMemory fonksiyonunun çağrıldığı instruction'ın hemen
üzerinde toplam 5 adet push instruction'ı var. Bu instruction'lar büyük
ihtimallle bu fonksiyonun aldığı parametreler olmalı.
ANALİZ
STATİK ANALİZ [Disassembly]
MSDN'den WriteProcessMemory API'si ile ilgili bilgilere göz attığımızda
fonksiyonun aldığı 5 parametreyi görebiliriz. Parametrelerden 3.sü diğer process'in
address space'ine yazılacak içeriğin barındırıldığı alana işaret eden bir pointer. Bir
zararlı yazılımı analiz ederken bizi merak ettirebilecek bir konu bu, o yüzden bu
parametre'nin nereden geldiğini biraz inceleyelim.
ANALİZ
STATİK ANALİZ [Disassembly]
Disassembly ekranında WriteProcessMemory fonksiyonuna verilen 3.
parametrenin dword_42FCC8 pointer'ı olarak belirtildiğini görüyoruz. Şimdi bu
parametreye tıkladıktan sonra bu asrese referans veren noktaları inceleyelim.
ANALİZ
STATİK ANALİZ [Disassembly]
"x" tuşuna bastığımızda bu adrese 2
noktada referans verildiğini görüyoruz.
2. sırada bulunan referans şu anda
gözlemlediğimiz alan, dolayısıyla
diğerini incelememizde fayda var. 1.
linke çift tıklayarak bu alanı inceleyelim.
ANALİZ
STATİK ANALİZ [Disassembly]
Bu alana geldiğimizde "eax" register
değerinin bu pointer'a atandığını
görüyoruz. "eax" register'ı da hemen 2
instruction yukarıdaki "call
sub_402A70" instruction'ı ile
belirlenmiş olmalı.
ANALİZ
STATİK ANALİZ [Disassembly]
Tekrar hatırlayalım halen diğer process'in address alanına yazılacak verinin
nereden geldiğini inceliyoruz. Görünen o ki sub_402A70 adlı fonksiyon bu veriye
işaret eden bir pointer döndürüyor. Şimdi çift tıklayarak bu fonksiyona göz
atalım.
ANALİZ
STATİK ANALİZ [Disassembly]
Şimdi bu fonksiyonun içindeyiz.
ANALİZ
STATİK ANALİZ [Disassembly]
1
2
3
Fonksiyonda biraz aşağıya indiğimizde deneyimli bir tersine mühendislik
uzmanı tarafından normalde bir derleyici tarafından üretildiğine pek şahit
olunmayacak olan bazı instruction'ları görüyoruz. Bu durum zararlı yazılımı
geliştirmiş olan kişinin uygulamanın bu bölümünü bir inline assembly kodu
ile geliştirmiş olma ihtimalini aklımıza getirmelidir. İlginç instruction'lardan
birkaçını işaretledik. Şimdi sırasıyla bu instruction'lara anlam vermeye
çalışalım.
ANALİZ
STATİK ANALİZ [Disassembly] 1
Birinci instruction "pusha", 32 bit'lik bir uygulama için bizim ikinci satırı esas
almamız lazım. Instruction'ın yaptığı işlem tüm genel amaçlı register'ları yukarıda
görüldüğü sırada stack'e yazmak. Bir shellcode programcısı bu işlemi kodu
gömdüğü alanda bu register'ları kullandıktan sonra "popa" instruction'ı ile kazasız
belasız tekrar orijinal hallerine döndürmek amacıyla kullanabilir.
ANALİZ
STATİK ANALİZ [Disassembly] 2
İkinci ilginç instruction ise "fs:0x30" adresindeki bir veriye işaret ediyor. "fs"
register'ı Thread Environment Block [TEB] veri alanına işaret etmek için kullanılır.
Bu veri yapısının 0x30 offset'inde ise Process Environment Block yer alır.
Derlenmiş bir kodda böyle bir instruction'a rastlamak olası değildir.
ANALİZ
THREAD ENVIRONMENT BLOCK (TEB)
Adım-1: PEB’in adresinin bulunması
0:000> !teb
TEB at 7efdd000
ExceptionList: 0026f814
StackBase: 00270000
StackLimit: 0026e000
SubSystemTib: 00000000
FiberData: 00001e00
ArbitraryUserPointer: 00000000
Self: 7efdd000
EnvironmentPointer: 00000000
ClientId: 00001920 . 00001928
RpcHandle: 00000000
Tls Storage: 7efdd02c
PEB Address: 7efde000
LastErrorValue: 0
LastStatusValue: 0
Count Owned Locks: 0
HardErrorMode: 0
fs:[0]
fs:[30]
0x30
kernel32.dll'in adresinin bulunması
2
WinDbg binary debugger'ı ile bazı Windows veri yapılarını kolayca inceleyebiliriz.
Yukarıda böyle bir örnek verilmektedir.
ANALİZ
STATİK ANALİZ [Disassembly] 3
Yukarıdaki instruction'lar başlangıçta biraz kafa karıştırıcı gelebilir, ancak iyi bir
tersine mühendislik uzmanı bu tür instruction'lara hakim olabilmelidir. fs:30h
alanında bulunan PEB referansı "esi" instruction'ına atıldıktan sonra, PEB'in 0xC
offset'indeki değer tekrar "esi"a atanmakta, bu adresin de 0x1C offset'indeki
değer de tekrar "esi"a atanmaktadır. Son adımda "esi" register'ının neyin adresini
barındıracağını inceleyelim.
ANALİZ
PROCESS ENVIRONMENT BLOCK (PEB)
Adım-2: _PEB_LDR_DATA veri yapısının bulunması
0:000> dt nt!_peb 7efde000
ntdll!_PEB
+0x000 InheritedAddressSpace : 0 ''
+0x001 ReadImageFileExecOptions : 0 ''
+0x002 BeingDebugged : 0x1 ''
+0x003 BitField : 0x8 ''
+0x003 ImageUsesLargePages : 0y0
+0x003 IsProtectedProcess : 0y0
+0x003 IsLegacyProcess : 0y0
+0x003 IsImageDynamicallyRelocated : 0y1
+0x003 SkipPatchingUser32Forwarders : 0y0
+0x003 SpareBits : 0y000
+0x004 Mutant : 0xffffffff Void
+0x008 ImageBaseAddress : 0x01380000 Void
+0x00c Ldr : 0x77240200 _PEB_LDR_DATA
+0x010 ProcessParameters : 0x002f2178 _
....
fs:[30]
0x0c
kernel32.dll'in adresinin bulunması
3
0xC offset'inde process'in address alanına yüklenmiş olan DLL'ler ile ilgili yükleme veri yapısına bir
referans bulmaktayız. Shellcode geliştirme deneyimi olan bir kişi size bu adımların içinde "LoadLibrary"
fonksiyonunu barındıran Kernel32.dll kütüphanesinin process'in adres alanındaki tabanını bulmak için
gerekli ilk adımlardan birisi olduğunu söyleyecektir. LoadLibrary fonksiyonu uygulama içinde dinamik
olarak farklı DLL'lerin yüklenebilmesi için kullanılır.
ANALİZ kernel32.dll'in adresinin bulunması
_PEB_LDR_DATA
Adım-3: Modül zincir listelerinin bulunması
0:000> dt _PEB_LDR_DATA 0x77240200
ntdll!_PEB_LDR_DATA
+0x000 Length : 0x30
+0x004 Initialized : 0x1 ''
+0x008 SsHandle : (null)
+0x00c InLoadOrderModuleList : _LIST_ENTRY [ 0x2f4cf8 -
0x2f5990 ]
+0x014 InMemoryOrderModuleList : _LIST_ENTRY [ 0x2f4d00
- 0x2f5998 ]
+0x01c InInitializationOrderModuleList : _LIST_ENTRY [
0x2f4d98 - 0x2f59a0 ]
+0x024 EntryInProgress : (null)
+0x028 ShutdownInProgress : 0 ''
+0x02c ShutdownThreadId : (null)
0x1c
3
Bu adresin 0x1C offset'inde ise yüklenme sırasına göre modül (yani DLL) bilgileri
veri yapılarının başlangıç adresi tutulur.
ANALİZ kernel32.dll'in adresinin bulunması
MODÜL ZİNCİR LİSTESİ
Adım-4: Başlatılma sırasına göre modül zincir listesinin izlenmesi
0:000> dt _LIST_ENTRY 0x7724021c
ntdll!_LIST_ENTRY
[ 0x2f4d98 - 0x2f59a0 ]
+0x000 Flink : 0x002f4d98 _LIST_ENTRY [ 0x2f5230 - 0x7724021c ]
+0x004 Blink : 0x002f59a0 _LIST_ENTRY [ 0x7724021c - 0x2f5118 ]
0:000> dt _LIST_ENTRY 0x002f4d98
ntdll!_LIST_ENTRY
[ 0x2f5230 - 0x7724021c ]
+0x000 Flink : 0x002f5230 _LIST_ENTRY [ 0x2f5118 - 0x2f4d98 ]
+0x004 Blink : 0x7724021c _LIST_ENTRY [ 0x2f4d98 - 0x2f59a0 ]
0:000> dt _LIST_ENTRY 0x002f5230
ntdll!_LIST_ENTRY
[ 0x2f5118 - 0x2f4d98 ]
+0x000 Flink : 0x002f5118 _LIST_ENTRY [ 0x2f59a0 - 0x2f5230 ]
+0x004 Blink : 0x002f4d98 _LIST_ENTRY [ 0x2f5230 - 0x7724021c
]
1
2
3
Bu veri yapısı bir zincir listedir
[linked list] ve zincirin her bir
bileşeni bir sonra gelene işaret
eden adresi ilk 4 byte'ında
barındırır.
ANALİZ kernel32.dll'in adresinin bulunması
MODÜL ADI
Adım-5: Modül adının bulunması
0:000> dd 0x002f4d98 + 20
002f4db8 77185bc4 00004004 0000ffff 002f59cc
002f4dc8 772448e0 521ea8e7 00000000 00000000
0:000> db 77185bc4
77185bc4 6e 00 74 00 64 00 6c 00-6c 00 2e 00 64 00 6c 00 n.t.d.l.l...d.l.
77185bd4 6c 00 00 00 14 00 16 00-e0 5b 18 77 5c 00 53 00 l........[.w.S.
77185be4 59 00 53 00 54 00 45 00-4d 00 33 00 32 00 5c 00 Y.S.T.E.M.3.2..
77185bf4 00 00 90 90 90 90 90 8b-ff 55 8b ec 51 51 83 65 .........U..QQ.e
77185c04 fc 00 53 56 8b 35 0c 02-24 77 57 81 fe 0c 02 24 ..SV.5..$wW....$
77185c14 77 74 31 8d 45 f8 50 6a-09 8b fe 8b 36 6a 01 ff wt1.E.Pj....6j..
Ayrıca bu adresten [decimal] 20 byte sonraki 4 byte'lık alanda da bu veri yapısının ait olduğu DLL'in
adının tutulduğu alanın pointer'ını barındıran veri yer alır. Bu alanlar sırasıyla incelenerek
Kernel32.dll'in kaydına ulaşıp ulaşmadığımız tespit edilebilir. Zincir halkalarında her bir modül'ün adresi
de bulunur. Sonraki adımlar bu modül başlangıç adresinden başlayarak modülün (yani DLL'in) Export
tablosu içinde gezinmeye başlamak ve LoadLibrary fonksiyon adresini bulmaya çalışarak devam
edecektir. Biz örneği daha da karmaşıklaştırmamak için bu adımı burada sonlandırıyoruz. Bu aşamada
zararlı yazılım yazarının bazı DLL'leri yüklediğinin kolay görünür olmaması için çaba gösterdiğini
söyleyebiliriz.
ANALİZ
STATİK ANALİZ [Disassembly]
Bu fonksiyonda daha aşağılara ilerlediğimizde
bazı HEX değerlerin stack'e push edildiğini
görüyoruz. Bunları "R" karakteri ile ASCII
karakterlere dönüştürebiliriz.
Zararlı yazılım yazarı
strings incelemesinden
[wininet.dll] DLL adının
stack'e yazıldığı ortaya
çıkmasın diye işlevsiz
opcode'ları da assembly
koduna eklemiş.
ANALİZ
STATİK ANALİZ [Disassembly]
[wininet.dll] kütüphanesinin
barındırdığı fonksiyonlara
MSDN'den göz atalım.
ANALİZ
STATİK ANALİZ [Disassembly]
HTTP erişimi ile ilgili olanların bir
kısmı burada görüldüğü gibidir.
ANALİZ
STATİK ANALİZ [Disassembly]
InternetOpenUrl fonksiyonu HTTP
protokolü ile bir web kaynağına
erişmek için kullanılabilir.
ANALİZ
STATİK ANALİZ [Disassembly]
İncelediğimiz kodun içinde pek çok
defa çağrıldığını gördüğümüz bir
fonksiyon da dikkatimizi çekebilir.
Yeterli zaman olması halinde bu
fonksiyona verilen iki parametrenin
belli bir DLL'in başlangıç adresi ve bir
fonksiyon adının basit bir algoritma ile
hash'lenmiş değeri olduğunu tespit
edebilirdik. Bu sayede çağrılan
fonksiyonların neler olduğunu statik
analiz ile tespit etmemiz çok
zorlaştırılmıştır. Ancak dinamik
analizde hangi fonksiyonların çağrıldığı
açıkça görülebilir.
ANALİZ
STATİK ANALİZ [Disassembly]
Fonksiyon kodları içinde biraz daha
aşağıya indiğimizde stack'e yazılan
bir dizi HEX veri daha görebiliriz.
Ancak bu verileri "R" komutuyla
ASCII karşılıklarına
dönüştüremiyoruz, çünkü dikkat
ederseniz arada NULL [00]
karakterleri bulunması bu
karakterlerin Unicode karakterler
olabileceğine işaret etmektedir.
ANALİZ
STATİK ANALİZ [Disassembly]
Bu karakterleri kodun içinden daha rahat çekebilmek için IDA'nın 8 opcode byte'ına kadar
görüntüleme ayarını Options penceresinden yapalım.
ANALİZ
STATİK ANALİZ [Disassembly]
Opcode'ları da içeren satırları
tarayarak clipboard'a kopyalayalım
(sağ klikle)
ANALİZ
STATİK ANALİZ [Disassembly]
Kopyaladığımız veriyi Notepad++
ekranına yapıştırdıktan sonra
sadece push edilen 2. ve 5. byte'lar
arasını ALT tuşuna basarken mouse
ile tarayarak kopyalayalım.
ANALİZ
STATİK ANALİZ [Disassembly]
Kopyaladığımız veriyi bir başka
Notepad++ ekranına yapıştırdıktan
sonra boşlukları ve satır sonlarını
kaldıralım.
ANALİZ
STATİK ANALİZ [Disassembly]
Kalan son veriyi HxD veya farklı bir
Hexadecimal bir editöre
kopyaladığımızda sağ tarafta
Unicode karakter karşılıklarını
görebiliriz [Microsoft Internet
Explore]
ANALİZ
STATİK ANALİZ [Disassembly]
Aynı işlemi daha aşağıdaki bölüm
için de tekrarlayalım.
ANALİZ
STATİK ANALİZ [Disassembly]
Notepad++'da sadece push edilen
verilerin kalmasını sağlayalım.
ANALİZ
STATİK ANALİZ [Disassembly]
Bu alanda da aşağıdaki verinin stack'e
yazıldığını ortaya çıkarmış olduk:
[http://www.btr-mlwsunucu.com/paket.bin]
ANALİZ
DİNAMİK ANALİZ [Debugging]
Bu noktaya kadar analizin tamamını statik
analiz olarak yapmanın kulağa geldiği kadar
hoş olmadığını farketmiş olmalıyız.
Zararlı yazılımın farklı bir proses'in address
alanına yazdığı verinin ne olduğunu anlamanın
en pratik yolu dinamik analizden faydalanmak
olacaktır.
Bunun için zararlı yazılımımızın çalışacağı
Windows bilgisayarla aynı karantina
subnet'inde bulunmakta olan Kali
bilgisayarımız üzerindeki Honeypot servislerini
[inetsim] başlatalım.
ANALİZ
DİNAMİK ANALİZ [Debugging]
Decompress edilmiş olan uygulamamızın ASLR
desteğini daha önceden kaldırmıştık (çünkü
başka türlü çalışmıyordu). Bu imkan sayesinde
statik analizdeki VA adreslerimizin debug
ederken de aynı kalacağından emin olabiliriz.
Şimdi tam farklı process'in address alanına
yazılacak olan verinin Stack'e yazıldığı
instruction'ın adresi olan [0x401E79] adresine
bir breakpoint koyalım.
ANALİZ
DİNAMİK ANALİZ [Debugging]
Play düğmesine gerektiği kadar basarak
breakpoint satırına kadar ilerleyelim.
ANALİZ
DİNAMİK ANALİZ [Debugging]
F7 tuşu veya Step Into düğmesine basarak Stack'e farklı process'in
address alanına yazılacak olan verinin adresini yazalım.
Bu işlem gerçekleştikten hemen sonra da yazılan adresin işaret ettiği
alanı daha iyi gözlemleyebilmek için Stack'te bu adrese sağ tıklayarak
[Follow in Dump] seçeneğini seçelim.
ANALİZ
DİNAMİK ANALİZ [Debugging]
Sol altta bulunan Memory Dump alanındaki
verileri daha iyi görebilmek için bu alana sağ
klikleyerek [Hex/ASCII (16 bytes)] seçeneğini
seçelim.
ANALİZ
DİNAMİK ANALİZ [Debugging]
Anlaşılan o ki söz konusu veri [www.btr-
mlwsunucu.com/paket.bin] HTTP isteğine
gelen yanıttan oluşuyor. Inetsim servisi
sayesinde bu yanıt gerçek paket.bin dosyası
değil de sahte bir HTML yanıtından oluşuyor.
ANALİZ
PAYLOAD ANALİZİ
Bu noktada
[http://www.btr-mlwsunucu.com/paket.bin]
isteğine dönen gerçek yanıtı inceleyelim.
ANALİZ
PAYLOAD ANALİZİ
paket.bin dosyasını VirusTotal'e
gönderdiğimizde Shellcode olarak
tanımlanıyor.
ANALİZ
PAYLOAD ANALİZİ
IDA Pro'da bu dosyayı incelediğimizde dosya
normal bir PE dosyası olmadığından paket.bin
dosyasının içeriğini veri olarak algılanacaktır.
ANALİZ
PAYLOAD ANALİZİ
IDA Pro'nun bu verileri kod olarak
değerlendirmesi için sağ klikleyerek [Code]
seçeneğini seçebiliriz.
ANALİZ
PAYLOAD ANALİZİ
Kod bölümü hemen normal bir uygulamadaki
gibi grafik halinde görüntülenmeyebilir,
uygulama grafiğini görebilmek için [Space]
tuşuna basınız.
ANALİZ
PAYLOAD ANALİZİ Grafik gösterimde sağdaki koyu mavi çizgi bir
döngü olduğuna işaret ediyor. Bu shellcode'un
encoded bir shellcode olması durumunda
dinamik analiz daha doğru bir tercih olacaktır.
Zararlı uygulamanın internete erişmesi yerine
paket.bin dosyasını inetsim tarafından
sağlayarak dinamik analiz gerçekleştirilebilir.
ANALİZ
PAYLOAD ANALİZİ
• Gerçekte bu payload'un tam olarak ne yaptığını anlamak için
ciddi bir süreyi tersine mühendislik için harcamamaız gerekebilir.
• Bu payload bir meterpreter reverse_tcp payload'u ve karşı
tarafta bir handler tarafından karşılanması gerekir.
• Gerçek payload'un ne yaptığının dinamik analizle görülmesi için
kurum ağından bağımsız bir ADSL hattı ve yine bir sanal makine
kullanılarak inceleme yapılabilir, elbette çok dikkatli olmak
kaydıyla.
ANTI-DISASSEMBLY
ANTI-DISASSEMBLY TEKNİKLERİ
• Uygulamamızda bir anti-disassembly örneği barındırmadık,
çünkü yeterli zaman ayrılmaması durumunda ve henüz konuya
yeni kişiler için bu durumların tespiti ve çözülmesi zor olabilir.
• Ancak deneyimli tersine mühendislik uzmanları için bu
tekniklerin tespiti ve ortadan kaldırılmasının
zannedilebileceğinden daha kolay olacağını söyleyebiliriz.
ANTI-DISASSEMBLY
ANTI-DISASSEMBLY TEKNİKLERİ
• Disassembler'ları yanlış yönlendirmek ve disassembly kodunun
uygulamanın gerçek davranışından farklılaştırmak için pek çok
teknik kullanılabilir, örneğin:
• [EB FF C0 48] opcode'ları "EB FF - jmp 1", geçerli olmayan bir
"C0" opcode'u ve "48 - dec eax" olarak disassemble
edilecektir.
• Gerçekte ise "jmp 1" instruction'ı Instruction Pointer'ı "EB
FF" opcode'larının başından itibaren 1 byte ileriye atlatacak
ve "FF C0 - inc eax" olarak, "48 - dec eax" olarak
çalıştırılacaktır.
• Çözüm bu işe yaramayan ve karmaşıklığa neden olan opcode'ları
NOP ile yamalayarak ortadan kaldırmaktır.
BTRisk Zararlı Yazılım Analizi Eğitimi Sunumu - Bölüm 2

More Related Content

What's hot

Windows Ağlarda Saldırı Tespiti
Windows Ağlarda Saldırı TespitiWindows Ağlarda Saldırı Tespiti
Windows Ağlarda Saldırı TespitiSparta Bilişim
 
Zararlı Yazılım Analizi İçin Lab Ortamı Hazırlamak
Zararlı Yazılım Analizi İçin Lab Ortamı HazırlamakZararlı Yazılım Analizi İçin Lab Ortamı Hazırlamak
Zararlı Yazılım Analizi İçin Lab Ortamı HazırlamakBGA 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
 
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
 
Kurumsal Ağlarda Log İnceleme Yöntemiyle Saldırı Analizi
Kurumsal Ağlarda Log İnceleme Yöntemiyle Saldırı AnaliziKurumsal Ağlarda Log İnceleme Yöntemiyle Saldırı Analizi
Kurumsal Ağlarda Log İnceleme Yöntemiyle Saldırı AnaliziBGA Cyber Security
 
Yeni Nesil Sosyal Mühendislik Saldırıları ve Siber İstihbarat
Yeni Nesil Sosyal Mühendislik Saldırıları ve Siber İstihbaratYeni Nesil Sosyal Mühendislik Saldırıları ve Siber İstihbarat
Yeni Nesil Sosyal Mühendislik Saldırıları ve Siber İstihbaratSeyfullah KILIÇ
 
İleri Seviye Ağ Güvenliği Lab Kitabı
İleri Seviye Ağ Güvenliği Lab Kitabıİleri Seviye Ağ Güvenliği Lab Kitabı
İleri Seviye Ağ Güvenliği Lab KitabıBGA 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
 
Penetrasyon Testlerinde Açık Kod Yazılımların Kullanımı
Penetrasyon Testlerinde Açık Kod Yazılımların KullanımıPenetrasyon Testlerinde Açık Kod Yazılımların Kullanımı
Penetrasyon Testlerinde Açık Kod Yazılımların KullanımıBGA Cyber Security
 
Beyaz Şapkalı Hacker (CEH) Lab Kitabı
Beyaz Şapkalı Hacker (CEH) Lab KitabıBeyaz Şapkalı Hacker (CEH) Lab Kitabı
Beyaz Şapkalı Hacker (CEH) Lab KitabıBGA Cyber Security
 
Log Yönetimi ve Saldırı Analizi Eğitimi - 2
Log Yönetimi ve Saldırı Analizi Eğitimi - 2Log Yönetimi ve Saldırı Analizi Eğitimi - 2
Log Yönetimi ve Saldırı Analizi Eğitimi - 2BGA Cyber Security
 
Sandbox Atlatma Teknikleri ve Öneriler
Sandbox Atlatma Teknikleri ve ÖnerilerSandbox Atlatma Teknikleri ve Öneriler
Sandbox Atlatma Teknikleri ve ÖnerilerBGA Cyber Security
 
Hacklenmiş Web Sunucu Analizi
Hacklenmiş Web Sunucu AnaliziHacklenmiş Web Sunucu Analizi
Hacklenmiş Web Sunucu AnaliziBGA Cyber Security
 
Hacklenmiş Windows Sistem Analizi
Hacklenmiş Windows Sistem AnaliziHacklenmiş Windows Sistem Analizi
Hacklenmiş Windows Sistem AnaliziBGA Cyber Security
 
Mobil Pentest Eğitim Dökümanı
Mobil Pentest Eğitim DökümanıMobil Pentest Eğitim Dökümanı
Mobil Pentest Eğitim DökümanıAhmet Gürel
 
LINUX, WINDOWS VE AĞ SİSTEMLERİ SIZMA TESTLERİ
LINUX, WINDOWS VE AĞ SİSTEMLERİ SIZMA TESTLERİ LINUX, WINDOWS VE AĞ SİSTEMLERİ SIZMA TESTLERİ
LINUX, WINDOWS VE AĞ SİSTEMLERİ SIZMA TESTLERİ BGA Cyber Security
 

What's hot (20)

Windows Ağlarda Saldırı Tespiti
Windows Ağlarda Saldırı TespitiWindows Ağlarda Saldırı Tespiti
Windows Ağlarda Saldırı Tespiti
 
Zararlı Yazılım Analizi İçin Lab Ortamı Hazırlamak
Zararlı Yazılım Analizi İçin Lab Ortamı HazırlamakZararlı Yazılım Analizi İçin Lab Ortamı Hazırlamak
Zararlı Yazılım Analizi İçin Lab Ortamı Hazırlamak
 
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
 
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
 
Kurumsal Ağlarda Log İnceleme Yöntemiyle Saldırı Analizi
Kurumsal Ağlarda Log İnceleme Yöntemiyle Saldırı AnaliziKurumsal Ağlarda Log İnceleme Yöntemiyle Saldırı Analizi
Kurumsal Ağlarda Log İnceleme Yöntemiyle Saldırı Analizi
 
Yeni Nesil Sosyal Mühendislik Saldırıları ve Siber İstihbarat
Yeni Nesil Sosyal Mühendislik Saldırıları ve Siber İstihbaratYeni Nesil Sosyal Mühendislik Saldırıları ve Siber İstihbarat
Yeni Nesil Sosyal Mühendislik Saldırıları ve Siber İstihbarat
 
İleri Seviye Ağ Güvenliği Lab Kitabı
İleri Seviye Ağ Güvenliği Lab Kitabıİleri Seviye Ağ Güvenliği Lab Kitabı
İleri Seviye Ağ Güvenliği Lab Kitabı
 
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
 
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
 
Uygulamali Sizma Testi (Pentest) Egitimi Sunumu - 1
Uygulamali Sizma Testi (Pentest) Egitimi Sunumu - 1Uygulamali Sizma Testi (Pentest) Egitimi Sunumu - 1
Uygulamali Sizma Testi (Pentest) Egitimi Sunumu - 1
 
Penetrasyon Testlerinde Açık Kod Yazılımların Kullanımı
Penetrasyon Testlerinde Açık Kod Yazılımların KullanımıPenetrasyon Testlerinde Açık Kod Yazılımların Kullanımı
Penetrasyon Testlerinde Açık Kod Yazılımların Kullanımı
 
Beyaz Şapkalı Hacker (CEH) Lab Kitabı
Beyaz Şapkalı Hacker (CEH) Lab KitabıBeyaz Şapkalı Hacker (CEH) Lab Kitabı
Beyaz Şapkalı Hacker (CEH) Lab Kitabı
 
Log Yönetimi ve Saldırı Analizi Eğitimi - 2
Log Yönetimi ve Saldırı Analizi Eğitimi - 2Log Yönetimi ve Saldırı Analizi Eğitimi - 2
Log Yönetimi ve Saldırı Analizi Eğitimi - 2
 
Sandbox Atlatma Teknikleri ve Öneriler
Sandbox Atlatma Teknikleri ve ÖnerilerSandbox Atlatma Teknikleri ve Öneriler
Sandbox Atlatma Teknikleri ve Öneriler
 
10 Adımda Sızma Testleri
10 Adımda Sızma Testleri10 Adımda Sızma Testleri
10 Adımda Sızma Testleri
 
Hacklenmiş Web Sunucu Analizi
Hacklenmiş Web Sunucu AnaliziHacklenmiş Web Sunucu Analizi
Hacklenmiş Web Sunucu Analizi
 
Hacklenmiş Windows Sistem Analizi
Hacklenmiş Windows Sistem AnaliziHacklenmiş Windows Sistem Analizi
Hacklenmiş Windows Sistem Analizi
 
Web uygulama açıklıklarından faydalanarak sistem ele geçirme
Web uygulama açıklıklarından faydalanarak sistem ele geçirmeWeb uygulama açıklıklarından faydalanarak sistem ele geçirme
Web uygulama açıklıklarından faydalanarak sistem ele geçirme
 
Mobil Pentest Eğitim Dökümanı
Mobil Pentest Eğitim DökümanıMobil Pentest Eğitim Dökümanı
Mobil Pentest Eğitim Dökümanı
 
LINUX, WINDOWS VE AĞ SİSTEMLERİ SIZMA TESTLERİ
LINUX, WINDOWS VE AĞ SİSTEMLERİ SIZMA TESTLERİ LINUX, WINDOWS VE AĞ SİSTEMLERİ SIZMA TESTLERİ
LINUX, WINDOWS VE AĞ SİSTEMLERİ SIZMA TESTLERİ
 

Similar to BTRisk Zararlı Yazılım Analizi Eğitimi Sunumu - Bölüm 2

Metasploit Framework ile Güvenlik Denetimi
Metasploit Framework ile Güvenlik DenetimiMetasploit Framework ile Güvenlik Denetimi
Metasploit Framework ile Güvenlik DenetimiFatih Ozavci
 
Web Uygulamalarında Kaynak Kod Analizi - 1
Web Uygulamalarında Kaynak Kod Analizi - 1Web Uygulamalarında Kaynak Kod Analizi - 1
Web Uygulamalarında Kaynak Kod Analizi - 1Mehmet Ince
 
Devfest Istanbul 2015 Sunumu
Devfest Istanbul 2015 SunumuDevfest Istanbul 2015 Sunumu
Devfest Istanbul 2015 SunumuAybüke Özdemir
 
Kurumsal Yazılım Geliştirme ve Visual Studio 2008
Kurumsal Yazılım Geliştirme ve Visual Studio 2008Kurumsal Yazılım Geliştirme ve Visual Studio 2008
Kurumsal Yazılım Geliştirme ve Visual Studio 2008mtcakmak
 
Bilgi Sistemleri Güvenliği Metasploit
Bilgi Sistemleri Güvenliği MetasploitBilgi Sistemleri Güvenliği Metasploit
Bilgi Sistemleri Güvenliği Metasploitmsoner
 
Windows İşletim Sistemi Yetki Yükseltme Çalışmaları
Windows İşletim Sistemi Yetki Yükseltme ÇalışmalarıWindows İşletim Sistemi Yetki Yükseltme Çalışmaları
Windows İşletim Sistemi Yetki Yükseltme ÇalışmalarıBGA Cyber Security
 
45965 php-source-code-analysis
45965 php-source-code-analysis45965 php-source-code-analysis
45965 php-source-code-analysisAttaporn Ninsuwan
 
Beyaz Şapkalı Hacker CEH Eğitimi - Exploit Aşaması
Beyaz Şapkalı Hacker CEH Eğitimi - Exploit AşamasıBeyaz Şapkalı Hacker CEH Eğitimi - Exploit Aşaması
Beyaz Şapkalı Hacker CEH Eğitimi - Exploit AşamasıPRISMA CSI
 
Go Programlama Dili - Seminer
Go Programlama Dili - SeminerGo Programlama Dili - Seminer
Go Programlama Dili - SeminerCihan Özhan
 
Python programlama
Python programlamaPython programlama
Python programlamaMurat KARA
 
Siber Guvenlik ve Etik Hhacking -2-
Siber Guvenlik ve Etik Hhacking -2-Siber Guvenlik ve Etik Hhacking -2-
Siber Guvenlik ve Etik Hhacking -2-Murat KARA
 
Hacker’ların Yeni Gozdesi - PowerShell
Hacker’ların Yeni Gozdesi - PowerShellHacker’ların Yeni Gozdesi - PowerShell
Hacker’ların Yeni Gozdesi - PowerShellAdeo Security
 
Python Programlama Diline Giriş - Güncelleme 2018
Python Programlama Diline Giriş - Güncelleme 2018Python Programlama Diline Giriş - Güncelleme 2018
Python Programlama Diline Giriş - Güncelleme 2018Murat KARA
 
ASP.NET MVC'den ASP.NET Core MVC'ye Geçiş Süreci
ASP.NET MVC'den ASP.NET Core MVC'ye Geçiş SüreciASP.NET MVC'den ASP.NET Core MVC'ye Geçiş Süreci
ASP.NET MVC'den ASP.NET Core MVC'ye Geçiş SüreciSinan Bozkuş
 
Ders 2-1 :Yazılım Kavramı ve Çeşitleri
Ders 2-1 :Yazılım Kavramı ve ÇeşitleriDers 2-1 :Yazılım Kavramı ve Çeşitleri
Ders 2-1 :Yazılım Kavramı ve ÇeşitleriOnlineWebDersleri
 

Similar to BTRisk Zararlı Yazılım Analizi Eğitimi Sunumu - Bölüm 2 (20)

Metasploit Framework ile Güvenlik Denetimi
Metasploit Framework ile Güvenlik DenetimiMetasploit Framework ile Güvenlik Denetimi
Metasploit Framework ile Güvenlik Denetimi
 
Web Uygulamalarında Kaynak Kod Analizi - 1
Web Uygulamalarında Kaynak Kod Analizi - 1Web Uygulamalarında Kaynak Kod Analizi - 1
Web Uygulamalarında Kaynak Kod Analizi - 1
 
Devfest Istanbul 2015 Sunumu
Devfest Istanbul 2015 SunumuDevfest Istanbul 2015 Sunumu
Devfest Istanbul 2015 Sunumu
 
Visual Studio Developer Tools
Visual Studio Developer ToolsVisual Studio Developer Tools
Visual Studio Developer Tools
 
Kurumsal Yazılım Geliştirme ve Visual Studio 2008
Kurumsal Yazılım Geliştirme ve Visual Studio 2008Kurumsal Yazılım Geliştirme ve Visual Studio 2008
Kurumsal Yazılım Geliştirme ve Visual Studio 2008
 
Bilgi Sistemleri Güvenliği Metasploit
Bilgi Sistemleri Güvenliği MetasploitBilgi Sistemleri Güvenliği Metasploit
Bilgi Sistemleri Güvenliği Metasploit
 
Windows İşletim Sistemi Yetki Yükseltme Çalışmaları
Windows İşletim Sistemi Yetki Yükseltme ÇalışmalarıWindows İşletim Sistemi Yetki Yükseltme Çalışmaları
Windows İşletim Sistemi Yetki Yükseltme Çalışmaları
 
45965 php-source-code-analysis
45965 php-source-code-analysis45965 php-source-code-analysis
45965 php-source-code-analysis
 
Akıllı Otopark Sistemi
Akıllı Otopark SistemiAkıllı Otopark Sistemi
Akıllı Otopark Sistemi
 
Beyaz Şapkalı Hacker CEH Eğitimi - Exploit Aşaması
Beyaz Şapkalı Hacker CEH Eğitimi - Exploit AşamasıBeyaz Şapkalı Hacker CEH Eğitimi - Exploit Aşaması
Beyaz Şapkalı Hacker CEH Eğitimi - Exploit Aşaması
 
Go Programlama Dili - Seminer
Go Programlama Dili - SeminerGo Programlama Dili - Seminer
Go Programlama Dili - Seminer
 
Python programlama
Python programlamaPython programlama
Python programlama
 
Siber Guvenlik ve Etik Hhacking -2-
Siber Guvenlik ve Etik Hhacking -2-Siber Guvenlik ve Etik Hhacking -2-
Siber Guvenlik ve Etik Hhacking -2-
 
Hacker’ların Yeni Gozdesi - PowerShell
Hacker’ların Yeni Gozdesi - PowerShellHacker’ların Yeni Gozdesi - PowerShell
Hacker’ların Yeni Gozdesi - PowerShell
 
Python Programlama Diline Giriş - Güncelleme 2018
Python Programlama Diline Giriş - Güncelleme 2018Python Programlama Diline Giriş - Güncelleme 2018
Python Programlama Diline Giriş - Güncelleme 2018
 
ASP.NET MVC'den ASP.NET Core MVC'ye Geçiş Süreci
ASP.NET MVC'den ASP.NET Core MVC'ye Geçiş SüreciASP.NET MVC'den ASP.NET Core MVC'ye Geçiş Süreci
ASP.NET MVC'den ASP.NET Core MVC'ye Geçiş Süreci
 
Ders 2-1 :Yazılım Kavramı ve Çeşitleri
Ders 2-1 :Yazılım Kavramı ve ÇeşitleriDers 2-1 :Yazılım Kavramı ve Çeşitleri
Ders 2-1 :Yazılım Kavramı ve Çeşitleri
 
Web Application Testing
Web Application Testing Web Application Testing
Web Application Testing
 
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 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
 

More from BTRisk Bilgi Güvenliği ve BT Yönetişim Hizmetleri

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

BTRisk X86 Tersine Mühendislik Eğitim Sunumu - Bölüm-3
BTRisk X86 Tersine Mühendislik Eğitim Sunumu - Bölüm-3BTRisk X86 Tersine Mühendislik Eğitim Sunumu - Bölüm-3
BTRisk X86 Tersine Mühendislik Eğitim Sunumu - Bölüm-3
 
BTRisk X86 Tersine Mühendislik Eğitim Sunumu - Bölüm-2
BTRisk X86 Tersine Mühendislik Eğitim Sunumu - Bölüm-2BTRisk X86 Tersine Mühendislik Eğitim Sunumu - Bölüm-2
BTRisk X86 Tersine Mühendislik Eğitim Sunumu - Bölüm-2
 
BTRisk X86 Tersine Mühendislik Eğitim Sunumu - Bölüm-1
BTRisk X86 Tersine Mühendislik Eğitim Sunumu - Bölüm-1BTRisk X86 Tersine Mühendislik Eğitim Sunumu - Bölüm-1
BTRisk X86 Tersine Mühendislik Eğitim Sunumu - Bölüm-1
 
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
 
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 Zararlı Yazılım Analizi Eğitimi Sunumu - Bölüm 2

  • 1. ZARARLI YAZILIM ANALİZİ EĞİTİMİ BÖLÜM 2 İSTANBUL blog.btrisk.com @btrisk /btrisktv /btrisk
  • 2. BTRİSK HAKKINDA TANIŞMA Pentest & BT Denetimi ISO27001 Danışmanlık Hizmetleri BG Operasyon Hizmetleri
  • 3. ANALİZ STATİK ANALİZ [Import Address Table] Bir uygulamanın Import ettiği fonksiyonlar o uygulamanın fonksiyonalitesine ilişkin bize fikir verebilirler
  • 4. ANALİZ STATİK ANALİZ [Import Address Table] Import edilen fonksiyon adlarını kopyalayarak bir şüpheli fonksiyon listesiyle karşılaştırabilmek için IDA Pro'nun Imports penceresinde sağ klikleyerek Copy seçeneğini seçelim
  • 5. ANALİZ STATİK ANALİZ [Import Address Table] Kopyaladığımız listeyi Notepad++'a yapıştırarak arama yapabiliriz
  • 6. ANALİZ STATİK ANALİZ [Import Address Table] Şüpheli API listemizle Import adres tablosunu karşılaştırmak için MS Excel'in VLOOKUP fonksiyonunu da kullanabiliriz
  • 7. ANALİZ STATİK ANALİZ [Import Address Table] Bunun için fonksiyon adlarını ayrı kolona bölmek amacıyla Text to Columns özelliğini kullanalım ve delimiter olarak "Space"i seçelim
  • 8. ŞÜPHELİ WINDOWS API'LERİ Windows API Fonksiyonları • Windows API fonksiyonlarına baktığımızda bazılarının “A” ile, bazılarının ise “W” ile bittiğini görürüz. Bu fonksiyonlardan A ile bitenler “string” veri tipinde aldıkları parametreleri ANSI (ASCII değil) string’leri olarak, W ile bitenler ise Unicode (Wide Character) string’leri olarak kabul ederler. • Bazı fonksiyonların sonu da “Ex” olarak bitmektedir (bu fonksiyonlarda da W ve A ekleri görülebilir, yani “Ex” ekinden sonra W veya A gelebilir). Bu fonksiyonlar da benzer isimli önceki fonksiyonların yerini almış ancak eski fonksiyonların sahip oldukları fonksiyonaliteyi de destekleyen “Extended” fonksiyonlardır.
  • 9. ŞÜPHELİ WINDOWS API'LERİ Şüphe Doğurabilecek API’ler • Zararlı yazılımların genellikle ihtiyaç duydukları ve bu yüzden şüpheli olabilecek API’lere sonraki sayfalardaki örnekleri verebiliriz. Elbette API’lerin birden fazla kullanım amacı olabilir ve liste daha da genişletilebilir, ancak kullanım amaçları ile ilgili fikir vermesi için bu şekilde bir gruplama yapılmıştır. • Elbette zararlının özel amaçları doğrultusunda ihtiyaç duyacağı başka API’ler de olabilir. Tüm Windows API’lerine erişmek için MSDN’den faydalanabilirsiniz.
  • 10. ŞÜPHELİ WINDOWS API'LERİ Ağ Erişimiyle İlgili API’ler İhtiyaç: Zararlı yazılımlar veriyi dışarı sızdırmak, bir sunucuyla tünel bağlantısı kurmak, ikinci aşama payload’larını indirmek, v.b. ihtiyaçlarla ağ erişim API’lerini kullanabilirler. WinSock API • WSAStartup • getaddrinfo • socket • connect • send • recv • WSAGetLastError
  • 11. ŞÜPHELİ WINDOWS API'LERİ Ağ Erişimiyle İlgili API’ler (devamı) WinINet API • InternetOpen • InternetConnect • InternetOpenURL • InternetReadFile • InternetWriteFile • HTTPOpenRequest • HTTPQueryInfo • HTTPSendRequest
  • 12. ŞÜPHELİ WINDOWS API'LERİ Ağ Erişimiyle İlgili API’ler (devamı) Kernel32 API • ConnectNamedPipe • PeekNamedPipe Urlmon API • URLDownloadToFile Diğer • FtpPutFile • GetAdaptersInfo (Anti-Virtual Machine kontrolü için de kullanılabilir)
  • 13. İhtiyaç: Zararlı yazılımlar dosya drop etmek (resource section’larındaki bir dosyayı diske yazmak), kendilerini başka bir isimle saklamak, veri sızdırmak için dosyalara erişmek, indirdiği ve ihtiyacı kalmayan dosyaları silmek v.b. amaçlarla dosya erişim API’lerini kullanabilirler. • CreateFile • ReadFile • WriteFile • FindResource • LoadResource ŞÜPHELİ WINDOWS API'LERİ Dosya Erişimiyle ve Dropper Fonksiyonalitesiyle İlgili API’ler
  • 14. ŞÜPHELİ WINDOWS API'LERİ Registry Erişimiyle İlgili API’ler İhtiyaç: Zararlı yazılımlar kalıcılıklarını sağlamak için Autorun registry değerlerine yazmak, parola v.b. hassas verilere erişmek, varsa hedeflediği bir uygulamanın kurulu olup olmadığını anlamak, v.b. amaçlarla registry API’lerini kullanabilirler. • RegOpenKeyEx • RegSetValueEx • RegGetValue
  • 15. ŞÜPHELİ WINDOWS API'LERİ Keylogger Fonksiyonalitesiyle İlgili API’ler İhtiyaç: Zararlı yazılımın keylogger fonksiyonalitesi var ise bu bilgileri elde etmelerine imkan veren API’lere erişebilirler. • GetAsyncKeyState • GetForegroundWindow • GetKeyState • SetWindowsHookEx • CallNextHookEx • AttachThreadInput • MapVirtualKey
  • 16. ŞÜPHELİ WINDOWS API'LERİ Proses İşlemleri ile İlgili API’ler İhtiyaç: Zararlı yazılımlar diğer proses’lerin adres space’lerinde kod çalıştırmak için, anti-virüs v.d. proses’leri öldürmek için, dinamik analizi engellemek için v.d. amaçlarla bu API’lere ihtiyaç duyabilirler. • CreateToolhelp32Snapshot (process listesini belirlemek için kullanılır) • Process32First/Process32Next • Module32First/Module32Next • OpenProcess • VirtualAllocEx • VirtualProtectEx (bellek erişim haklarının değiştirilmesi için kullanılır) • WriteProcessMemory • AdjustTokenPrivileges • CreateRemoteThread • EnumProcesses • EnumProcessModules • IsWoW64Process • QueueUserAPC
  • 17. ŞÜPHELİ WINDOWS API'LERİ DLL Yükleme ve Fonksiyon Adresi Bulma API’leri İhtiyaç: Zararlı yazılımlar detaylı statik analizde tespit edilebilecek olmalarına rağmen Import Address Table’larında kullandıkları kütüphane ve API’lerin görünmemesi amacıyla dinamik olarak kütüphane yükleme ve bunların Export ettikleri fonksiyonların adreslerini bulmak için gerekli API’leri kullanabilirler. • LoadLibrary • GetProcAddress • LdrLoadDll
  • 18. ŞÜPHELİ WINDOWS API'LERİ Debug Edilip Edilmediğini Tespit Etmek için Kullanılan API’ler İhtiyaç: Zararlı yazılımlar debug edildiklerini tespit etmek ve normal davranışlarını sergilememek için çok çeşitli teknikler kullanırlar. Bunlardan bir kısmı Windows’un sağladığı debugger tespit imkanlarıdır. • IsDebuggerPresent • CheckRemoteDebuggerPresent • FindWindow (örneğin Ollydbg uygulamasının aktif olup olmadığını anlamak için) • GetTickCount • NtQueryInformationProcess • OutputDebugString
  • 19. Servislerle ve Scheduled Task’larla Kalıcılığı Sağlamak için Kullanılabilecek API’ler ŞÜPHELİ WINDOWS API'LERİ İhtiyaç: Zararlının kalıcılık için servis veya scheduled task kullanması durumunda kullandığı API’ler • CreateService • ControlService • OpenSCManager • NetScheduleJobAdd
  • 20. ŞÜPHELİ WINDOWS API'LERİ Diğer Dosyalara Bulaşmak için Kullanılan API’ler İhtiyaç: Zararlının diğer dosyalara da kod eklemek için kullandığı API’ler • FindFirstFile • FindNextFile • NtQueryDirectoryFile • CreateFileMapping (Disk üzerindeki PE dosyalarına kod inject etmek için bunları belleğe yükleyerek ona erişmek için kullanılan API) • MapViewOfFile
  • 21. ŞÜPHELİ WINDOWS API'LERİ COM Nesnelerini Kullanmak için Kullanılan API’ler İhtiyaç: Zararlı yazılım Windows işletim sistemi ile gelen COM bileşenlerini kullanabilir. Bu durumda hangi COM nesnesinin ve dolayısıyla hangi fonksiyonalitenin kullanıldığını anlamak için onun class identifier’ını (CLSID) incelememiz gerekir. • OleInitialize (COM nesneleri kullanılmadan önce çağrılır) • CoInitializeEx (COM nesneleri kullanılmadan önce çağrılır)
  • 22. ŞÜPHELİ WINDOWS API'LERİ Veri Sızdırmak, Parola Çalmak için Kullanılabilecek API’ler İhtiyaç: Zararlı yazılım sistem üzerinde tanımlı kullanıcıların parola hash’lerini SAM veritabanına erişerek, sisteme erişmiş kullanıcıların parolalarını bellekteki verilere erişerek ele geçirmek isteyebilir, sisteme map’lenmiş paylaşımlar içinde de veri arayabilir. • LsaEnumerateLogonSessions (Credential çalan zararlılar tarafından sisteme logon olmuş kullanıcıları tespit etmek için kullanılabilir) • SamIConnect (SAM veritabanına erişmek ve parola hash’lerini dump etmek için kullanılır) • SamIGetPrivateData (SAM veritabanına erişmek ve parola hash’lerini dump etmek için kullanılır) • SamQueryInformationUse (SAM veritabanına erişmek ve parola hash’lerini dump etmek için kullanılır)
  • 23. ŞÜPHELİ WINDOWS API'LERİ Veri Sızdırmak, Parola Çalmak için Kullanılabilecek API’ler (devamı) • NetShareEnum (SAM veritabanına erişmek ve parola hash’lerini dump etmek için kullanılır) • ReadProcessMemory • Toolhelp32ReadProcessMemory
  • 24. ŞÜPHELİ WINDOWS API'LERİ Diğer API’ler • CreateMutex (Aynı anda zararlı prosesin tek bir instance’ının çalışması için kullanılabilen bir API’dir. Mutex bir kilit gibi davranır ve bu kilide sahip olmayan proses diğerlerini bekler) • CreateProcess • ShellExecute • WinExec • System (zararlı proses drop ettiği başka bir uygulamayı veya sistem üzerindeki başka bir uygulamayı başlatmak için bu API’leri kullanabilir) • CryptAcquireContext (Kriptolama fonksiyonları zararlı tarafından çeşitli amaçlarla kullanılabilir, crypt ile başlayan pek çok fonksiyon incelenebilir) • EnableExecuteProtectionSupport (DEP kontrolünü ortadan kaldırmak için kullanılan fonksiyondur)
  • 25. ŞÜPHELİ WINDOWS API'LERİ Diğer API’ler (devamı) • NtSetInformationProcess (Proses haklarını yükseltmek veya DEP kontrolünü ortadan kaldırmak için kullanılabilir) • GetSystemDefaultLangId (Ransomware v.b. mesaj veren zararlılar tarafından sistemin dil ayarlarını tespit etmek için kullanılır) • GetTempPath (zararlı yazılım bir takım geçici dosyaları saklamak için bu alanı kullanabilir) • SetFileTime (zararlı yazılım aktivitelerini gizleyebilmek için kullanabilir) • StartServiceCtrlDispatcher (Servis olarak başlayan bir proses’in ilk 30 sn. içinde bu fonksiyonu çağırması gerekir. Bu API’nin gözlenmesi zararlının servis olarak çalıştırılması gerektiği anlamına gelebilir.) • IsNTAdmin • IsUserAnAdmin (zararlı kullanıcının admin haklarına sahip olup olmadığını kontrol etmek için bu API’leri kullanabilir)
  • 26. ŞÜPHELİ WINDOWS API'LERİ ÖNEMLİ • Derleyiciler bazı fonksiyonları yazılımcı bu fonksiyonu doğrudan kullanmamış olsa da uygulamaya ekleyebilmektedir. Örneğin [IsDebuggerPresent] fonksiyonunu aslında yazılımcı böyle bir kontrol yapmasa da bazı uygulamalarda mevcut olarak gözlemleyebilirsiniz. • Şüpheli bir API’nin tam olarak nasıl kullanıldığını anlayabilmek için disassembly üzerinde aldığı parametreleri incelemek ve binary debugger ile dinamik analiz ile izlemek gerekecektir. Bunu yapabilmek için de X86 mimarisi, X86 Assembly, calling conventions (fonksiyon çağırma yöntemleri) bilgilerine sahip olmak gereklidir.
  • 27. ANALİZ STATİK ANALİZ [Import Address Table] Oluşturduğumuz şüpheli API adları listesini kopyalayarak A ve W uzantılı adlarını da türetelim
  • 28. ANALİZ STATİK ANALİZ [Import Address Table] MS Excel'in VLOOKUP fonksiyonunu kullanarak zararlı yazılımın IAT'ından elde ettiğimiz liste ile şüpheli API listemizi karşılaştıralım
  • 29. ANALİZ STATİK ANALİZ [Import Address Table] Henüz X86 mimarisi ile ilgili teorik bir çalışma yapmadık, ancak küçük bir tanışıklık için ilgimizi çeken bir API için [ör: RegSetValueExW] zararlımızı inceleyelim. Dinamik analiz sırasında zararlının Autorun registry key'lerine değer yazdığını görmüştük, zararlı yazılımın bu davranışını biraz daha yakından inceleyelim.
  • 30. ANALİZ STATİK ANALİZ [Import Address Table] RegSetValueExW fonksiyonunun çağrıldığı yerleri bulmak ve bu bölümleri inceleyebilmek için IDA Pro'nun Imports penceresinden faydalanabiliriz. Bunun için bu fonksiyonun üzerinde çift tıklayalım.
  • 31. ANALİZ STATİK ANALİZ [Import Address Table] Buradan RegSetValueExW fonksiyonunun IAT'daki yerine geliriz. Fonksiyon adına tıkladıktan sonra "X" harfine basarsak IDA bize bu adresin kullanıldığı kod bölümlerinin Cross (bu yüzden X) Reference bilgilerini verir.
  • 32. ANALİZ STATİK ANALİZ [Import Address Table] XREF listesinde seçtiğimiz bir satıra çift tıkladığımızda ilgili kod için disassembly ekranına geçeriz. Mouse'umuzu fonksiyon adı üzerine getirdiğimizde fonksiyonun parametre yapısını görebiliriz. X86 hakkında daha detaylı çalışacağız, ancak fonksiyonların parametrelerini Stack'e yazılan değerlerden aldığını söyleyelim. Disassembly üzerinden bu değerlerin neler olduğunu anlamak güç, çünkü parametrelerin bir kısmı daha yukarıda yapılan hesaplamalar ve diğer işlemler sonucunda belirlenerek stack'e yazılıyor (push ediliyor).
  • 33. ANALİZ STATİK ANALİZ [Import Address Table] Windows API'leri ve bu fonksiyonların alabilecekleri parametre değerleri ile ilgil detaylı bilgiyi MSDN v.d. kaynaklardan bulabilirsiniz.
  • 34. ANALİZ DİNAMİK ANALİZ [Import Address Table] RegSetValueExW fonksiyonuna verilen parametreleri statik olarak analiz etmek zor olduğu için Immunity Debugger ile dinamik analiz yapalım ve bu fonksiyon çağrılmadan önce Stack'te bulunacak parametreleri inceleyelim.
  • 35. ANALİZ DİNAMİK ANALİZ [Import Address Table] Uygulamanın ASLR destekli olması nedeniyle unpack edilmiş olan uygulamada da hata alıyoruz [uzun incelemeler sonrasında ulaştığım bu sonuç hakkında bana güvenin!] Ancak bu hata yüzünden olmasa da yine de ASLR desteğini kaldırmamız gerekecekti, yoksa IDA'da öğrendiğimiz adresi bellekte aynı adreste bulamayacaktık
  • 36. ANALİZ DİNAMİK ANALİZ [Import Address Table] Unpack edilmiş zararlı yazılımımıza PEView ile göz attığımızda Image Optional Header içinde bulunan DLL Characteristics alanında ASLR desteği bulunduğunu görebiliriz [Dynamic Base özelliği] OS Loader bu özelliği dikkate alarak uygulamayı ASLR ile belleğe yükler. Bundan kaçınmak için uygulamanın ASLR'ı desteklemediğini belirtmemiz lazım. Bu alanın dosya içindeki offset'inin 0x176 byte'ta olduğunu PEView'ın pFile adres formatı ile görebiliriz.
  • 37. ANALİZ DİNAMİK ANALİZ [Import Address Table] Uygulama dosyasını yamalamak için 010 Editör'le dosyayı açmadan önce Immunity Debugger ve PEView'ı kapatalım, aksi takdirde dosya Read Only olarak açılacaktır DLL Characteristics alanının mevcut değeri 40 81 (PEView'da little endian formatta gösterilmiştir)
  • 38. ANALİZ DİNAMİK ANALİZ [Import Address Table] 40 değerini 00 ile değiştirerek dosyamızı Save edelim
  • 39. ANALİZ DİNAMİK ANALİZ [Import Address Table] Yamamızdan sonra unpacked zararlı yazılım uygulamamızın ASLR (Dynamic Base) desteğinin kalktığını görebiliriz
  • 40. ANALİZ DİNAMİK ANALİZ [Import Address Table] Uygulamamızı bu defa sorunsuz başlatabiliriz. RegSetValueExW fonksiyonunun tam çağrıldığı noktada breakpoint koymak için [b 40298f] komutunu kullanabiliriz.
  • 41. ANALİZ DİNAMİK ANALİZ [Import Address Table] Imminuty Debugger'ın [b] düğmesiyle erişilen Breakpoints ekranına göz attığımızda breakpoint'imizin başarı ile konup konmadığını gözleyebiliriz.
  • 42. ANALİZ DİNAMİK ANALİZ [Import Address Table] Normalde çalışan uygulamamız Immunity Debugger ile çalıştırdığımızda [Division by zero] hatası aldı Shift+F9 ile kontrolü uygulamaya iade ettiğimizde de herhangi bir ilerleme gözlemleyemedik EAX register'ının hata anındaki değeri [0]
  • 43. ANALİZ DİNAMİK ANALİZ [Import Address Table] DIV instruction'ının açıklamasına baktığımızda EDX:EAX register'larındaki değerin EAX register'ı ile bölme işlemini gerçekleştirdiğini görebiliriz
  • 44. DİNAMİK ANALİZ [Import Address Table] ANALİZ Hata aldığımız noktanın öncesini Immunity Debugger'ın Disassembly penceresinden de inceleyebiliriz, ama incelememizi IDA'da yapmak istersek [Jump to address] aracılığıyla ilgili adrese gidebiliriz
  • 45. DİNAMİK ANALİZ [Import Address Table] ANALİZ Hatanın alındığı [0x401D8A] adresine gidelim
  • 46. DİNAMİK ANALİZ [Import Address Table] ANALİZ [div eax] instruction'ından hemen önceki satıra bakarsak [xor eax, eax] instruction'ı ile EAX register'ının değerinin 0'landığını görebiliriz. Bu bilgi 0'a bölme hatasının kasten oluşturulduğu şüphesini doğuruyor. Bu satırdan hemen önce de yeni bir Exception Handler belirlenmiş. Uygulama çalışırken bu handler hatayı ele alıyor olmalı, ancak Immunity kontrolü uygulamaya devrettiğinde aynı durum gerçekleşmiyor.
  • 47. HATA ALDIRMA ÖRNEĞİ ANTI-DEBUGGING YÖNTEMLERİ ImmunityDebugger'ın Options / Debugging options / Exceptions penceresinde istediğimiz hata kodları için kontrolün otomatik olarak uygulamaya devredilmesi ayarını yapabiliriz
  • 48. HATA ALDIRMA ÖRNEĞİ ANTI-DEBUGGING YÖNTEMLERİ Tam hata kodunu öğrenmek için bu ekrandaki "Add last exception" düğmesini kullanabiliriz, veya bir aralık tanımlayarak 0 – FFFFFFFF aralığındaki tüm exception'ları göz ardı ettirebiliriz.
  • 49. HATA ALDIRMA ÖRNEĞİ ANTI-DEBUGGING YÖNTEMLERİ ImmunityDebugger'ın bu özelliğini kullanarak Exception'ı uygulamaya aktarma denememiz başarılı olamadı.
  • 50. ANTI-DEBUGGING YÖNTEMLERİ AMAÇ • Anti-Debugging yöntemleri ile zararlı yazılım geliştiren taraf dinamik analizi zorlaştırmak ister. • Ancak hemen her durumda bu kontrolün tespiti ve uygulama yamalanarak (debug kontrolü yapan instruction'ların NOP instruction'ları ile etkisiz hale getirilmesiyle) atlatılması mümkündür. • Bu kontrollerin uygulandığı noktalar tespit edildikten sonra dinamik analiz sırasında bu noktalarda registry değerleri veya belleğe manuel müdahale etme veya bu debugger'ların sağladığı bazı atlatma imkanlarının kullanılması da anti- debugging engellerini atlatmak için kullanılabilir.
  • 51. ANTI-DEBUGGING YÖNTEMLERİ ÖRNEKLER API Metodları • [IsDebuggerPresent()] – PEB bloğundaki BeingDebugged byte'ının değerini kontrol eder • [CheckRemoteDebuggerPresent(GetCurrentProcess(), &isDebuggerPresent)] – Mevcut proses'imizin handle'ını kullarak debug edilip edilmediğini test eder • [NtQueryInformationProcess(...)] – Debug Flag'lerini verilen değişken referansına döndürür • [OutputDebugString(L"test")/GetLastError()] – proses debug edilmiyorsa GetLastError ile dönen hata kodu değişecektir • [DebugActiveProcess(pid)] – Eğer proses zaten debug ediliyorsa hata döndürecektir
  • 52. ANTI-DEBUGGING YÖNTEMLERİ ÖRNEKLER Manuel Kontrol Yöntemleri • Debugger uygulama varlığını arama: [FindWindow(L"OLLYDBG",0)] fonksiyonu ile aktif uygulamaların adlarını inceleme, registry 'yi veya dosya sistemini debugger varlığını keşfetmek için tarama • Manuel olarak PEB bloğu içindeki BeingDebugged değerini arama
  • 53. ANTI-DEBUGGING YÖNTEMLERİ ÖRNEKLER Breakpoint Arama ve Kod Bütünlüğünü Test Etme • Software breakpoint ve yama tespiti: Belli bir kod bölümünün byte'larını basit bir biçimde bir byte'lık bir değişkene ekleyerek hesaplanan değer önceden hesaplanmış bir değerle karşılaştırılabilir. Veya her bir byte bir değerle XOR'lanarak 0xCC olup olmadığı test edilebilir (ör: [0xCC XOR 0x55 == 0x99]) • Hardware breakpoint tespiti: [GetThreadContext(hnd, &ctx)] fonksiyonuyla DR0, DR1, DR2, DR3 register değerlerini içeren context veri yapısı incelenebilir.
  • 54. ANTI-DEBUGGING YÖNTEMLERİ ÖRNEKLER Zaman Aralıklarını Ölçme • [GetTickCount() ], [timeGetTime()] gibi fonksiyonlarla art arda ölçülen zaman değerleri arasındaki fark test edilerek proses'in debug edilip edilmediği anlaşılmaya çalışılır.
  • 55. ANTI-DEBUGGING YÖNTEMLERİ UYGULAMANIN YAMALANMASI Debug etmemizi engelleyen bu durumu aşmak için hata alan satırı NOP instruction'ı ile yamalayacağız. Bunun için önce Options / IDA Options / Disassembly menüsünde "Number of opcode bytes" değerini 8 yaparak Opcode'ların görünür olmasını sağlayalım.
  • 56. ANTI-DEBUGGING YÖNTEMLERİ UYGULAMANIN YAMALANMASI "div eax" instruction'ının opcode'larının "F7 F0" olduğunu görebiliyoruz. Bu instruction'ın VA adresi de 0x401D8A
  • 57. ANTI-DEBUGGING YÖNTEMLERİ UYGULAMANIN YAMALANMASI Hex View'a geçtiğimizde seçtiğimiz instruction'ı Hex veriler arasında da görebiliriz
  • 58. ANTI-DEBUGGING YÖNTEMLERİ UYGULAMANIN YAMALANMASI IDA Pro'nun güncel versiyonunda disk üzerindeki dosyanın yamalanması imkanı var. Ne yazık ki ücretsiz versiyon olan IDA Pro 5'te "Patch program" seçeneği bulunmuyor.
  • 59. ANTI-DEBUGGING YÖNTEMLERİ UYGULAMANIN YAMALANMASI Uygulamayı IDA'da yamalayamadığımız için VA ve dosya offset dönüşümünü PEView ile yapmaya çalışacağız. Bunun için önce VA adresi olarak 0x401D8A adresinin bulunduğu yeri bulalım. Yamalanacak olan [F7 F0] byte'ları işaretlenen satırın 11. ve 12. byte'ları.
  • 60. ANTI-DEBUGGING YÖNTEMLERİ UYGULAMANIN YAMALANMASI PEView'ın adres formatını File Offset'e getirdiğimizde yamalayacağımız adresin 0x118A'da bulunduğunu görebiliriz.
  • 61. ANTI-DEBUGGING YÖNTEMLERİ UYGULAMANIN YAMALANMASI Yamayı 010 Editör'le veya farklı bir Hex editörle uygulayabiliriz.
  • 62. ANTI-DEBUGGING YÖNTEMLERİ UYGULAMANIN YAMALANMASI Yamalanacak [F7 F0] byte'larını [90 90] yani NOP NOP instruction'ları ile yamalayalım.
  • 64. ANTI-DEBUGGING YÖNTEMLERİ UYGULAMANIN YAMALANMASI Yamalanmış uygulamayı tekrar IDA Pro'da açarak yamayı gerçekleştirdiğimiz adrese gidelim.
  • 65. ANTI-DEBUGGING YÖNTEMLERİ UYGULAMANIN YAMALANMASI Daha önce "div eax" instruction'ının bulunduğu yerde "nop nop" instruction'larının bulunduğunu görebiliriz.
  • 67. ANALİZ DİNAMİK ANALİZ [Import Address Table] Uygulama sonlandı ancak registry değerinin atandığı instruction çalışmadı. Böyle bir durum zararlının daha önce bu sistem üzerinde çalışmış olması nedeniyle tekrar sisteme bulaşmamak istemesinden kaynaklanmış olabilir. Bu nedenle infection öncesi SnapShot'a dönerek uygulamayı tekrar denemekte fayda var.
  • 68. ANALİZ DİNAMİK ANALİZ [Import Address Table] Kurban sistemi kurulumlar sonrası aldığımız snapshot'a döndürdüğümüzde üzerinde çalıştığımız ve yamaladığımız zararlı kopyalarını da kaybedeceğiz. Bunun için snapshot'a dönmeden önce yamayı uyguladığımız fatura_pdf-decompress.exe dosyasını Host bilgisayarımıza kopyalayalım.
  • 69. ANALİZ DİNAMİK ANALİZ [Import Address Table] Kurban sistemimizi "Kurulum Sonrası" snapshot'umuza döndürelim.
  • 70. ANALİZ DİNAMİK ANALİZ [Import Address Table] Kurban sistemimiz kurulumlar sonrasında henüz zararlı yazılımı çalıştırmadan önceki haline dönecektir.
  • 71. ANALİZ DİNAMİK ANALİZ [Import Address Table] Host bilgisayarımıza aldığımız Anti-Debug amaçlı kod bölümünü yamaladığımız "fatura_pdf-decompress.exe" dosyasını Host bilgisayardan kopyalayalım.
  • 72. ANALİZ DİNAMİK ANALİZ [Import Address Table] "fatura_pdf-decompress.exe" dosyamızı kurban bilgisayara kopyalayalım.
  • 73. ANALİZ DİNAMİK ANALİZ [Import Address Table] "fatura_pdf-decompress.exe" dosyasını Immunity Debugger ile başlatalım. Başlatır başlatmaz da 0x40298F adresine breakpoint koyalım.
  • 74. ANALİZ DİNAMİK ANALİZ [Import Address Table] Uygulamayı devam ettirdiğimizde PDF dosyasının görüntülendiğini görüyoruz. Bu davranış son denememizden farklı, muhtemelen uygulama daha önceden bulaşmadığı bir sistem üzerinde bu şekilde davranıyor. Uygulama tanımladığımız breakpoint adresinde durdu.
  • 75. ANALİZ DİNAMİK ANALİZ [Import Address Table] RegSetValueExW fonksiyonu çağrılmadan hemen önce Stack'te bu fonksiyona verilen parametreleri görebiliriz. Bunlardan "ValueName" parametresi Registry değerini ifade ediyor
  • 76. ANALİZ DİNAMİK ANALİZ [Import Address Table] MSDN'den edindiğimiz bilgiye göre RegSetValueEx fonksiyonuna verilen 5. parametre Registry değerine atanacak veriye işaret eden bir pointer
  • 77. ANALİZ DİNAMİK ANALİZ [Import Address Table] ImmunityDebugger'ın Buffer olarak adlandırdığı bu alanda belirtilen adrese giderek atanan veriyi gözlemlemek için sol alt bölümdeki Memory Dump alanında sağ klikleyerek "Go to" / "Expression" seçeneğini seçelim.
  • 78. ANALİZ DİNAMİK ANALİZ [Import Address Table] Buffer'ın stack'te tutulduğu adresi çıkan kutuya yazalım
  • 79. ANALİZ DİNAMİK ANALİZ [Import Address Table] Bu adreste bulunan Unicode string'i biraz daha rahat gözlemleyebilmek için dump alanında sağ klikleyerek "Hex / UNICODE (16 bytes)" seçeneğini işaretleyelim.
  • 80. ANALİZ DİNAMİK ANALİZ [Import Address Table] Bu alanda bir exe dosya adı görüyoruz. SORU: Burada gözlemlediğimiz dosya adını daha önce nerede gözlemlemiştik?
  • 81. ANALİZ DİNAMİK ANALİZ [Import Address Table] hKey handle'ının hangi registry key'ine ait olduğunu anlamak için daha yukarıda çağrılan RegOpenKeyExW fonksiyonunun çağrıldığı yere breakpoint koymamız lazım. Tabi bunun için sanal makinemizi yine kurulumlar sonrası snapshot'ımıza döndürmeyi unutmamalıyız.
  • 82. EGZERSİZ DİNAMİK ANALİZ [Import Address Table] • Import Address Table'da ilginç bulduğunuz fonksiyonlar için Immunity Debugger ile benzer analizleri yapınız. • Fonksiyonun çağrıldığı adrese breakpoint koyunuz ve stack'te fonksiyon için hazırlanmış olan parametreleri inceleyiniz. Parametreler hakkında detaylı bilgi için MSDN'e başvurunuz. • Tespitlerinizi bu noktaya kadar yapmış olduğumuz strings analizleri ve capturebat ile yaptığımız dinamik analiz sonuçları ile birlikte değerlendiriniz. • Daha ileri statik ve dinamik analiz yapabilmek için gerekli X86 temel bilgileri üzerinde sonraki bölümde durulacaktır.
  • 83. X86 MİMARİSİNE GİRİŞ İNCELEYECEĞİMİZ UYGULAMA PE dosya formatını da inceleme için kullandığımız bu basit C uygulamasından derlenmiş kodu Immunity Debugger üzerinde incelerken temel X86 bilgilerine değineceğiz.
  • 84. X86 MİMARİSİNE GİRİŞ ANA KONULAR VE KAVRAMLAR Daha Önce Değindiklerimiz • Derleme ve linkleme • OS Loader'ın uygulamayı belleğe yüklemesi • Executable imajı, DLL modülleri, Stack ve Heap alanlarının bellekteki konumları [ASLR konusuyla bağlantıları] • Virtual Address kavramı
  • 85. X86 MİMARİSİNE GİRİŞ ANA KONULAR VE KAVRAMLAR (DEVAMI) Bu Bölümde Değineceklerimiz • Register'lar ve kullanım amaçları • X86 instruction set'i • Stack alanının kullanımı [fonksiyon çağırma, fonksiyon içindeki ve fonksiyondan çıkış işlemleri sırasındaki olaylar] • Calling conventions [fonksiyon çağırma sırasında parametrelerin fonksiyona aktarım yöntemleri, fonksiyon dönüşünde stack'i temizleme görevleri]
  • 86. X86 MİMARİSİNE GİRİŞ X86 hakkındaki teorik bilgiler üzerinde daha sonrak konuşmak üzere, öncelikle uygulamamızın Makine Kodu seviyesindeki işleyişini inceleyelim. Öncelikle main() fonksiyonu içindeki ilk instruction'ın adresini öğrenmek için Visual Studio'nun "Go To Assembly" özelliğini kullanacağız.
  • 87. X86 MİMARİSİNE GİRİŞ Visual Studio'da Disassembly view'ına geçtiğimizde derleyicinin üreteceği Assembly kodlarının yanı sıra bunların adreslerini de görüyoruz. Bu bilgiye şu nedenle ihtiyacımız var: Derleyiciler kod üretmeye doğrudan main() fonksiyonundan başlamazlar ve Address of Entry Point'te main() fonksiyonuna işaret etmez. Ancak bizim X86 mimarisini anlama amaçlı incelememizi main() fonksiyonundan başlatmamız lazım. İlk instruction olan "push ebp" instruction'ının adresi 0x401060
  • 88. X86 MİMARİSİNE GİRİŞ Uygulama belleğe yüklendiğinde de bu adreste olacağından emin olabilmek için ASLR'ı bu ayarlarla etkisiz hale getirdik.
  • 89. X86 MİMARİSİNE GİRİŞ Address of Entry Point'e koyduğumuz breakpoint [0x401060] sonrası bir kaç defa F9 tuşuna basılarak main() fonksiyonunun başına geliyoruz.
  • 90. X86 MİMARİSİNE GİRİŞ main() fonksiyonunun ilk instruction'ları "function prologue" adı da verilen önceki fonksiyon frame pointer'ın saklanması ve mevcut stack pointer'ın yeni fonksiyonun frame pointer'ı olarak belirlenmesidir.
  • 91. X86 MİMARİSİNE GİRİŞ Stack ve Registry Değişim Özeti 0x0018FF88 [EBP] STACK DEĞİŞEN REGISTER'LAR ESP 0x0018FF40 ESP Yüksek Adres Düşük Adres Buradaki stack gösterimimiz ile Immunity Debugger'ın stack penceresindeki büyüme yönleri farklı, bu nedenle biraz kafanız karışabilir !
  • 92. X86 MİMARİSİNE GİRİŞ "function prologue"un ikinci adımında mevcut stack pointer [ESP] main() fonksiyonunun stack base pointer'ı [EBP] olarak atanıyor.
  • 93. X86 MİMARİSİNE GİRİŞ Stack ve Registry Değişim Özeti 0x0018FF88 [EBP] STACK EBP 0x0018FF40 ESP DEĞİŞEN REGISTER'LAR Yüksek Adres Düşük Adres
  • 94. X86 MİMARİSİNE GİRİŞ main() fonksiyonunun lokal değişkenleri için stack'te 12 byte'lık [0x0C] yer ayrılıyor.
  • 95. X86 MİMARİSİNE GİRİŞ Stack ve Registry Değişim Özeti 0x0018FF88 [EBP] XXXXXXXX XXXXXXXX XXXXXXXX STACK ESP 0x0018FF34 ESP DEĞİŞEN REGISTER'LAR Yüksek Adres Düşük Adres
  • 96. X86 MİMARİSİNE GİRİŞ [EBP-8] adresindeki lokal değişkene 10 [0x0A] değeri atanıyor.
  • 97. X86 MİMARİSİNE GİRİŞ Stack ve Registry Değişim Özeti 0x0018FF88 [EBP] XXXXXXXX 0x0000000A XXXXXXXX STACK ESP DEĞİŞEN REGISTER'LAR Yüksek Adres Düşük Adres
  • 98. X86 MİMARİSİNE GİRİŞ [EBP-4] adresindeki lokal değişkene 20 [0x14] değeri atanıyor.
  • 99. X86 MİMARİSİNE GİRİŞ Stack ve Registry Değişim Özeti 0x0018FF88 [EBP] 0x00000014 0x0000000A XXXXXXXX STACK ESP DEĞİŞEN REGISTER'LAR Yüksek Adres Düşük Adres
  • 100. X86 MİMARİSİNE GİRİŞ [EBP-4] adresindeki lokal değişken EAX register'ına atanıyor.
  • 101. X86 MİMARİSİNE GİRİŞ Stack ve Registry Değişim Özeti 0x0018FF88 [EBP] 0x00000014 0x0000000A XXXXXXXX STACK ESP EAX 0x00000014 DEĞİŞEN REGISTER'LAR Yüksek Adres Düşük Adres
  • 102. X86 MİMARİSİNE GİRİŞ EAX register'ının değeri Stack'e push ediliyor. Bu değer "add" fonksiyonu için bir parametre olarak kullanılacak.
  • 103. X86 MİMARİSİNE GİRİŞ Stack ve Registry Değişim Özeti 0x0018FF88 [EBP] 0x00000014 0x0000000A XXXXXXXX 0x00000014 [Arg 2]STACK ESP ESP 0x0018FF30 DEĞİŞEN REGISTER'LAR Yüksek Adres Düşük Adres
  • 104. X86 MİMARİSİNE GİRİŞ [EBP-8] adresindeki lokal değişken ECX register'ına atanıyor.
  • 105. X86 MİMARİSİNE GİRİŞ Stack ve Registry Değişim Özeti 0x0018FF88 [EBP] 0x00000014 0x0000000A XXXXXXXX 0x00000014 [Arg 2]STACK ESP ECX 0x0000000A DEĞİŞEN REGISTER'LAR Yüksek Adres Düşük Adres
  • 106. X86 MİMARİSİNE GİRİŞ ECX register'ının değeri Stack'e push ediliyor. Bu değer "add" fonksiyonu için bir diğer parametre olarak kullanılacak.
  • 107. X86 MİMARİSİNE GİRİŞ Stack ve Registry Değişim Özeti 0x0018FF88 [EBP] 0x00000014 0x0000000A XXXXXXXX 0x00000014 [Arg 2] 0x0000000A [Arg 1] STACK ESP ESP 0x0018FF2C DEĞİŞEN REGISTER'LAR Yüksek Adres Düşük Adres
  • 108. X86 MİMARİSİNE GİRİŞ Immunity Debugger debug sembollerine sahip olduğu bir executable için bize fonksiyon adı ve bu fonksiyona verilen parametrelerle ilgili bilgi sağlıyor.
  • 109. X86 MİMARİSİNE GİRİŞ "call add" instruction'ı çalıştığında EIP değeri add fonksiyonuna işaret edecek şekilde değişiyor, ancak main() fonksiyonu içindeki bir sonraki instruction'ın adresi stack'e yazılıyor.
  • 110. X86 MİMARİSİNE GİRİŞ Stack ve Registry Değişim Özeti 0x0018FF88 [EBP] 0x00000014 0x0000000A XXXXXXXX 0x00000014 [Arg 2] 0x0000000A [Arg 1] 0x00401081 [EIP] STACK ESP ESP 0x0018FF28 DEĞİŞEN REGISTER'LAR Yüksek Adres Düşük Adres
  • 111. X86 MİMARİSİNE GİRİŞ add() fonksiyonunun prologue'unın ilk instruction'ı çalıştığında main() fonksiyonunun stack base pointer'ı stack'e yazılıyor.
  • 112. X86 MİMARİSİNE GİRİŞ Stack ve Registry Değişim Özeti 0x0018FF88 [EBP] 0x00000014 0x0000000A XXXXXXXX 0x00000014 [Arg 2] 0x0000000A [Arg 1] 0x00401081 [EIP] 0x0018FF40 [EBP] STACK ESP ESP 0x0018FF24 DEĞİŞEN REGISTER'LAR Yüksek Adres Düşük Adres
  • 113. X86 MİMARİSİNE GİRİŞ add() fonksiyonunun prologue'unın ikinci instruction'ı çalıştığında ESP register'ının değeri add() fonksiyonunun stack base pointer'ına [EBP] yazılıyor.
  • 114. X86 MİMARİSİNE GİRİŞ Stack ve Registry Değişim Özeti 0x0018FF88 [EBP] 0x00000014 0x0000000A XXXXXXXX 0x00000014 [Arg 2] 0x0000000A [Arg 1] 0x00401081 [EIP] 0x0018FF40 [EBP] STACK ESP EBP 0x0018FF24 DEĞİŞEN REGISTER'LAR Yüksek Adres Düşük Adres
  • 115. X86 MİMARİSİNE GİRİŞ add() fonksiyonu lokal değişkenler için sadece 4 byte'lık bir alan kullandığından "push ecx" instruction'ı ile stack'te yeterli alan ayrılmış oluyor.
  • 116. X86 MİMARİSİNE GİRİŞ Stack ve Registry Değişim Özeti 0x0018FF88 [EBP] 0x00000014 0x0000000A XXXXXXXX 0x00000014 [Arg 2] 0x0000000A [Arg 1] 0x00401081 [EIP] 0x0018FF40 [EBP] XXXXXXXX STACK ESP ESP 0x0018FF20 DEĞİŞEN REGISTER'LAR Yüksek Adres Düşük Adres
  • 117. X86 MİMARİSİNE GİRİŞ add() fonksiyonunun stack'te hazır bulunan birinci parametresi [EAX] register'ına atanıyor.
  • 118. X86 MİMARİSİNE GİRİŞ Stack ve Registry Değişim Özeti 0x0018FF88 [EBP] 0x00000014 0x0000000A XXXXXXXX 0x00000014 [Arg 2] 0x0000000A [Arg 1] 0x00401081 [EIP] 0x0018FF40 [EBP] XXXXXXXX STACK ESP EAX 0x0000000A DEĞİŞEN REGISTER'LAR Yüksek Adres Düşük Adres
  • 119. X86 MİMARİSİNE GİRİŞ add() fonksiyonunun stack'te hazır bulunan ikinci parametresi [EAX] register'ına [add] instruction'ı ile ekleniyor.
  • 120. X86 MİMARİSİNE GİRİŞ Stack ve Registry Değişim Özeti 0x0018FF88 [EBP] 0x00000014 0x0000000A XXXXXXXX 0x00000014 [Arg 2] 0x0000000A [Arg 1] 0x00401081 [EIP] 0x0018FF40 [EBP] XXXXXXXX STACK ESP EAX 0x0000001E DEĞİŞEN REGISTER'LAR Yüksek Adres Düşük Adres
  • 121. X86 MİMARİSİNE GİRİŞ [EAX] register'ının değeri stack'te add() fonksiyonu için ayrılmış 4 byte'lık lokal değişken alanına atanıyor. Uygulamamızı optimizasyon ayarları ile derlemiş olsaydık muhtemelen bu adımı görmeyecektik. Çünkü zaten return değeri [EAX] register'ı ile döndürülecek.
  • 122. X86 MİMARİSİNE GİRİŞ Stack ve Registry Değişim Özeti 0x0018FF88 [EBP] 0x00000014 0x0000000A XXXXXXXX 0x00000014 [Arg 2] 0x0000000A [Arg 1] 0x00401081 [EIP] 0x0018FF40 [EBP] 0x0000001E STACK ESP DEĞİŞEN REGISTER'LAR Yüksek Adres Düşük Adres
  • 123. X86 MİMARİSİNE GİRİŞ Bu adımda gereksiz bir biçimde lokal değişken tekrar [EAX] register'ına atanıyor. Ancak register değeri zaten aynı olduğu için değişmiyor.
  • 124. X86 MİMARİSİNE GİRİŞ Stack ve Registry Değişim Özeti 0x0018FF88 [EBP] 0x00000014 0x0000000A XXXXXXXX 0x00000014 [Arg 2] 0x0000000A [Arg 1] 0x00401081 [EIP] 0x0018FF40 [EBP] 0x0000001E STACK ESP DEĞİŞEN REGISTER'LAR Yüksek Adres Düşük Adres
  • 125. X86 MİMARİSİNE GİRİŞ add() fonksiyonun epilogue'unun ilk adımında add() fonksiyonunun stack base pointer'ı [ESP] register'ına atanıyor. Bu adımda add() fonksiyonu için stack'ten almış olduğumuz alan geri veriliyor.
  • 126. X86 MİMARİSİNE GİRİŞ Stack ve Registry Değişim Özeti 0x0018FF88 [EBP] 0x00000014 0x0000000A XXXXXXXX 0x00000014 [Arg 2] 0x0000000A [Arg 1] 0x00401081 [EIP] 0x0018FF40 [EBP] 0x0000001E STACK ESP 0x0018FF24 ESP DEĞİŞEN REGISTER'LAR Yüksek Adres Düşük Adres
  • 127. X86 MİMARİSİNE GİRİŞ add() fonksiyonun epilogue'unun ikinci adımında main() fonksiyonunun stack'te saklanmış olan [EBP] register değeri tekrar yükleniyor. pop instruction'ı ile birlikte stack de 4 byte daha azaltılmış oluyor.
  • 128. X86 MİMARİSİNE GİRİŞ Stack ve Registry Değişim Özeti 0x0018FF88 [EBP] 0x00000014 0x0000000A XXXXXXXX 0x00000014 [Arg 2] 0x0000000A [Arg 1] 0x00401081 [EIP] 0x0018FF40 [EBP] 0x0000001E STACK EBP 0x0018FF40 ESP 0x0018FF28 ESP DEĞİŞEN REGISTER'LAR Yüksek Adres Düşük Adres
  • 129. X86 MİMARİSİNE GİRİŞ "retn" instruction'ı çalıştığında stack'in en üstünde bulunan saklanmış [EIP] değeri "pop" edilecek ve uygulama akışı bu adresten devam edecektir.
  • 130. X86 MİMARİSİNE GİRİŞ "retn" instruction'ı çalıştığında sadece saklanmış EIP değerine atlamıyoruz aynı zamanda stack'de 4 byte küçültülmüş oluyor.
  • 131. X86 MİMARİSİNE GİRİŞ Stack ve Registry Değişim Özeti 0x0018FF88 [EBP] 0x00000014 0x0000000A XXXXXXXX 0x00000014 [Arg 2] 0x0000000A [Arg 1] 0x00401081 [EIP] 0x0018FF40 [EBP] 0x0000001E STACK ESP 0x0018FF2C ESP DEĞİŞEN REGISTER'LAR Yüksek Adres Düşük Adres
  • 132. X86 MİMARİSİNE GİRİŞ "add esp, 8" instruction'ı ile stack'te add() fonksiyon parametreleri için kullanmış olduğumuz 8 byte'lık alanı geri veriyoruz. Bu işlemde çağıran [caller] stack'i temizliyor.
  • 133. X86 MİMARİSİNE GİRİŞ Stack ve Registry Değişim Özeti 0x0018FF88 [EBP] 0x00000014 0x0000000A XXXXXXXX 0x00000014 [Arg 2] 0x0000000A [Arg 1] 0x00401081 [EIP] 0x0018FF40 [EBP] 0x0000001E STACK ESP 0x0018FF34 ESP DEĞİŞEN REGISTER'LAR Yüksek Adres Düşük Adres
  • 134. X86 MİMARİSİNE GİRİŞ [EAX] register'ında bulunan toplama işlemi sonucu main() fonksiyonunun lokal değişkenine atanıyor.
  • 135. X86 MİMARİSİNE GİRİŞ Stack ve Registry Değişim Özeti 0x0018FF88 [EBP] 0x00000014 0x0000000A 0x0000001E 0x00000014 [Arg 2] 0x0000000A [Arg 1] 0x00401081 [EIP] 0x0018FF40 [EBP] 0x0000001E STACK ESP DEĞİŞEN REGISTER'LAR Yüksek Adres Düşük Adres
  • 136. X86 MİMARİSİNE GİRİŞ Lokal değişkenimizde bulunan toplama sonucu [EDX] register'ına atanıyor.
  • 137. X86 MİMARİSİNE GİRİŞ Stack ve Registry Değişim Özeti 0x0018FF88 [EBP] 0x00000014 0x0000000A 0x0000001E 0x00000014 [Arg 2] 0x0000000A [Arg 1] 0x00401081 [EIP] 0x0018FF40 [EBP] 0x0000001E STACK EDX 0x0000001E ESP DEĞİŞEN REGISTER'LAR Yüksek Adres Düşük Adres
  • 138. X86 MİMARİSİNE GİRİŞ Optimizasyon uygulamadığımız için printf() fonksiyonunun ikinci parametresi olarak (parametreler yine sağdan sola doğru stack'e yazılıyor) [EDX] register'ında bulunan toplam değerini stack'e yazıyoruz (halbuki bu değer zaten stack'te mevcuttu)
  • 139. X86 MİMARİSİNE GİRİŞ Stack ve Registry Değişim Özeti 0x0018FF88 [EBP] 0x00000014 0x0000000A 0x0000001E 0x0000001E [Arg 2] 0x0000000A [Arg 1] 0x00401081 [EIP] 0x0018FF40 [EBP] 0x0000001E STACK ESP 0x0018FF30 ESP DEĞİŞEN REGISTER'LAR Yüksek Adres Düşük Adres Buradaki Arg 2 printf()'in ikinci parametresi
  • 140. X86 MİMARİSİNE GİRİŞ Bu instruction'da printf() fonksiyonu için format string'in bulunduğu adresi stack'e yazıyoruz. Stack penceresinde bu değerin Sonuc = "%d" olduğunu görebiliriz.
  • 141. X86 MİMARİSİNE GİRİŞ Stack ve Registry Değişim Özeti 0x0018FF88 [EBP] 0x00000014 0x0000000A 0x0000001E 0x0000001E [Arg 2] 0x00403000 [Arg 1] 0x00401081 [EIP] 0x0018FF40 [EBP] 0x0000001E STACK ESP 0x0018FF2C ESP DEĞİŞEN REGISTER'LAR Yüksek Adres Düşük Adres
  • 142. X86 MİMARİSİNE GİRİŞ printf() fonksiyonu çağrılmadan önce konsol penceresini görünteleyelim ve henüz birşey yazılmadığını görelim.
  • 143. X86 MİMARİSİNE GİRİŞ printf fonksiyonunun içine girmeden "step over" şeklinde bu fonksiyonu çalıştırıyoruz, çünkü bu API fonksiyonunu incelemek istemiyoruz. Bu çağrıdan sonra Sonuc = 30 ifadesini görmemizin yanında ilginç olan bir nokta [EAX], [ECX] ve [EDX] register'larımızın değişmiş olması.
  • 144. X86 MİMARİSİNE GİRİŞ Stack ve Registry Değişim Özeti 0x0018FF88 [EBP] 0x00000014 0x0000000A 0x0000001E 0x0000001E [Arg 2] 0x00403000 [Arg 1] 0x00401081 [EIP] 0x0018FF40 [EBP] 0x0000001E STACK EAX 0x0018FF2C ECX 0x0018FF2C EDX 0x0018FF2CESP DEĞİŞEN REGISTER'LAR Yüksek Adres Düşük Adres "caller saved" registers kavramına "calling conventions" bölümünde değineceğiz.
  • 145. X86 MİMARİSİNE GİRİŞ printf() fonksiyonuna verilen parametreler için tüketilen stack alanı geri veriliyor.
  • 146. X86 MİMARİSİNE GİRİŞ Stack ve Registry Değişim Özeti 0x0018FF88 [EBP] 0x00000014 0x0000000A 0x0000001E 0x0000001E [Arg 2] 0x00403000 [Arg 1] 0x00401081 [EIP] 0x0018FF40 [EBP] 0x0000001E STACK ESP 0x0018FF34 ESP DEĞİŞEN REGISTER'LAR Yüksek Adres Düşük Adres
  • 147. X86 MİMARİSİNE GİRİŞ getchar() API fonksiyonunun çalışabilmesi için konsol penceresinden bir girdi vermemiz gerekecek. Bu yüzden "step over" komutu ile bir instruction daha atlamaya çalıştıktan sonra konsolu tekrar ön plana alalım.
  • 148. X86 MİMARİSİNE GİRİŞ Konsol penceresinde "Enter" tuşuna bastıktan sonra getchar() fonksiyonu tamamlanarak dönüyor. [ECX] ve [EDX] register'larının değiştiğini gözlemliyoruz.
  • 149. X86 MİMARİSİNE GİRİŞ Stack ve Registry Değişim Özeti 0x0018FF88 [EBP] 0x00000014 0x0000000A 0x0000001E 0x0000001E [Arg 2] 0x00403000 [Arg 1] 0x00401081 [EIP] 0x0018FF40 [EBP] 0x0000001E STACK ECX 0x683D60B0 EDX 0x0000000A ESP DEĞİŞEN REGISTER'LAR Yüksek Adres Düşük Adres
  • 150. X86 MİMARİSİNE GİRİŞ main() fonksiyonundan çıkmadan önce [EAX] register'ı return değeri olarak "0"lanmak amacıyla kendisiyle XOR'lanıyor.
  • 151. X86 MİMARİSİNE GİRİŞ Stack ve Registry Değişim Özeti 0x0018FF88 [EBP] 0x00000014 0x0000000A 0x0000001E 0x0000001E [Arg 2] 0x00403000 [Arg 1] 0x00401081 [EIP] 0x0018FF40 [EBP] 0x0000001E STACK EAX 0x00000000 ESP DEĞİŞEN REGISTER'LAR Yüksek Adres Düşük Adres
  • 152. X86 MİMARİSİNE GİRİŞ main() fonksiyonundan çıkmadan önce epilogue adımlarından main() fonksiyonu için alınmış olan stack alanını geri veren "mov esp, ebp" instruction'ı çalıştırılıyor.
  • 153. X86 MİMARİSİNE GİRİŞ Stack ve Registry Değişim Özeti 0x0018FF88 [EBP] 0x00000014 0x0000000A 0x0000001E 0x0000001E [Arg 2] 0x00403000 [Arg 1] 0x00401081 [EIP] 0x0018FF40 [EBP] 0x0000001E STACK ESP 0x0018FF40 ESP DEĞİŞEN REGISTER'LAR Yüksek Adres Düşük Adres
  • 154. X86 MİMARİSİNE GİRİŞ main() fonksiyonu 2. epilogue adımında main() fonksiyonunu çağıran bir üst fonksiyonun [EBP] register'ı restore ediliyor.
  • 155. X86 MİMARİSİNE GİRİŞ Stack ve Registry Değişim Özeti 0x0018FF88 [EBP] 0x00000014 0x0000000A 0x0000001E 0x0000001E [Arg 2] 0x00403000 [Arg 1] 0x00401081 [EIP] 0x0018FF40 [EBP] 0x0000001E STACK EBP 0x0018FF88 ESP 0x0018FF44 ESP DEĞİŞEN REGISTER'LAR Yüksek Adres Düşük Adres
  • 156. X86 MİMARİSİNE GİRİŞ main() fonksiyonunun sonunda "retn" instruction'ı çalıştığında saklanmış olan [EIP] adresinden uygulama akışı devam ediyor.
  • 157. X86 MİMARİSİNE GİRİŞ Uygulamanın devam etmesine izin verdiğimizde "0" exit değeri ile sonlandığını görüyoruz.
  • 158. X86 MİMARİSİNE GİRİŞ İNCELEYEDİĞİMİZ UYGULAMA Assembly kodlarının üzerinden geçtikten sonra kaynak kodumuzu tekrar hatırlamak isteyebilirsiniz. (Aslında her aşamada bu kaynak koda göz atmak disassembly'yi anlamak için size yardımcı olabilir.)
  • 159. X86 MİMARİSİNE GİRİŞ REGISTER'LAR VE KULLANIM AMAÇLARI EIP [Extended Instruction Pointer] Bir sonra çalışacak olan instruction’ın adresi (sadece makine tarafından değiştirilir) EBP [Extended Base Pointer] ve ESP [Extended Stack Pointer] İçinde bulunulan fonksiyonun stack frame’inin taban ve tavan adreslerini barındıran register’lar EAX, EBX, ECX, EDX, ESI, EDI Genel amaçlı register’lar (ancak geleneksel olarak belli amaçlarla kullanılabilirler) EFLAGS Çeşitli instruction’lar tarafından etkilenen ve kullanılan bayrakları barındıran 32 bit’lik bir register
  • 160. X86 MİMARİSİNE GİRİŞ REGISTER'LAR VE KULLANIM AMAÇLARI • EAX – Accumulator Register: Genellikle fonsiyonların return değerlerini tutar. Hesaplamaların sonuçları da genellikle bu register'da tutulur. • EBX – Base Register: Genellikle belli bir özel amaç için kullanılmaz. • ECX – Counter Register: Genellikle döngülerde ve string işlemlerinde sayaç değişkenini (yani meşhur "i" değerini) tutmak için kullanılır. • EDX – Data Register: Çarpma ve bölme gibi işlemlerde EAX'in yetersiz kalması nedeniyle işlem sonuçlarının most significant bit'lerini tutmak için kullanılır. • ESI – Source Index: Genellikle string yazma işlemlerinde kopyalanacak string'den okunacak adresi tutar (read pointer). • EDI – Destination Index: Genellikle string yazma işlemlerinde yazılacak adresi tutar (write pointer). Önemli: ESP ve EBP register'ları ile birlikte yukarıdaki genel amaçlı register'lar assembly yazan uygulama geliştirici veya derleyici tarafından istenildiği gibi kullanılabilir. Ancak yukarıda belirtilen kullanımlar geleneksel kullanımlardır.
  • 161. X86 MİMARİSİNE GİRİŞ REGISTER'LAR VE KULLANIM AMAÇLARI EAX EBX ECX EDX AX BX CX DX 078151631 32 Bit Register'lar 16 Bit Register'lar 8 Bit Register'lar Bu bölümleme sadece EAX, EBX, ECX ve EDX'e özeldir
  • 162. X86 MİMARİSİNE GİRİŞ X86 ASSEMBLY GİRİŞ Assembly Syntax'ları Intel AT&T Prefix'ler mov eax, 1 movl $1, %eax Operand yönü instr dest, source instr source, dest Bellek operand'ları mov eax, [ebx] movl (%ebx), %eax Suffix'ler mov al, bl movb %bl, %al
  • 163. X86 MİMARİSİNE GİRİŞ X86 ASSEMBLY GİRİŞ Bellek adresleme yöntemleri Instruction Anlamı mov eax, [ebx] EBX register'ının içerdiği adresteki 4 byte'lık değeri EAX register'ına atama mov [var], ebx EBX register'ının değerini 32bit'lik bir değişkenin içerdiği adrese yazma mov eax, [esi-4] ESI + (-4) adresindeki 4 byte'lık değeri EAX register'ına atama mov [esi+eax], cl CL register'ının taşıdığı bir byte'lık değeri ESI+EAX adresine yazma mov edx, [esi+4*ebx] ESI+4*EBX adresinde bulunan 4 byte'lık değeri EDX register'ına atama
  • 164. X86 MİMARİSİNE GİRİŞ X86 ASSEMBLY GİRİŞ Size Directive'leri Register adlarının geçtiği instruction'lardan okunacak ve/veya yazılacak verinin büyüklüğü anlaşılabilir. Ancak immediate (sabit) verilerin yazıldığı durumlarda yazılacak verinin kaplayacağı alanın belirtilmesi gerekir. Instruction Anlamı mov BYTE PTR [ebx], 2 2 sabit değerini EBX register'ında saklı adresteki 1 byte'lık alan yaz mov WORD PTR [ebx], 2 2 sabit değerinin 16 bit'lik gösterimini EBX register'ında saklı adresten başlayan 2 byte'lık alana yaz mov DWORD PTR [ebx], 2 2 sabit değerinin 32 bit'lik gösterimini EBX register'ında saklı adresten başlayan 2 byte'lık alana yaz
  • 165. X86 MİMARİSİNE GİRİŞ X86 ASSEMBLY GİRİŞ Instruction'lar Şu ana kadar pek çok assembly instruction'ı ile karşılaştık. Açıkçası belli bir instruction set'i kullanılan veya derleyicilerin ürettiği assembly kodlarının önemli bir bölümünü kapsar. Bu bölümde daha önce de karşılaştığımız çok kullanılan Assembly Instruction'larının üzerinden geçeceğiz.
  • 166. X86 MİMARİSİNE GİRİŞ X86 ASSEMBLY GİRİŞ Instruction'lar [Data Movement Instruction'ları] mov Move (Opcodes: 88, 89, 8A, 8B, 8C, 8E, ...) Bellekten belleğe mov instruction'ı ile veri kopyalamak mümkün değildir. Syntax mov <reg>,<reg> mov <reg>,<mem> mov <mem>,<reg> mov <reg>,<imm> mov <mem>,<imm>
  • 167. X86 MİMARİSİNE GİRİŞ X86 ASSEMBLY GİRİŞ Instruction'lar [Data Movement Instruction'ları] push Push stack (Opcodes: FF, 89, 8A, 8B, 8C, 8E, ...) Syntax push <reg32> push <mem> push <imm32>
  • 168. X86 MİMARİSİNE GİRİŞ X86 ASSEMBLY GİRİŞ Instruction'lar [Data Movement Instruction'ları] pop Pop stack Syntax pop <reg32> pop <mem>
  • 169. X86 MİMARİSİNE GİRİŞ X86 ASSEMBLY GİRİŞ Instruction'lar [Data Movement Instruction'ları] lea Load effective address Bu instruction diğerlerine nazaran biraz kafa karıştırıcı olabilir. "lea" instruction'ın da kaynak değer mutlaka köşeli parantezler arasındadır, ancak "mov" instruction'ı için bu köşeli parantezler arasında adresi bulunan bellek alanındaki değer anlamına gelirken "lea" instruction'ı doğrudan adres değerini kullanır. Bu imkan zaman zaman adres bilgisini kullanmaktan ziyade hesaplama amacıyla kullanılmaktadır. Örnek lea edi, [ebx+4*esi] - EBX+4*ESI hesaplamasının sonucu EDI register'ına atanır
  • 170. X86 MİMARİSİNE GİRİŞ X86 ASSEMBLY GİRİŞ Instruction'lar [Aritmetik ve Mantık Instruction'ları] add Integer Addition Toplama instruction'ında en fazla bir operand bellek alanı olabilir. Syntax add <reg>,<reg> add <reg>,<mem> add <mem>,<reg> add <reg>,<imm> add <mem>,<imm>
  • 171. X86 MİMARİSİNE GİRİŞ X86 ASSEMBLY GİRİŞ Instruction'lar [Aritmetik ve Mantık Instruction'ları] sub Integer Subtraction Toplama instruction'ında olduğu gibi çıkarma instruction'ında da en fazla bir operand bellek alanı olabilir. Syntax sub <reg>,<reg> sub <reg>,<mem> sub <mem>,<reg> sub <reg>,<imm> sub <mem>,<imm>
  • 172. X86 MİMARİSİNE GİRİŞ X86 ASSEMBLY GİRİŞ Instruction'lar [Aritmetik ve Mantık Instruction'ları] inc, dec Increment, Decrement Artırma instruction'ı registry veya bellek alanını bir artırırken azaltma instruction'ı da tam tersini gerçekleştirir. Syntax inc <reg> inc <mem> dec <reg> dec <mem>
  • 173. X86 MİMARİSİNE GİRİŞ X86 ASSEMBLY GİRİŞ Instruction'lar [Aritmetik ve Mantık Instruction'ları] imul Integer Multiplication 2 veya 3 operand'la çalışır. 2 operand'lı kullanımda iki değer çarpılıp sonuç birinci operand'da saklanır. 3 operand'lı kullanımda 2. ve 3. operand'lar çarpılıp sonuç birinci operand'da saklanır. Birinci operand (destination) her zaman registry olmak zorundadır, 3 operand'lı kullanımda 3. operand her zaman bir immediate (sabit) değer olmak zorundadır. Syntax imul <reg32>,<reg32> imul <reg32>,<mem> imul <reg32>,<reg32>,<imm> imul <reg32>,<mem>,<imm>
  • 174. X86 MİMARİSİNE GİRİŞ X86 ASSEMBLY GİRİŞ Instruction'lar [Aritmetik ve Mantık Instruction'ları] idiv Integer Division EDX:EAX registerlarında bulunan 64 bit'lik integer değeri operand değerine böler. Bölüm EAX'e kalan ise EDX register'ına yazılır. Syntax idiv <reg32> idiv <mem>
  • 175. X86 MİMARİSİNE GİRİŞ X86 ASSEMBLY GİRİŞ Instruction'lar [Aritmetik ve Mantık Instruction'ları] and, or, xor Bitwise logical and, or and exclusive or Operand'lar üzerinde belirtilen işlemleri gerçekleştirdikten sonra sonucu birinci operand'a yazarlar. Syntax and <reg>,<reg> and <reg>,<mem> and <mem>,<reg> and <reg>,<imm> and <mem>,<imm> or <reg>,<reg> or <reg>,<mem> or <mem>,<reg> or <reg>,<imm> or <mem>,<imm> xor <reg>,<reg> xor <reg>,<mem> xor <mem>,<reg> xor <reg>,<imm> xor <mem>,<imm>
  • 176. X86 MİMARİSİNE GİRİŞ X86 ASSEMBLY GİRİŞ Instruction'lar [Aritmetik ve Mantık Instruction'ları] shl, shr Shift Left, Shift Right Birinci operand'ı sola veya sağa kaydırırken boşalan bit pozisyonlarına 0 yazılır. Kaç bit kaydırma yapılacağı 8 bit'lik bir immediate değerde veya CL register'ı ile verilir. Syntax shl <reg>,<imm8> shl <mem>,<imm8> shl <reg>,<cl> shl <mem>,<cl> shr <reg>,<imm8> shr <mem>,<imm8> shr <reg>,<cl> shr <mem>,<cl>
  • 177. X86 MİMARİSİNE GİRİŞ X86 ASSEMBLY GİRİŞ Instruction'lar [Akış Kontrol Instruction'ları] jmp Jump Uygulama akışını koşulsuz olarak operand ile belirtilen adrese yönlendirir. Syntax jmp <label>
  • 178. X86 MİMARİSİNE GİRİŞ X86 ASSEMBLY GİRİŞ Instruction'lar [Akış Kontrol Instruction'ları] jcondition (Conditional Jump) EFLAGS register'ında tutulan ve son aritmetik işlemin (bunlar add, sub gibi instruction'lar olabileceği gibi cmp ve test gibi çıkarma işleminin türevleri olan karşılaştırma instruction'ları da olabilir) sonuçlarına bağlı olarak uygulama akışını operand'da belirtilen adrese yönlendirir veya akışın bir sonraki instruction'dan devam etmesine izin verir. ZF - zero flag yapılan işlem veya karşılaştırmanın sonucu "0" ise "1" değerini alır. SF - sign flag yapılan işlemin sonucu negatif ise "1" değerini alır. Syntax je <label> (jump when equal) jne <label> (jump when not equal) jz <label> (jump when last result was zero) jg <label> (jump when greater than) jge <label> (jump when greater than or equal to) jl <label> (jump when less than) jle <label> (jump when less than or equal to)
  • 179. X86 MİMARİSİNE GİRİŞ X86 ASSEMBLY GİRİŞ Instruction'lar [Akış Kontrol Instruction'ları] cmp Compare CMP instruction'ı SUB instruction'ına benzer ancak çıkartma işleminin sonucu birinci operand'a yazılmaz, sadece işlemin sonucu negatif ise Sign Flag "1" olarak işaretlenir. Syntax cmp <reg>,<reg> cmp <reg>,<mem> cmp <mem>,<reg> cmp <reg>,<imm>
  • 180. X86 MİMARİSİNE GİRİŞ X86 ASSEMBLY GİRİŞ Instruction'lar [Akış Kontrol Instruction'ları] call, ret (Subroutine call and return) CALL instruction'ı operand ile verilen adrese uygulama akışını yönlendirirken bir yandan da kendisinden bir sonra gelen instruction'ın adresini STACK'e yazar, JMP instruction'ından temel farkı da budur. RET instruction'ı ise önce STACK'in o anda en üstünde bulunan adres değerini restore eder, yani uygulama akışını daha önce CALL instruction'ı ile saklanmış olan adrese yönlendirir. Dolayısıyla RET instruction'ından önce function epilog bölümü gerçekleştirilerek çalıştırılan fonksiyon için STACK'te ayrılmış olan tüm alanın SUB ESP, 0x??? instruction'ı veya benzeri bir işlem ile geri verilmiş olması gerekir. Syntax call <label> ret
  • 181. X86 MİMARİSİNE GİRİŞ STACK ALANININ KULLANIMI Stack Alanının Çalışma Mekanizması • Stack yüksek bir adresten düşük adreslere doğru büyür. • Stack'e veri yazma (PUSH) ve bu veriyi bir register'a okuyarak silme (POP) işlemi LIFO (Last In First Out) yöntemiyle stack'e veri yazılması ve silinmesine yol açar. Bu stack'teki herhangi bir alan okunarak (MOV instruction'ı ile) bir register'a atanamaz ve tam tersi şekilde bir register veya immediate değeri stack'e yazılamaz anlamına gelmez, LIFO yöntemi ile sadece stack'in alan tüketimi ve iadesine ilişkin yöntemi ifade ediyoruz. • Stack sadece PUSH instruction'ı ile büyümez ve POP instruction'ı ile küçülmez. [SUB ESP, 0x20] benzeri instruction'larla ESP register değeri küçültülerek büyüyebilir ve [ADD ESP, 0x20] benzeri instruction'larla ESP değeri artırılarak küçülebilir. • Stack ASLR uygulanırsa her yüklemede farklı bir adresten başlatılır.
  • 182. X86 MİMARİSİNE GİRİŞ STACK ALANININ KULLANIMI Stack'te Saklanan Veriler • Fonksiyon parametreleri: fastcall gibi calling convention'larda register'lar da fonksiyonlara parametre vermek için kullanılabilmekle birlikte diğer convention'larda ve bu iş için ayrılmış register'ların sayısının yetmediği durumlarda parametreler "CALL" instruction'ı ile fonksiyon çağrılmadan önce stack'e yazılır. Parametreler genellikle sağdan sola doğru stack'e PUSH edilir ("printf" gibi değişken sayıda parametre kabul eden fonksiyonlar için format string parametresinde olduğu gibi diğer parametreleri tanımlayan bir string başta olduğundan bu yaklaşım oldukça mantıklıdır).
  • 183. X86 MİMARİSİNE GİRİŞ STACK ALANININ KULLANIMI Stack'te Saklanan Veriler [devamı] • Fonksiyon dönüş adresi: "CALL" instruction'ı çalıştığı anda bu instruction'dan bir sonraki instruction adresi fonksiyondan "RET" instruction'ı ile dönüldüğünde EIP register'ına atanmak üzere stack'te saklanır. Bellek taşma açıklıklarında uygulama akışını manipüle etmek için hedef alınan başlıca pointer değeri bu değerdir (diğerlerine SEH pointer değeri, lokal değişken olarak saklanan object veri yapılarının ilk alanında bulunan Virtual Table pointer değeri örnek verilebilir).
  • 184. X86 MİMARİSİNE GİRİŞ STACK ALANININ KULLANIMI Stack'te Saklanan Veriler [devamı] • Bir önceki fonksiyon frame pointer'ı: Fonksiyon "prolog"larında daha önce de gördüğümüz gibi ilk yapılan işlem mevcut frame pointer değeri (EBP) yeni fonksiyonun frame pointer değeri ile ezileceği için "PUSH EBP" instruction'ı ile stack'e yazılır. Bu değer fonksiyon "epilog"unda "POP EBP" instruction'ı ile EBP pointer'ını eski frame pointer'ı haline getirmek için kullanılır. • Fonksiyon lokal değişkenleri: Fonksiyon "prolog"undan sonra genellikle fonksiyon lokal değişkenleri için ESP değeri düşürülerek yer ayrılır. Daha sonra lokal değişkenler için ayrılan bu alana lokal değişkenler yazılmaya ve bu alandan gerektiğinde okunmaya başlanır.
  • 185. X86 MİMARİSİNE GİRİŞ CALLING CONVENTIONS CALLING CONVENTION'LARI NEDEN ANLAMALIYIZ? Calling convention'lar çağıranın mı çağrılanın mı parametreler için kullanılan alanı geri vereceği ve hangi register'ların korunmasının kimin sorumluluğunda olduğu ile ilgilidir. İyi Niyetli Cevap Bu sorunun iyi niyetli cevabı farklı compiler'ların ürettikleri kodların bir arada uyum içinde çalışabilmeleri için stack yönetimi ve register'ların korunması için aynı yaklaşımları izleme ihtiyacıdır.
  • 186. X86 MİMARİSİNE GİRİŞ CALLING CONVENTIONS CALLING CONVENTION'LARI NEDEN ANLAMALIYIZ? [devamı] Kötü Niyetli Cevap Inline assembly ile bir kod yazarken veya virüs benzeri bir kodu mevcut bir uygulamaya yerleştirirken assembly içinden çağrılan Windows API'lerinin calling convention'ına uygun olarak hareket edilmezse Stack yapısının düzeni bozulacak, dolayısıyla da uygulama stack frame'i ile ilgili bu düzensizlikten dolayı hata alarak sonlanacaktır. Windows API'leri için "stdcall" convention'ına uygun bir biçimde stack'teki parametreleri yönetmezsek kodumuzun içinde çalıştığı proses hata alacaktır.
  • 187. X86 MİMARİSİNE GİRİŞ CALLING CONVENTIONS stdcall Adının çağrıştırabileceğinin aksine aslında tüm derleyiciler için standart convention değildir ve Microsoft Win32 API tarafından kullanılır. İlk olarak bu convention'dan söz etmemizin sebebi de budur. • Stack'in temizlenmesinden çağırılan (callee) sorumludur. Yani çağıran (caller) parametreleri stack'e push eder, ancak temizleme işlemini gerçekleştirmez. • Parametreler stack'e sağdan sola doğru push edilir. • EAX, ECX ve EDX register'ları fonksiyon içinde kullanılır, dolayısıyla fonksiyondan geri dönüldüğünde farklılaşmış olma ihtimalleri yüksektir. Yani bunlar caller saved register'lardır. • Fonksiyon return değeri EAX register'ına yazılır.
  • 188. X86 MİMARİSİNE GİRİŞ CALLING CONVENTIONS cdecl C declaration'ın kısaltması olan bu convention çoğu C derleyicileri tarafından kullanılır. • Stack'in temizlenmesinden çağıran (caller) sorumludur. Bu yaklaşım stdcall'unkinden farklıdır. • Parametreler stack'e sağdan sola doğru push edilir. • EAX, ECX ve EDX register'ları fonksiyon içinde kullanılır, dolayısıyla fonksiyondan geri dönüldüğünde farklılaşmış olma ihtimalleri yüksektir. Yani bunlar caller saved register'lardır. • Fonksiyon return değeri EAX register'ına yazılır.
  • 189. X86 MİMARİSİNE GİRİŞ CALLING CONVENTIONS Microsoft fastcall Parametre aktarımında register kullanımına da bir örnek olması amacıyla fastcall convention'ından da bahsedelim. Bir fonksiyonun bu convention'a göre derlenmesi için __fastcall anahtar kelimesinin kullanılması gerekir. • Soldan sağa ilk iki parametre ECX ve EDX register'larında aktarılır. • Diğer parametreler (bu defa sağdan sola) stack'e yazılır. • Stack'in temizlenmesinden stdcall'da olduğu gibi çağırılan (callee) sorumludur.
  • 190. ANALİZ STATİK ANALİZ [Disassembly] • X86 mimarisi ve assembly hakkında daha fazla bilgiye sahip olduğumuza göre biraz daha detaylı bir statik analiz gerçekleştirebiliriz. • İlk dinamik analiz çalışmalarımız sırasında uygulamanın bir HTTP isteğinde bulunduğunu gözlemlemiştik. Tabi bu gözlemi zararlı yazılıma herhangi bir internet erişimi vermeden gözlemlediğimiz için aslında indireceği [paket.bin] dosyasında ne olduğunu henüz bilmiyoruz. • Ancak ilginç olan konu uygulamanın Import ettiği API fonksiyonları içinde herhangi bir network veya HTTP API'sinin bulunmaması.
  • 191. ANALİZ STATİK ANALİZ [Disassembly] Yeniden hatırlamak gerekirse Import edilen API'lerden ilgimizi çekenlerin listesini aşağıda bulabilirsiniz (aralarında bir network API'si yok!): AdjustTokenPrivileges CreateFileW CreateRemoteThread CreateToolhelp32Snapshot FindNextFileW FindResourceW GetProcAddress IsDebuggerPresent LoadResource OpenProcess Process32FirstW Process32NextW ReadFile RegOpenKeyExW RegSetValueExW ShellExecuteW VirtualAllocEx WriteFile WriteProcessMemory
  • 192. ANALİZ STATİK ANALİZ [Disassembly] Bu API'lerden VirtualAllocEx farklı bir proses'in adres alanında yer ayırma işlevine sahip. Bu metodun çağrıldığı yeri biraz inceleyelim. AdjustTokenPrivileges CreateFileW CreateRemoteThread CreateToolhelp32Snapshot FindNextFileW FindResourceW GetProcAddress IsDebuggerPresent LoadResource OpenProcess Process32FirstW Process32NextW ReadFile RegOpenKeyExW RegSetValueExW ShellExecuteW VirtualAllocEx WriteFile WriteProcessMemory
  • 193. ANALİZ STATİK ANALİZ [Disassembly] VirtualAllocEx metodunun kullanıldığı yerleri tespit etmek için IDA Pro'nun Imports view'ında bu metodu bularak çift tıklayalım.
  • 194. ANALİZ STATİK ANALİZ [Disassembly] Import Address Table'da VirtualAllocEx fonksiyonuyla ilgili alana geçiyoruz. Burada VirtualAllocEx fonksiyon isminin üzerinde tıkladıktan sonra "x" tuşuna tıklayarak bu adrese referans verilen yerleri gözlemleyelim.
  • 195. ANALİZ STATİK ANALİZ [Disassembly] VirtualAllocEx fonksiyonuna tek bir noktada referans verildiğini görüyoruz. Bu referans'a çift tıklayarak .text section'ındaki ilgili instruction'a geçelim.
  • 196. ANALİZ STATİK ANALİZ [Disassembly] Bu alana ulaştığımızda biraz aşağıda WriteProcessMemory fonksiyonunun da çağrıldığını görebiliyoruz. VirtualAllocEx fonksiyonunun return değerinin "mov ebx, eax" instruction'ı ile "ebx" register'ına aktarıldığını görüyoruz.
  • 197. ANALİZ STATİK ANALİZ [Disassembly] WriteProcessMemory fonksiyonunun çağrıldığı instruction'ın hemen üzerinde toplam 5 adet push instruction'ı var. Bu instruction'lar büyük ihtimallle bu fonksiyonun aldığı parametreler olmalı.
  • 198. ANALİZ STATİK ANALİZ [Disassembly] MSDN'den WriteProcessMemory API'si ile ilgili bilgilere göz attığımızda fonksiyonun aldığı 5 parametreyi görebiliriz. Parametrelerden 3.sü diğer process'in address space'ine yazılacak içeriğin barındırıldığı alana işaret eden bir pointer. Bir zararlı yazılımı analiz ederken bizi merak ettirebilecek bir konu bu, o yüzden bu parametre'nin nereden geldiğini biraz inceleyelim.
  • 199. ANALİZ STATİK ANALİZ [Disassembly] Disassembly ekranında WriteProcessMemory fonksiyonuna verilen 3. parametrenin dword_42FCC8 pointer'ı olarak belirtildiğini görüyoruz. Şimdi bu parametreye tıkladıktan sonra bu asrese referans veren noktaları inceleyelim.
  • 200. ANALİZ STATİK ANALİZ [Disassembly] "x" tuşuna bastığımızda bu adrese 2 noktada referans verildiğini görüyoruz. 2. sırada bulunan referans şu anda gözlemlediğimiz alan, dolayısıyla diğerini incelememizde fayda var. 1. linke çift tıklayarak bu alanı inceleyelim.
  • 201. ANALİZ STATİK ANALİZ [Disassembly] Bu alana geldiğimizde "eax" register değerinin bu pointer'a atandığını görüyoruz. "eax" register'ı da hemen 2 instruction yukarıdaki "call sub_402A70" instruction'ı ile belirlenmiş olmalı.
  • 202. ANALİZ STATİK ANALİZ [Disassembly] Tekrar hatırlayalım halen diğer process'in address alanına yazılacak verinin nereden geldiğini inceliyoruz. Görünen o ki sub_402A70 adlı fonksiyon bu veriye işaret eden bir pointer döndürüyor. Şimdi çift tıklayarak bu fonksiyona göz atalım.
  • 203. ANALİZ STATİK ANALİZ [Disassembly] Şimdi bu fonksiyonun içindeyiz.
  • 204. ANALİZ STATİK ANALİZ [Disassembly] 1 2 3 Fonksiyonda biraz aşağıya indiğimizde deneyimli bir tersine mühendislik uzmanı tarafından normalde bir derleyici tarafından üretildiğine pek şahit olunmayacak olan bazı instruction'ları görüyoruz. Bu durum zararlı yazılımı geliştirmiş olan kişinin uygulamanın bu bölümünü bir inline assembly kodu ile geliştirmiş olma ihtimalini aklımıza getirmelidir. İlginç instruction'lardan birkaçını işaretledik. Şimdi sırasıyla bu instruction'lara anlam vermeye çalışalım.
  • 205. ANALİZ STATİK ANALİZ [Disassembly] 1 Birinci instruction "pusha", 32 bit'lik bir uygulama için bizim ikinci satırı esas almamız lazım. Instruction'ın yaptığı işlem tüm genel amaçlı register'ları yukarıda görüldüğü sırada stack'e yazmak. Bir shellcode programcısı bu işlemi kodu gömdüğü alanda bu register'ları kullandıktan sonra "popa" instruction'ı ile kazasız belasız tekrar orijinal hallerine döndürmek amacıyla kullanabilir.
  • 206. ANALİZ STATİK ANALİZ [Disassembly] 2 İkinci ilginç instruction ise "fs:0x30" adresindeki bir veriye işaret ediyor. "fs" register'ı Thread Environment Block [TEB] veri alanına işaret etmek için kullanılır. Bu veri yapısının 0x30 offset'inde ise Process Environment Block yer alır. Derlenmiş bir kodda böyle bir instruction'a rastlamak olası değildir.
  • 207. ANALİZ THREAD ENVIRONMENT BLOCK (TEB) Adım-1: PEB’in adresinin bulunması 0:000> !teb TEB at 7efdd000 ExceptionList: 0026f814 StackBase: 00270000 StackLimit: 0026e000 SubSystemTib: 00000000 FiberData: 00001e00 ArbitraryUserPointer: 00000000 Self: 7efdd000 EnvironmentPointer: 00000000 ClientId: 00001920 . 00001928 RpcHandle: 00000000 Tls Storage: 7efdd02c PEB Address: 7efde000 LastErrorValue: 0 LastStatusValue: 0 Count Owned Locks: 0 HardErrorMode: 0 fs:[0] fs:[30] 0x30 kernel32.dll'in adresinin bulunması 2 WinDbg binary debugger'ı ile bazı Windows veri yapılarını kolayca inceleyebiliriz. Yukarıda böyle bir örnek verilmektedir.
  • 208. ANALİZ STATİK ANALİZ [Disassembly] 3 Yukarıdaki instruction'lar başlangıçta biraz kafa karıştırıcı gelebilir, ancak iyi bir tersine mühendislik uzmanı bu tür instruction'lara hakim olabilmelidir. fs:30h alanında bulunan PEB referansı "esi" instruction'ına atıldıktan sonra, PEB'in 0xC offset'indeki değer tekrar "esi"a atanmakta, bu adresin de 0x1C offset'indeki değer de tekrar "esi"a atanmaktadır. Son adımda "esi" register'ının neyin adresini barındıracağını inceleyelim.
  • 209. ANALİZ PROCESS ENVIRONMENT BLOCK (PEB) Adım-2: _PEB_LDR_DATA veri yapısının bulunması 0:000> dt nt!_peb 7efde000 ntdll!_PEB +0x000 InheritedAddressSpace : 0 '' +0x001 ReadImageFileExecOptions : 0 '' +0x002 BeingDebugged : 0x1 '' +0x003 BitField : 0x8 '' +0x003 ImageUsesLargePages : 0y0 +0x003 IsProtectedProcess : 0y0 +0x003 IsLegacyProcess : 0y0 +0x003 IsImageDynamicallyRelocated : 0y1 +0x003 SkipPatchingUser32Forwarders : 0y0 +0x003 SpareBits : 0y000 +0x004 Mutant : 0xffffffff Void +0x008 ImageBaseAddress : 0x01380000 Void +0x00c Ldr : 0x77240200 _PEB_LDR_DATA +0x010 ProcessParameters : 0x002f2178 _ .... fs:[30] 0x0c kernel32.dll'in adresinin bulunması 3 0xC offset'inde process'in address alanına yüklenmiş olan DLL'ler ile ilgili yükleme veri yapısına bir referans bulmaktayız. Shellcode geliştirme deneyimi olan bir kişi size bu adımların içinde "LoadLibrary" fonksiyonunu barındıran Kernel32.dll kütüphanesinin process'in adres alanındaki tabanını bulmak için gerekli ilk adımlardan birisi olduğunu söyleyecektir. LoadLibrary fonksiyonu uygulama içinde dinamik olarak farklı DLL'lerin yüklenebilmesi için kullanılır.
  • 210. ANALİZ kernel32.dll'in adresinin bulunması _PEB_LDR_DATA Adım-3: Modül zincir listelerinin bulunması 0:000> dt _PEB_LDR_DATA 0x77240200 ntdll!_PEB_LDR_DATA +0x000 Length : 0x30 +0x004 Initialized : 0x1 '' +0x008 SsHandle : (null) +0x00c InLoadOrderModuleList : _LIST_ENTRY [ 0x2f4cf8 - 0x2f5990 ] +0x014 InMemoryOrderModuleList : _LIST_ENTRY [ 0x2f4d00 - 0x2f5998 ] +0x01c InInitializationOrderModuleList : _LIST_ENTRY [ 0x2f4d98 - 0x2f59a0 ] +0x024 EntryInProgress : (null) +0x028 ShutdownInProgress : 0 '' +0x02c ShutdownThreadId : (null) 0x1c 3 Bu adresin 0x1C offset'inde ise yüklenme sırasına göre modül (yani DLL) bilgileri veri yapılarının başlangıç adresi tutulur.
  • 211. ANALİZ kernel32.dll'in adresinin bulunması MODÜL ZİNCİR LİSTESİ Adım-4: Başlatılma sırasına göre modül zincir listesinin izlenmesi 0:000> dt _LIST_ENTRY 0x7724021c ntdll!_LIST_ENTRY [ 0x2f4d98 - 0x2f59a0 ] +0x000 Flink : 0x002f4d98 _LIST_ENTRY [ 0x2f5230 - 0x7724021c ] +0x004 Blink : 0x002f59a0 _LIST_ENTRY [ 0x7724021c - 0x2f5118 ] 0:000> dt _LIST_ENTRY 0x002f4d98 ntdll!_LIST_ENTRY [ 0x2f5230 - 0x7724021c ] +0x000 Flink : 0x002f5230 _LIST_ENTRY [ 0x2f5118 - 0x2f4d98 ] +0x004 Blink : 0x7724021c _LIST_ENTRY [ 0x2f4d98 - 0x2f59a0 ] 0:000> dt _LIST_ENTRY 0x002f5230 ntdll!_LIST_ENTRY [ 0x2f5118 - 0x2f4d98 ] +0x000 Flink : 0x002f5118 _LIST_ENTRY [ 0x2f59a0 - 0x2f5230 ] +0x004 Blink : 0x002f4d98 _LIST_ENTRY [ 0x2f5230 - 0x7724021c ] 1 2 3 Bu veri yapısı bir zincir listedir [linked list] ve zincirin her bir bileşeni bir sonra gelene işaret eden adresi ilk 4 byte'ında barındırır.
  • 212. ANALİZ kernel32.dll'in adresinin bulunması MODÜL ADI Adım-5: Modül adının bulunması 0:000> dd 0x002f4d98 + 20 002f4db8 77185bc4 00004004 0000ffff 002f59cc 002f4dc8 772448e0 521ea8e7 00000000 00000000 0:000> db 77185bc4 77185bc4 6e 00 74 00 64 00 6c 00-6c 00 2e 00 64 00 6c 00 n.t.d.l.l...d.l. 77185bd4 6c 00 00 00 14 00 16 00-e0 5b 18 77 5c 00 53 00 l........[.w.S. 77185be4 59 00 53 00 54 00 45 00-4d 00 33 00 32 00 5c 00 Y.S.T.E.M.3.2.. 77185bf4 00 00 90 90 90 90 90 8b-ff 55 8b ec 51 51 83 65 .........U..QQ.e 77185c04 fc 00 53 56 8b 35 0c 02-24 77 57 81 fe 0c 02 24 ..SV.5..$wW....$ 77185c14 77 74 31 8d 45 f8 50 6a-09 8b fe 8b 36 6a 01 ff wt1.E.Pj....6j.. Ayrıca bu adresten [decimal] 20 byte sonraki 4 byte'lık alanda da bu veri yapısının ait olduğu DLL'in adının tutulduğu alanın pointer'ını barındıran veri yer alır. Bu alanlar sırasıyla incelenerek Kernel32.dll'in kaydına ulaşıp ulaşmadığımız tespit edilebilir. Zincir halkalarında her bir modül'ün adresi de bulunur. Sonraki adımlar bu modül başlangıç adresinden başlayarak modülün (yani DLL'in) Export tablosu içinde gezinmeye başlamak ve LoadLibrary fonksiyon adresini bulmaya çalışarak devam edecektir. Biz örneği daha da karmaşıklaştırmamak için bu adımı burada sonlandırıyoruz. Bu aşamada zararlı yazılım yazarının bazı DLL'leri yüklediğinin kolay görünür olmaması için çaba gösterdiğini söyleyebiliriz.
  • 213. ANALİZ STATİK ANALİZ [Disassembly] Bu fonksiyonda daha aşağılara ilerlediğimizde bazı HEX değerlerin stack'e push edildiğini görüyoruz. Bunları "R" karakteri ile ASCII karakterlere dönüştürebiliriz. Zararlı yazılım yazarı strings incelemesinden [wininet.dll] DLL adının stack'e yazıldığı ortaya çıkmasın diye işlevsiz opcode'ları da assembly koduna eklemiş.
  • 214. ANALİZ STATİK ANALİZ [Disassembly] [wininet.dll] kütüphanesinin barındırdığı fonksiyonlara MSDN'den göz atalım.
  • 215. ANALİZ STATİK ANALİZ [Disassembly] HTTP erişimi ile ilgili olanların bir kısmı burada görüldüğü gibidir.
  • 216. ANALİZ STATİK ANALİZ [Disassembly] InternetOpenUrl fonksiyonu HTTP protokolü ile bir web kaynağına erişmek için kullanılabilir.
  • 217. ANALİZ STATİK ANALİZ [Disassembly] İncelediğimiz kodun içinde pek çok defa çağrıldığını gördüğümüz bir fonksiyon da dikkatimizi çekebilir. Yeterli zaman olması halinde bu fonksiyona verilen iki parametrenin belli bir DLL'in başlangıç adresi ve bir fonksiyon adının basit bir algoritma ile hash'lenmiş değeri olduğunu tespit edebilirdik. Bu sayede çağrılan fonksiyonların neler olduğunu statik analiz ile tespit etmemiz çok zorlaştırılmıştır. Ancak dinamik analizde hangi fonksiyonların çağrıldığı açıkça görülebilir.
  • 218. ANALİZ STATİK ANALİZ [Disassembly] Fonksiyon kodları içinde biraz daha aşağıya indiğimizde stack'e yazılan bir dizi HEX veri daha görebiliriz. Ancak bu verileri "R" komutuyla ASCII karşılıklarına dönüştüremiyoruz, çünkü dikkat ederseniz arada NULL [00] karakterleri bulunması bu karakterlerin Unicode karakterler olabileceğine işaret etmektedir.
  • 219. ANALİZ STATİK ANALİZ [Disassembly] Bu karakterleri kodun içinden daha rahat çekebilmek için IDA'nın 8 opcode byte'ına kadar görüntüleme ayarını Options penceresinden yapalım.
  • 220. ANALİZ STATİK ANALİZ [Disassembly] Opcode'ları da içeren satırları tarayarak clipboard'a kopyalayalım (sağ klikle)
  • 221. ANALİZ STATİK ANALİZ [Disassembly] Kopyaladığımız veriyi Notepad++ ekranına yapıştırdıktan sonra sadece push edilen 2. ve 5. byte'lar arasını ALT tuşuna basarken mouse ile tarayarak kopyalayalım.
  • 222. ANALİZ STATİK ANALİZ [Disassembly] Kopyaladığımız veriyi bir başka Notepad++ ekranına yapıştırdıktan sonra boşlukları ve satır sonlarını kaldıralım.
  • 223. ANALİZ STATİK ANALİZ [Disassembly] Kalan son veriyi HxD veya farklı bir Hexadecimal bir editöre kopyaladığımızda sağ tarafta Unicode karakter karşılıklarını görebiliriz [Microsoft Internet Explore]
  • 224. ANALİZ STATİK ANALİZ [Disassembly] Aynı işlemi daha aşağıdaki bölüm için de tekrarlayalım.
  • 225. ANALİZ STATİK ANALİZ [Disassembly] Notepad++'da sadece push edilen verilerin kalmasını sağlayalım.
  • 226. ANALİZ STATİK ANALİZ [Disassembly] Bu alanda da aşağıdaki verinin stack'e yazıldığını ortaya çıkarmış olduk: [http://www.btr-mlwsunucu.com/paket.bin]
  • 227. ANALİZ DİNAMİK ANALİZ [Debugging] Bu noktaya kadar analizin tamamını statik analiz olarak yapmanın kulağa geldiği kadar hoş olmadığını farketmiş olmalıyız. Zararlı yazılımın farklı bir proses'in address alanına yazdığı verinin ne olduğunu anlamanın en pratik yolu dinamik analizden faydalanmak olacaktır. Bunun için zararlı yazılımımızın çalışacağı Windows bilgisayarla aynı karantina subnet'inde bulunmakta olan Kali bilgisayarımız üzerindeki Honeypot servislerini [inetsim] başlatalım.
  • 228. ANALİZ DİNAMİK ANALİZ [Debugging] Decompress edilmiş olan uygulamamızın ASLR desteğini daha önceden kaldırmıştık (çünkü başka türlü çalışmıyordu). Bu imkan sayesinde statik analizdeki VA adreslerimizin debug ederken de aynı kalacağından emin olabiliriz. Şimdi tam farklı process'in address alanına yazılacak olan verinin Stack'e yazıldığı instruction'ın adresi olan [0x401E79] adresine bir breakpoint koyalım.
  • 229. ANALİZ DİNAMİK ANALİZ [Debugging] Play düğmesine gerektiği kadar basarak breakpoint satırına kadar ilerleyelim.
  • 230. ANALİZ DİNAMİK ANALİZ [Debugging] F7 tuşu veya Step Into düğmesine basarak Stack'e farklı process'in address alanına yazılacak olan verinin adresini yazalım. Bu işlem gerçekleştikten hemen sonra da yazılan adresin işaret ettiği alanı daha iyi gözlemleyebilmek için Stack'te bu adrese sağ tıklayarak [Follow in Dump] seçeneğini seçelim.
  • 231. ANALİZ DİNAMİK ANALİZ [Debugging] Sol altta bulunan Memory Dump alanındaki verileri daha iyi görebilmek için bu alana sağ klikleyerek [Hex/ASCII (16 bytes)] seçeneğini seçelim.
  • 232. ANALİZ DİNAMİK ANALİZ [Debugging] Anlaşılan o ki söz konusu veri [www.btr- mlwsunucu.com/paket.bin] HTTP isteğine gelen yanıttan oluşuyor. Inetsim servisi sayesinde bu yanıt gerçek paket.bin dosyası değil de sahte bir HTML yanıtından oluşuyor.
  • 234. ANALİZ PAYLOAD ANALİZİ paket.bin dosyasını VirusTotal'e gönderdiğimizde Shellcode olarak tanımlanıyor.
  • 235. ANALİZ PAYLOAD ANALİZİ IDA Pro'da bu dosyayı incelediğimizde dosya normal bir PE dosyası olmadığından paket.bin dosyasının içeriğini veri olarak algılanacaktır.
  • 236. ANALİZ PAYLOAD ANALİZİ IDA Pro'nun bu verileri kod olarak değerlendirmesi için sağ klikleyerek [Code] seçeneğini seçebiliriz.
  • 237. ANALİZ PAYLOAD ANALİZİ Kod bölümü hemen normal bir uygulamadaki gibi grafik halinde görüntülenmeyebilir, uygulama grafiğini görebilmek için [Space] tuşuna basınız.
  • 238. ANALİZ PAYLOAD ANALİZİ Grafik gösterimde sağdaki koyu mavi çizgi bir döngü olduğuna işaret ediyor. Bu shellcode'un encoded bir shellcode olması durumunda dinamik analiz daha doğru bir tercih olacaktır. Zararlı uygulamanın internete erişmesi yerine paket.bin dosyasını inetsim tarafından sağlayarak dinamik analiz gerçekleştirilebilir.
  • 239. ANALİZ PAYLOAD ANALİZİ • Gerçekte bu payload'un tam olarak ne yaptığını anlamak için ciddi bir süreyi tersine mühendislik için harcamamaız gerekebilir. • Bu payload bir meterpreter reverse_tcp payload'u ve karşı tarafta bir handler tarafından karşılanması gerekir. • Gerçek payload'un ne yaptığının dinamik analizle görülmesi için kurum ağından bağımsız bir ADSL hattı ve yine bir sanal makine kullanılarak inceleme yapılabilir, elbette çok dikkatli olmak kaydıyla.
  • 240. ANTI-DISASSEMBLY ANTI-DISASSEMBLY TEKNİKLERİ • Uygulamamızda bir anti-disassembly örneği barındırmadık, çünkü yeterli zaman ayrılmaması durumunda ve henüz konuya yeni kişiler için bu durumların tespiti ve çözülmesi zor olabilir. • Ancak deneyimli tersine mühendislik uzmanları için bu tekniklerin tespiti ve ortadan kaldırılmasının zannedilebileceğinden daha kolay olacağını söyleyebiliriz.
  • 241. ANTI-DISASSEMBLY ANTI-DISASSEMBLY TEKNİKLERİ • Disassembler'ları yanlış yönlendirmek ve disassembly kodunun uygulamanın gerçek davranışından farklılaştırmak için pek çok teknik kullanılabilir, örneğin: • [EB FF C0 48] opcode'ları "EB FF - jmp 1", geçerli olmayan bir "C0" opcode'u ve "48 - dec eax" olarak disassemble edilecektir. • Gerçekte ise "jmp 1" instruction'ı Instruction Pointer'ı "EB FF" opcode'larının başından itibaren 1 byte ileriye atlatacak ve "FF C0 - inc eax" olarak, "48 - dec eax" olarak çalıştırılacaktır. • Çözüm bu işe yaramayan ve karmaşıklığa neden olan opcode'ları NOP ile yamalayarak ortadan kaldırmaktır.