Cumartesi, Aralık 12

Shellcode Linux - 2

/*Evet en son serinin üstünden çok zaman geçti nasip bu zamanaymış diyerekten yazılarımızı devam ettirebiliriz. Olağan gelişen ve sürekli olarak gelişmeye devam eden iş tantanasından ötürü bu yazıları seri şekilde yazamıyorum, bu yüzden kimse kusura bakmasın diyerekten yazımıza geçelim istiyorum... */

Evet en son shellcode'da Linux System Call Number işliyorduk hatta birde pause fonksiyonunu işlemişiz ikinci seride biraz daha string ağırlıklı ve system call function kullanarak hareket etmeyi göreceğiz ama öncelikle kaldığımız yerden devam edelim kafa karışıklıklarına meydan vermeyelim.

Evet biraz string yazdıralım cümleleyelim felan salıverelim isterseniz, evet yeniden terminalimiz açıp gerekli kodları yazdıralım zaten bu asm editor hakkında da bilgi vermiştim isteyen nasm isteyen gasm vs. gibi editörler kullanabilir. Basic olarak .asm öğrendiğinizde bir nevi shellcode ilerletmiş oluyorsunuz ama tam manasıyla ben asm. hakim olmak istiyorum diyorsanız opcode ve sistemin işleyişi hakkında tam manasıyla çözümleme yapmanız gerekmektedir. Peki bunlar nelerdir diye soracak olursanız her yazımda belirttiğim gibi "EZBER YAPMAYIN" sözüyle bir örnekle açıklamak istiyorum; CMP fonksiyonun açılımı "compare" yani karşılaştırma fonksiyonudur. Şöyle ki,

mov ebx, 0x1
xor eax, eax
inc eax
cmp eax, ebx
:?

Peki ne yaptık burada ? Açıklayalım, asm mantığı tamamen ilkokulda düşman olduğumuz matematik ile bağdaşır ve bu şekilde çalışır; "Ya bilgisayar 0 ve 1 ile çalışıyor yaa" diye söylediğimizde nasıl yaa ? Diye sorduklarında şu yukarıda ki çıktı ve binary aklınıza gelirse eğer tam manasıyla anlamış olursunuz. Yukarıda ebx 1 atadık, sonrasında eax register xor operatoru ile "0" sayısına çevirdik ve inc operatoruyle 1 sayı öne attırdık daha sonrasında cmp fonksiyonu ilede karşılaştırdık karşılaştırmadan sonrada yapılacak şeyler size kalıyor artık "je" mi dersiniz "jne" mi dersiniz orası size kalmış bir mevzu kısa bir açıklamadan sonra mevzumuza dönelim.

Shellcode mantığında yazdığımız kodlar, belirli bir şekilde kodlanarak istismar edilecek sistemlere enjekte edilmektedir. İsterseniz "kem küm" etmeden direkt mevzuya geçelim;

Aşağıda gördüğünüz kod silsilesiyle /bin/bash çağırarak konsolda istediğimiz gibi komutlama işlemini yapabiliriz öncelikle bu kodu bir inceleyelim ve olup biteni anlayalım.


#include <stdio.h>
int main() {
         char *name[2];
          name[0] = "/bin/sh";
           name[1] = NULL;
            execve(name[0], name, NULL);
}  
/* gcc shell2.c -o shell2 -static */

hafif bir C bilgisiyle yukarı da "/bin/sh" çağırdığımızı görebilirsiniz bunun içinde execve fonksiyonu kullanılmaktadır birde gdb ile inceleyelim;


(gdb) set disassembly-flavor intel 

(gdb) disas main

Dump of assembler code for function main:

   0x08048254 <+0>: push   ebp

   0x08048255 <+1>: mov    ebp,esp

   0x08048257 <+3>: and    esp,0xfffffff0

   0x0804825a <+6>: sub    esp,0x20

   0x0804825d <+9>: mov    DWORD PTR [esp+0x18],0x80aad68

   0x08048265 <+17>: mov    DWORD PTR [esp+0x1c],0x0

   0x0804826d <+25>: mov    eax,DWORD PTR [esp+0x18]

   0x08048271 <+29>: mov    DWORD PTR [esp+0x8],0x0

   0x08048279 <+37>: lea    edx,[esp+0x18]

   0x0804827d <+41>: mov    DWORD PTR [esp+0x4],edx

   0x08048281 <+45>: mov    DWORD PTR [esp],eax

   0x08048284 <+48>: call   0x804f770 <execve>

   0x08048289 <+53>: leave  

   0x0804828a <+54>: ret    

