Neymiş bu Shellcode önce onu öğrenelim;
Shellcode hattı zatında bu gördüğümüz "x/" "x45" bilmem ne gibi hex codelerin makine dilinden okunarak bug olan application üstüne enjekte edilmesiyle çağırılan kodlar silsilesidir desek oturaklı bir tabir olur sanırım. Gerekli olan malzemeleri yukarıda verdik ama yinede küçük bir liste yapalım;
- Birazcıcık Linux
- Assembly
- C < (Arada Derede)
- Beyin
Evet ASM için kayıt adresleri yukarıda listelenmiş gözüküyor isterseniz kısaca bunuda açalım diyecekken aklıma Türkçe olarak gördüğüm ve müthiş derecede başarılı bulduğum bir arkadaşın bu konuda makalesi geldi ben burayı kısadan yine açıklayıp geçeceğim lakin kesinlikle bunu seriyi sabırla okumanızı tavsiye ediyorum.
Velhasıl kelam bizde gelelim işi özüne;
EAX, EBX,ECX,EDX bu ifadelerin hepsi ASM x86(32 BIT) işlemciler için genel amaçlı kayıt adresleridir.
EAX, EBX,ECX,EDX bu ifadelerin hepsi ASM x86(32 BIT) işlemciler için genel amaçlı kayıt adresleridir.
AX,BX,CX,DX bu ifadelerin hepsi yukarıda ki ifadelerle çelişik olarak 16 Bit kayıt adresleri olarak karşımıza çıkarlar.(anlayacaksınız)
AH,BH,CH,DH ifadeleri ise High etiketiyle karşımıza çıkar ki bu yüksek önem taşıyan registerlar anlamına gelir ikilik 8 Bit regiterlarda öncelik olduğunu gösterir bu registerlar 8 Bit grubuna dahildir
AL,BL,CL,DL ifadeleri ise Lower etiketiyle karşımızadalar bunlarda düşük önceliği olan registerlardır.
Şimdi yukarıdakilerle beraber bir örnek verelim;
0x80706050
0x80706050
Görülen adreste Little Endian sistemini kullanacağız yani adresi sağdan sola doğru okuyacağız ki bunun birde Big Endian sistemi vardır ordada soldan sağa doğru bir okuma terimi vardır yukarıda belirttiğim kaynakta arakadaş detaylı olarak girmiş bu konulara incelerseniz göreceksiniz. Velhasıl kelam;
0x50 < Bu değer bizim yukarıda bahsettiğimiz AL değerimizdir yani Lower düşük öncelikli değerdir ki ilk 8 Bitlik olan ilk Bytemizi cebimize koyduk
0x50 < Bu değer bizim yukarıda bahsettiğimiz AL değerimizdir yani Lower düşük öncelikli değerdir ki ilk 8 Bitlik olan ilk Bytemizi cebimize koyduk
0x60 < Bu değerimiz ise yukarıda bahsedilne AH yani High registerda önceliği olan kaydedicinin aldığı değerdir. -Little Endian sistemiyle gidiyoruz sağdan sola gördüğünüz üzere-
0x8070 < Bu değeri inceleyecek olursak eğer bu değerimiz 16 Bit değerinde ki alt registerlardan ikili olan AX aittir.
0x80706050 < Total değere zaten baktığımızda EAX registerını görmüş oluyoruz 4 Byte değerinde bir register 1 Byte = 8 Bit eşit olarak düşünürsek mevzu tamamdır karşimm.
0x80706050 < Total değere zaten baktığımızda EAX registerını görmüş oluyoruz 4 Byte değerinde bir register 1 Byte = 8 Bit eşit olarak düşünürsek mevzu tamamdır karşimm.
Kısaca bahsettiğimize göre asıl mevzumuza artık geçebiliriz şimdi ikinci adımda gerekli olan malzemeleri görelim isterseniz;
- gcc - C - C++ Kod derleyici
- ld – Bağlayıcı Toolumuz, Derlenen ASM Kodu Bağlamaya yarar kendileri.
- nasm - Netwide Assembler Tercihe Göre.
- objdump – Objdump reverse encinerink yapan arkadaşların dostu, obje bilgileri, hex vs.
- strace – Sistem hareketleri ve iz takibi.
Shellcode Vakti
Aslında yapmak istediğimiz her ne olursa olsun illa ki bir assembly uğruyoruz burda assembly ile ürettiğimiz kodları açık olan yazılıma enjekte ederek elde edilen sonuçla yürüyeceğiz -ki zaten shellcode teriminin amacı assembly ile yazılmış satırları shellcode vasıtasıyla makineye okutmak ve ondan dönen sonuçla bilitibar hareket etmektir. Örneğin; Ben application bir yerinde açık bulduysam ordan bir "sh" almak istiyorsam oraya /bin/sh yazamam makine bu dilden anlamaz bu makinenin syntax başka çok başka. O sadece sayılardan anlar ve atanan değerlerden bu sayede shellcode çevirerek programların içine enjekte ediyoruz ve dönen sonuçla hareket ediyoruz diyebiliriz.
Shell.c#include <stdio.h>const char shellc[]="x/shellcode";main(){int (*shell)();shell=shellc;shell();}
Evet yukarıda ki C kodumuz üstünden yürüyeceğiz, lakin bunu yapmadan önce shellcode generate için burda ve dahi sürekli kullamacağımız "system call number" yani çağıracağımız fonksiyonun numaraları lazım diyebiliriz.
Local'de görmek isterseniz ?
Yukarıda gördüğünüz adreste belirtilen fonksiyonlar ile sistemde hareket edeceğiz write, exit, pause, reboot bla bla bla diye devam ediyor. Peki nasıl kullanacağız görelim isterseniz, küçük bir asm dizisi yazalım.
Shello.asm;shello.asm;s3f4 / / / TG[SECTION .text] ;kod girişi yapıcam benglobal _start ;dizin adı_start: ;bu dizine kod girişimov eax, 29 :sys_pause çağırın banaint 80h ;Kernel Hazırlansın(80h kerneli çağırır)
Evet yukarıda belirttiğimiz üzere küçük bir ASM dizesi yazdık peki yazmakla mevzu bitiyormu elbette hayır devamını görsel olarak inceleyelim;
Nasm ile dosyasımızı derledikten sonra sırada ki komutumuz yukarıda da belirttiğimiz gibi "ld" komutu olacak;
Evet şimdi dizinimize bir adet shells adında dosya çıkacak isterseniz bunu çalıştırdığımızda neler olduğunu bir görelim;
Evet nolduğunu anlamak için aslında sistem çağrı numaralarını kontrol etmemiz yetecektir en nihayetinde "29" sadece Gümüşhane'nin plakası değil yani bakalım neymiş bu;
29. sys_pause
Syntax: int sys_pause(void)Source: arch/i386/kernel/sys_i386.cAction: wait for signalDetails:
Peki başlığımızla mütevellit şimdi bu kodları bir shell kodu olarka çalıştırmak istersek ne yapmamız gerekecek ? Evet devam edelim;
Yukarıda ki imajda görüldüğü üzere shellcode değerleri için objdump kullanıyoruz ki bu Linux platformdada reverse engineering için vazgeçilmez araçlardan biridir, çıkan kodları incelediğimizde;
b8 1d 00 00 00
cd 80
Gibi değerler görüyoruz asıl iş burda kardeşim bize lazım olanlar bunlar, objdump ile bu değerler bize shellcode üreterecek asli değerleri verecek lakin burda bir problem var biraz fazla sıfır var sanırım değil mi? Shellcode içinde ismine yabancı olmadığımız bir terim var null byte, bunu lfi injection'da görürsünüz, login form geçişlerinde görürsünüz, crash exploitlerde görürsünüz ki yaygındır programcının hatalarını istismar etmekte kullanılır neyse kafa karıştırmayalım burda hiç bir türlü işimize yaramayan null byte yerine farklı bir sistem uygulamalıyız. Bunu yazmadan önce isterseniz yukarıda gördüğümüz değerleri işe yaramasada bir shellcode stiline çevirelim;
Shellcode:“\xb8\x1d\x00\x00\x00\xcd\x80“
Yukarıda görülen çıktının shellcode olarak çıktısı bu şekilde olmalıydı lakin null byte shellcode içinde çalıştırmayacağımız ve bu değerin hiç bir manası olmadığı için cpu içinde dönmeyeceğinden dolayı alternatif bir işlem yapacağız bu işlemin adı "xor" işlemi ki bu işlem belirtilen register adresinin içini sıfırlar yani ben şimdi şöyle bir şey yapmak yerine;
mov eax, 0
mov eax, 0
Eax'ın değerine sıfır kaynağını okut demek yerine xor işlemini kullanacağım ki bu matematiksel bir işlemdir bizi null byte değerlerinden kurtaracaktır görelim;
Kodumuzu gördük xor işlemi yaptık gelen sonuçları önce derleyip sonra objdump ile görelim bakalım neler çıkmış bir anlayalım;
Evet sofiler xor ile null byte mevzusundan kurtulduk şimdi bu kodumuzu açık olduğunu bildiğimiz bir C kod içinde derleyip çalıştırmayı deneyelim ve çıkan sonuçları buraya kaydedelim.
const char pausecode[]="\x31\xc0\xb0\x1d\xcd\x80";main(){int (*shell)();shell=pausecode;shell();}
Şu şekilde C kodumuzun içine shellcode gömdük hani demiştik ya kardeşim biz kod içinde yav bi dur pause yapayım yav bi dur print ettireyimf felan diyemeyiz bu dilden anlamaz makine söylemiştik hangi dilden anladığını bu kodu bir derleyelim bakalım ne çıkacak;
root@tgseclnx:~/Desktop/reverse# gcc asmpau.c -o pausesroot@tgseclnx:~/Desktop/reverse# ./pauses
Evet çıkan sonucuda görmek istersek waiting signal gösterecek çünkü bu system call number yani çağrı numarasına baktığımızda açıklamasıyla beraber(-ki kendileri 29 numarada koşuyor) sistemde açıklanan görevi yerine getirdiğini göreceğiz.
(Evet aşağıda ki screenle beraber derlenen shellcode'nin çalıştığınıda görmüş olduk.)
Şimdi işleri biraz daha büyütelim ekrana bişeyler yazdıralım ne yazdıralım örneğin "Hello World" ki bizim offical cümlemizdir onu bir yazdıralım bakalım ne yapmamız gerekiyor hee demeyin ki yav sefa biz bunu pythonla'da yazdırırız ekrana perl ilede felanda filanda tamam yazdırırsınız ama sadece yazdırmış olursunuz o hazırlar halleder yazar siz burda hem pişirip hem yemeyi öğreniyorsunuz daha doğrusu hep beraber öğreniyoruz diyelim şuna. ---Devamı 2. Seriye--
Aslında 1. Seriyi Bu kadar kısa tutma niyetim yoktu ama 1. Seri şimdilik bu kadarla sonlansın diyelim yazının devamını ise 2. seriye aktaracağım takip edebilirsiniz.
Sevgiyle.
/**
Allahu Teala Hazretleri Buyuruyor ki;
"İlmi İsteyene, Rızkı ise İstediğime Veririm..."
*/
hikaye tadında okudum eline sağlık çok iyi
YanıtlaSilEline sağlık paylaşımın için teşekkür ederim. Yazını şu http://kali-linuxtr.net/ adreste paylaşmak istiyorum müsaden olursa
YanıtlaSilmerhabalar, elbette paylaşmanızda bir beis yok blog üstünde ki her içerik kaynak gösterilmek suretiyle paylaşılabilir.
Sil