BlackNullSec Path : MEMORY ROADMAP
🚀 Memory aşaması = malware dünyasına giriş kapısı
şöyle düşün:
Pointer = silah
Memory = savaş alanı
Process Memory = düşman bölgesi
🔎 RAM’i böyle düşün:
RAM = lineer bir byte dizisi
[0x1000] → 41
[0x1001] → 42
[0x1002] → 43
[0x1003] → 44
Bu ne demek?
👉 Her adres 1 byte
👉 Her adres = index gibi
DEĞİŞKENLER GERÇEKTE NE?
Sen bunu böyle görüyorsun:
int x = 10;
Ama sistem şöyle görüyor:
Adres: 0x1000
Değer: 0A 00 00 00 (little endian)
⚠️ KRİTİK NOKTA
👉 int = 4 byte
👉 RAM = byte bazlı
Yani:
10 sayısı = 4 parçaya bölünüyor
POINTER NE YAPIYOR?
int x = 10;
int *p = &x;
Memory’de:
[0x1000] → 0A 00 00 00 (x)
[0x2000] → 00 10 00 00 (p → x’in adresi)
👉 pointer = adres tutar
Önemli:)
Pointer = memory içindeki başka bir noktaya giden yol
POINTER ARİTMETİĞİ GERÇEKTE NE YAPIYOR?
int *p = 0x1000;
p + 1;
Bu ne olur?
👉 0x1004
💣 NEDEN BU KRİTİK?
PE header parsing
shellcode
encryption
signature scan
👉 hepsi byte seviyesinde yapılır
💣MEMORY OPERATIONS
memcpy → veri taşıma (payload copy)
memset → temizleme / obfuscation
memcmp → karşılaştırma
memcpy
👉 pointer arithmetic + byte copy memcpy nerede kullanılır?
shellcode inject ederken
payload decrypt ederken
config load ederken
👉 Yani:
memcpy = malware core tool
Örnek:)
char src[4] = {1,2,3,4};
char dest[4];
memcpy(dest, src, 4);
Memory’de ne olur?:)
BAŞLANGIÇ:)
src:
[1][2][3][4]
dest:
[?][?][?][?]
👉 memcpy sonrası:)
dest:
[1][2][3][4]
⚠️ KRİTİK NOKTA)
👉 bu byte copy’dir
👉 type önemli değil
Örnek:)
int x = 0x12345678;
int y;
memcpy(&y, &x, 4);
y kaç olur?
👉 0x12345678
Memory’de nasıl görünür?
y:
78 56 34 12
🧠 NEDEN BÖYLE?
memcpy(&y, &x, 4) → byte byte kopya
Sistem → little endian
Bu yüzden en düşük byte öne gelir
👉 memcpy:
“adres taşımaz”
“değerin byte’larını taşır”
🔴 SORUN
“Biri düz (0x12345678), diğeri neden ters (78 56 34 12)?”
👉 Çünkü:
Register / sayı gösterimi = “insan okuma formatı”
Memory = “byte byte saklama formatı”
Ve sistem:
Little Endian kullanıyor
🔥 1. “DÜZ” GÖRÜNEN NE?
int x = 0x12345678;
Bu bir sayıdır. CPU bunu şöyle yorumlar:
0x12345678
👉 Bu sadece anlam (value)
🔴 2. MEMORY NASIL TUTAR?
Memory byte bazlıdır:
78 56 34 12
👉 Çünkü:
Little endian = en düşük byte önce yazılır🧠 PARÇALAYALIM
0x12345678
Byte’lara ayır:
12 | 34 | 56 | 78🔴 Big Endian (mantıksal sıralama)
12 34 56 78🔥 Little Endian (gerçek memory)
78 56 34 12🧠 ZİHİN MODELİ
Value (mantık):0x12345678
Memory (gerçek):
[78][56][34][12]
💥 MALWARE / RE GERÇEĞİ
Bu yüzden:debugger’da hex dump ters görünür
PE header okurken offset’ler karışır
signature scan yaparken byte sırası önemlidir
👉 Eğer endian’ı anlamazsan:
yanlış analiz yaparsın
🔴 VERİLEN
int x = 0x11223344;
unsigned char *p = (unsigned char*)&x;
printf("%02X\n", p[2]);
🔴 1. Memory görünümü (Little Endian)
0x11223344Memory’de:
44 33 22 11✅ DOĞRU CEVAP
👉 p[2] = 22🔥 KRİTİK KURAL
index = byte offset🔴 2. Index mantığı
🧠 ZİHİN MODELİ
Adres Değer 0x1000 44 ← p[0] 0x1001 33 ← p[1] 0x1002 22 ← p[2] 0x1003 11 ← p[3]
🔥 (NOT AL)
🔥 (NOT AL)
Pointer = memory’yi nasıl okuduğundur
Sayı düz yazılır, memory’ye yazılırken little endian’a göre parçalanır
🔴 ADIM ADIM
1. SEN KODDA YAZIYORSUNint x = 0xA1B2C3D4;
👉 Bu sadece mantıksal değer (value)<
A1 B2 C3 D4
🔴 2. CPU BUNU MEMORY’YE KOYUYOR
Sistem:👉 Little Endian
🔥 NE YAPIYOR?
D4 C3 B2 A1👉 yani:
en küçük byte (D4) → ilk adres
en büyük byte (A1) → son adres
💣 KRİTİK CÜMLE
Kod “tersine çevrilmez”👉 memory’ye yazılırken byte sırası düzenlenir
0x4D, 0x5A, 0x90, 0x00,
0x03, 0x00, 0x00, 0x00
};
printf("%x\n", *(int*)(x + 4));
HANGİ BYTE’LAR OKUNUR?
(x + 4)👉 Başlangıç: index 4
Memory: [0] 4D [1] 5A [2] 90 [3] 00 [4] 03 ← başlangıç [5] 00 [6] 00 [7] 00 ✔ Okunan: 03 00 00 00
SONUÇ NE?
👉 RAM düz
👉 CPU little endian yorumluyor
Little endian → düşük byte önce
03 00 00 00 → 0x00000003
👉 Doğru sonuç:
0x3
🔴 DOĞRU YORUM
Memory: 03 00 00 00
Değer: 0x00000003
👉 printf çıktısı = CPU’nun yorumudur
Örnek
int *p = (int*)0x1000;Soru:
(char*)p + 3
👉 kaç byte ilerler?
👉 sonuç adres ne olur?
int *p = (int*)0x1000;
(char*)p + 3
ADIM ADIM ANALİZ
1. Başlangıç
p = 0x1000
👉 int* → normalde 4 byte zıplar
2. CAST NE YAPTI?
(char*)p
👉 Pointer tipi değişti:
❌ artık int* değil
✔ char* oldu
🔥 KRİTİK SONUÇ
👉 Artık pointer arithmetic:
sizeof(char) = 1
3. HESAP
(char*)p + 3
👉
3 × 1 = 3 byte
👉
0x1000 + 3 = 0x1003
✅ DOĞRU SONUÇ
👉 3 byte ilerler
👉 adres = 0x1003
🧪 MINI DRILL (BUNU ÇÖZ)
struct Test {
char a; // 0
int b; // 4
};
unsigned char mem[8] = {
0x11, 0x00, 0x00, 0x00,
0x78, 0x56, 0x34, 0x12
};
👉 SORU:
*(int*)(mem + 4) = ?
🔍 VERİ
struct Test {char a; // offset 0
int b; // offset 4
};
unsigned char mem[8] = {
0x11, 0x00, 0x00, 0x00,
0x78, 0x56, 0x34, 0x12
};
mem + 4 NE YAPAR?
Senin dediğin doğru:
👉 mem = unsigned char*👉 +4 = 4 byte ilerler
[4] → 0x78 ← başlangıç
AMA SONRA NE OLUYOR?
*(int*)(mem + 4)
👉 Bu şu demek:
"Buradan başlayarak 4 byte oku ve int olarak yorumla"OKUNAN BYTE'LAR
78 56 34 12
LITTLE ENDIAN YORUMLAMA
Memory: 78 56 34 12
Değer: 0x12345678
✅ SONUÇ
*(int*)(mem + 4) = 0x12345678
⚔️ PE BAĞLANTISI (EN ÖNEMLİ NOKTA)
Bu yaptığın şeyin aynısı:
dos->e_lfanew = *(int*)(base + 0x3C);
👉 Yani:
base + 0x3C → başlangıç
int → 4 byte oku
little endian → değeri oluştur
🌟 Sonraki Yazı: İndex_vs_Offset
← Önceki Sonraki →⚠️ Kritik Uyarı
Bu teknikler yalnızca eğitim amaçlıdır. Gerçek sistemlere uygulanması yasadışı olabilir. Asla gerçek ortamlarda test etme.
“Windows Belleğiyle Konuşan Kodlar”
hacker