End of assembler dump.


Evet ilk satırlarda da göreceğimiz üzere klasik bir işlem yapılmaktadır;

   0x08048254 <+0>: push   ebp

   0x08048255 <+1>: mov    ebp,esp

   0x08048257 <+3>: and    esp,0xfffffff0

   0x0804825a <+6>: sub    esp,0x20
push operatoruyle stack yazılan bilgilerden sonra, stack ve base pointer aynı değerler üstünden bilgiler çekiliyor(LIFO), and operatörüyle yapılan  mantıksal karşılaştırma ve sonrasında sub fonksiyonuyla bir stack segmentinden 0x20(32) bir değer çıkartılıyor ve değer ilk parametreye aktarıldı. Unutmadan cmp operatörü işlemlerinde subtract yani çıkarma işlemi kullanır.


 (gdb) p/d 0xfffffff0

$7 = 4294967280
Değeri incelediğimiz karşımıza şu şekilde bir değer çıkıyor bu değerin sonrasında tabi ki çıkarma işlemi ile işlemimiz devam ediyor. Burada "sys call number" dikkat çekmek istediğim bir konu var son satırda da görüldüğü üzere bir fonksyion call ediliyor bunun biraz daha derinine inmek gerekirse;


(gdb) disas execve

Dump of assembler code for function execve:

   0x0804f770 <+0>: push   ebp

   0x0804f771 <+1>: mov    ebp,esp

   0x0804f773 <+3>: mov    edx,DWORD PTR [ebp+0x10]

   0x0804f776 <+6>: push   ebx

   0x0804f777 <+7>: mov    ecx,DWORD PTR [ebp+0xc]

   0x0804f77a <+10>: mov    ebx,DWORD PTR [ebp+0x8]

   0x0804f77d <+13>: mov    eax,0xb <======

   0x0804f782 <+18>: int    0x80

   0x0804f784 <+20>: cmp    eax,0xfffff000

   0x0804f789 <+25>: ja     0x804f78e <execve+30>

   0x0804f78b <+27>: pop    ebx

   0x0804f78c <+28>: pop    ebp

   0x0804f78d <+29>: ret    

   0x0804f78e <+30>: mov    edx,0xffffffe8

   0x0804f794 <+36>: neg    eax

   0x0804f796 <+38>: mov    DWORD PTR gs:[edx],eax

   0x0804f799 <+41>: or     eax,0xffffffff

   0x0804f79c <+44>: jmp    0x804f78b <execve+27>

End of assembler dump.

"0x0804f77d" hex adresine baktığımızda "eax" register bir adres taşıması(0xb) gerçekleşiyor;


~ :/c# cat /usr/include/i386-linux-gnu/asm/unistd_32.h | grep 11

#define __NR_execve 11

Yukarıda "sys call" dosyasını geçen yazıda belirtmiştim çıkan sonuçta tam olarak "eax" registerıyla çağırılan fonksiyonla örtüşür durumda tesadüf değil : )

En son tanımladığımız ve asıl amacımızı belirten "bash" mevzusuna geri dönelim;

(gdb) printf  "%s\n", 0x80aad68

/bin/sh

Yukarıda main fonksiyonuna bağlı hex değerini okuduğumuzda bizi tam olarak amacımıza götürüyor üzerine sayfalarca shellcode yazılmış ve halen daha yazılmakta olan "/bin/sh" modülü.

Tam olarak bu offsete yapılan çağrılarda yahut bu hex tanımlanmış olan bu bu fonksiyonu istediğiniz gibi başka hex değerler üstünde kullanabilirsiniz yukarıda print edilen hex değerinin açılını "/bin/sh" demektir ve bu hex değeri okutularak /bin/sh çağırılabilir vs.

Mevzumuz bitmiş değil şimdi bir açılımla elde ettiğimiz değerler üstünden yürüyerek neler yaptığımızı görelim isterseniz(1. yazı seriye dahil);

1. Sistem call number ile fonksiyon numaraları,
2. C kod ile sistem çağrıları,
3. Sağlıklı ve terminate olmayacak şekilde shellcode yazılması(Null Byte),
4. C kod ile /bin/sh çağrısı ve çalışma mantığı,

5. Syscall fonksiyonlarından birinin Debug edilmesi.


//3. Seride görüşmek dileğiyle





0 yorum:

Yorum Gönder

Blogger tarafından desteklenmektedir.