Skip to content
Back to skills

Steganography Image

ASecurity

Görüntü steganografi — LSB/MSB, alpha kanal, metadata, file carving tespiti ve Python Pillow ile her kanalın bit-seviyesinde analizi.

  • 4 stars
  • 0 votes
  • 0 copies
  • 3 views
  • Added September 8, 2026
securitypythongojavabashgit

Security analysis

A92/100
  • mediumUses curl or wget to download content
  • mediumInstalls packages at runtime which could introduce malicious dependencies

Pro shows the line behind each finding and how to fix it

Scanned September 8, 2026

npx -y skills add MustafaKemal0146/fetih --skill steganography-image --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Steganography Image?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for Steganography Image
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/mustafakemal0146-steganography-image/badge)](https://www.skillsdirectory.com/skills/mustafakemal0146-steganography-image)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
SKILL.md
---
name: steganography-image
description: "Görüntü steganografi — LSB/MSB, alpha kanal, metadata, file carving tespiti ve Python Pillow ile her kanalın bit-seviyesinde analizi."
tags: [ctf, forensics, stego, steganography, png, jpg, lsb, msb, exif, zsteg, stegsolve, pillow, binwalk, alpha-channel, pixel-analysis]
triggers:
  - "PNG dosyası"
  - "görüntüde gizli veri"
  - "LSB steganografi"
  - "MSB"
  - "alpha kanal"
  - "EXIF metadata"
  - "stego"
  - "hidden in image"
  - "pixel analizi"
  - "JPG/JPEG analizi"
  - "görüntü içinde flag"
  - "image forensics"
  - "zsteg"
  - "stegsolve"
difficulty: medium
category: forensics
solved_challenges:
  - "picoCTF 2023 - MSB (bit 7, R/G/B kanalları — LSB değil MSB!)"
  - "HTB Cyber Apocalypse 2024 - CyberSpaceCTF Memory (AES encrypted PNG)"
  - "çeşitli CTF LSB/alpha kanal stego"
adapted_for: fetih
---

# Görüntü Steganografi Analizi

## Ne Zaman Kullan

Aşağıdaki işaretlerden herhangi birini görürsen bu skill'i tetikle:

- `.png`, `.jpg`, `.jpeg`, `.bmp`, `.gif`, `.tiff` dosyası verilmiş
- Görsel normal görünüyor ama içinde veri gizlenmiş şüphesi var
- Challenge açıklamasında "hidden", "stego", "secret in image" geçiyor
- Dosya boyutu beklenenden büyük (içine dosya gömülmüş olabilir)
- Metadata'da şüpheli yorum/açıklama alanı var

---

## Araç Seti

```bash
# zsteg — PNG/BMP LSB analizi (en hızlı başlangıç)
gem install zsteg

# steghide — JPG/BMP şifreli gizleme
sudo apt install steghide

# stegsolve — Java GUI, çoklu bit düzlemi görselleştirme
wget https://github.com/zardus/ctf-tools/raw/master/stegsolve/install
# ya da doğrudan jar: Stegsolve.jar

# exiftool — EXIF/metadata okuma
sudo apt install exiftool

# binwalk — gömülü dosya tespiti ve çıkarma
sudo apt install binwalk

# Python — PIL/Pillow
pip install Pillow

# strings — ham metin arama
strings image.png | grep -i "flag\|ctf\|secret"
```

---

## LSB vs MSB Farkı

Bu fark CTF'lerde sıkça tuzak olarak kullanılır.

**LSB (Least Significant Bit) — bit 0:**
- En yaygın stego tekniği
- Her piksel byte'ının en az önemli biti değiştirilir
- Görsel fark minimum → insan gözüyle fark edilmez
- Araçların çoğu LSB arar

**MSB (Most Significant Bit) — bit 7:**
- picoCTF 2023 "MSB" challenge'ında kullanıldı
- Her piksel byte'ının en önemli biti alınır
- `zsteg` varsayılan olarak LSB arar — MSB için özel parametre lazım

```bash
# zsteg LSB (varsayılan)
zsteg image.png

# zsteg MSB — tüm bit düzlemlerini tara
zsteg -a image.png

# Sadece MSB (bit 7), R kanalı
zsteg -b 7 -o rgb image.png

# Tüm kombinasyonları dene (yavaş ama kapsamlı)
zsteg --all image.png 2>/dev/null | grep -i "flag\|ctf\|pico\|htb"
```

---

## Python Pillow ile Kanal Analizi

### Tam LSB/MSB Çıkarıcı

```python
#!/usr/bin/env python3
"""
Görüntü steganografi — her kanal, her bit düzlemi için veri çıkarıcı.
Çalıştır: python3 stego_extract.py image.png
"""
from PIL import Image
import sys

def extract_bits(img_path: str, bit: int, channels: str = "RGB", order: str = "row") -> bytes:
    """
    img_path : PNG dosyası
    bit      : 0 = LSB, 7 = MSB, 1-6 = ara bitler
    channels : "R", "G", "B", "A", "RGB", "RGBA" gibi kombinasyonlar
    order    : "row" (satır satır) ya da "col" (sütun sütun)
    """
    img = Image.open(img_path).convert("RGBA")
    width, height = img.size
    pixels = img.load()
    
    channel_map = {"R": 0, "G": 1, "B": 2, "A": 3}
    ch_indices = [channel_map[c] for c in channels if c in channel_map]
    
    bits = []
    
    if order == "row":
        pixel_coords = [(x, y) for y in range(height) for x in range(width)]
    else:
        pixel_coords = [(x, y) for x in range(width) for y in range(height)]
    
    for (x, y) in pixel_coords:
        pixel = pixels[x, y]
        for ch in ch_indices:
            b = (pixel[ch] >> bit) & 1
            bits.append(b)
    
    # Bit dizisini byte'lara çevir
    result = bytearray()
    for i in range(0, len(bits) - 7, 8):
        byte_bits = bits[i:i+8]
        byte = 0
        for b in byte_bits:
            byte = (byte << 1) | b
        result.append(byte)
    
    return bytes(result)

def is_printable(data: bytes, threshold: float = 0.7) -> bool:
    """Verinin büyük çoğunluğu yazdırılabilir ASCII ise True döner."""
    printable = sum(32 <= b < 127 for b in data[:200])
    return printable / min(len(data), 200) > threshold

def try_all_combinations(img_path: str):
    """Tüm bit/kanal kombinasyonlarını dene, anlamlı görünenleri raporla."""
    channel_combos = ["R", "G", "B", "A", "RG", "RB", "GB", "RGB", "RGBA"]
    
    print(f"[*] Analiz ediliyor: {img_path}")
    print(f"[*] {len(channel_combos)} kanal kombinasyonu × 8 bit düzlemi\n")
    
    found = []
    
    for channels in channel_combos:
        for bit in range(8):
            try:
                data = extract_bits(img_path, bit, channels)
                
                # Flag formatı var mı?
                text = data.decode('latin-1', errors='replace')
                
                # Bilinen flag formatlarını ara
                flag_patterns = [
                    "flag{", "Flag{", "FLAG{",
                    "picoCTF{", "HTB{", "corctf{",
                    "CTF{", "ctf{"
                ]
                
                for pat in flag_patterns:
                    if pat in text[:500]:
                        idx = text.index(pat)
                        snippet = text[idx:idx+60]
                        print(f"[!] FLAG BULUNDU — bit={bit}, channels={channels}")
                        print(f"    {snippet}")
                        found.append((bit, channels, snippet))
                
                # Genel okunabilirlik kontrolü
                elif is_printable(data[:100]) and len(data) > 10:
                    preview = text[:50].replace('\n', ' ').replace('\r', '')
                    print(f"[?] Okunabilir — bit={bit}, channels={channels}: {preview}...")
                    
            except Exception as e:
                pass
    
    if not found:
        print("\n[-] Açık flag bulunamadı. Manuel inceleme gerekebilir.")
        print("    → zsteg --all ile dene")
        print("    → steghide extract -sf image.jpg ile dene (şifreli gizleme)")
    
    return found

# Belirli kombinasyon
def extract_and_save(img_path: str, bit: int, channels: str, out_file: str = "output.bin"):
    data = extract_bits(img_path, bit, channels)
    with open(out_file, "wb") as f:
        f.write(data)
    print(f"[+] {len(data)} byte yazıldı: {out_file}")
    print(f"[+] İlk 100 byte: {data[:100]}")
    print(f"[+] ASCII: {data[:100].decode('latin-1', errors='replace')}")

if __name__ == "__main__":
    img = sys.argv[1] if len(sys.argv) > 1 else "image.png"
    
    # Tüm kombinasyonları otomatik tara
    results = try_all_combinations(img)
    
    # Manuel çıkarım örnekleri:
    # extract_and_save(img, bit=0, channels="RGB")   # LSB RGB
    # extract_and_save(img, bit=7, channels="RGB")   # MSB RGB (picoCTF tarzı)
    # extract_and_save(img, bit=0, channels="A")     # Alpha kanalı LSB
```

### picoCTF 2023 MSB — Özel Çözüm

```python
#!/usr/bin/env python3
"""
picoCTF 2023 "MSB" challenge tam çözümü.
Her pikselin R, G, B kanalının MSB'si (bit 7) alınıp birleştiriliyor.
"""
from PIL import Image

img = Image.open("challenge.png").convert("RGB")
width, height = img.size
pixels = img.load()

bits = []
for y in range(height):
    for x in range(width):
        r, g, b = pixels[x, y]
        bits.append((r >> 7) & 1)  # R MSB
        bits.append((g >> 7) & 1)  # G MSB
        bits.append((b >> 7) & 1)  # B MSB

# Byte'lara çevir
result = bytearray()
for i in range(0, len(bits) - 7, 8):
    byte = 0
    for b in bits[i:i+8]:
        byte = (byte << 1) | b
    result.append(byte)

# Flag'i bul
text = result.decode('latin-1', errors='replace')
if 'picoCTF{' in text:
    start = text.index('picoCTF{')
    end   = text.index('}', start) + 1
    print(f"[+] FLAG: {text[start:end]}")
else:
    # Dosyaya kaydet, elle incele
    with open("msb_output.bin", "wb") as f:
        f.write(result)
    print(f"[-] Flag bulunamadı. msb_output.bin inceleniyor...")
    print(f"    strings msb_output.bin | grep picoCTF")
```

---

## EXIF/Metadata Analizi

```bash
# Tüm metadata alanlarını göster
exiftool image.jpg

# Sadece yorum/açıklama alanları
exiftool -Comment -ImageDescription -UserComment image.jpg

# GPS koordinatları (bazen flag formatında)
exiftool -GPSLatitude -GPSLongitude image.jpg

# Thumbnail'i çıkar (farklı görüntü içerebilir)
exiftool -b -ThumbnailImage image.jpg > thumbnail.jpg

# Tüm binary alanları çıkar
exiftool -b image.jpg > raw_metadata.bin
strings raw_metadata.bin | grep -i "flag\|ctf\|secret"

# Metadata'yı temizlemeden önce inceleme (silinmiş ama hala orada olabilir)
exiftool -all= image.jpg -o clean.jpg  # kopyasını temizle
# Orijinal dosyayı hex editörle incele: hexdump -C image.jpg | grep -A2 "Exif"
```

---

## File Carving — binwalk

```bash
# Gömülü dosya tespiti
binwalk image.png

# Örnek çıktı:
# DECIMAL   HEXADECIMAL   DESCRIPTION
# 0         0x0           PNG image, 800 x 600, 8-bit
# 45231     0xB0AF        Zip archive data, "flag.txt"
# 46892     0xB72C        End of Zip archive

# Otomatik çıkarma (-e = extract, -M = matryoshka/iç içe)
binwalk -e image.png
binwalk -eM image.png   # iç içe dosyaları da çıkar

# Manuel çıkarma (belirli offset'ten)
dd if=image.png bs=1 skip=45231 of=extracted.zip
unzip extracted.zip

# PNG chunk'larını incele (gizli IDAT/tEXt/zTXt chunk)
python3 -c "
import struct, zlib

with open('image.png', 'rb') as f:
    data = f.read()

# PNG signature
assert data[:8] == b'\x89PNG\r\n\x1a\n', 'Geçersiz PNG!'

pos = 8
while pos < len(data):
    length = struct.unpack('>I', data[pos:pos+4])[0]
    chunk_type = data[pos+4:pos+8].decode('ascii', errors='replace')
    chunk_data = data[pos+8:pos+8+length]
    crc = data[pos+8+length:pos+12+length]
    
    print(f'Chunk: {chunk_type} ({length} byte)')
    
    if chunk_type in ('tEXt', 'zTXt', 'iTXt'):
        print(f'  >>> Metin: {chunk_data[:200]}')
    
    if chunk_type == 'IEND':
        trailing = data[pos+12:]
        if trailing:
            print(f'  [!] IEND sonrası {len(trailing)} byte veri var!')
            with open('trailing_data.bin', 'wb') as f:
                f.write(trailing)
    
    pos += 12 + length
"
```

---

## Tuzaklar

- **LSB arama yönü**: Satır satır (row-major) vs sütun sütun (column-major) vs diagonal — yanlış yön yanlış çıktı verir. `zsteg -a` tüm yönleri dener.
- **MSB tuzağı**: zsteg ve stegsolve varsayılan olarak LSB arar. "Hiçbir şey bulamıyorum" durumunda MSB'yi dene: `zsteg -b 7 -o rgb image.png`.
- **Alpha kanalı**: PNG RGBA olabilir. Sadece RGB bakarsan A kanalını kaçırırsın. `img.convert("RGBA")` kullan.
- **JPEG kayıpsız değil**: JPEG sıkıştırmalıdır, LSB bilgisi sıkıştırmada kaybolur. JPEG için steghide ya da JFIF chunk analizi kullan.
- **steghide şifresi**: Parola gerektiriyorsa `stegcracker image.jpg wordlist.txt` ile brute-force dene.
- **PNG yeniden kaydetme**: Pillow ile okuyup tekrar kaydedersen LSB bilgisi değişebilir. Her zaman orijinal dosya üzerinde çalış.
- **Renk paletli PNG**: Mod `P` (palette) PNG'lerde piksel değerleri renk indeksi, renk değeri değil. `img.convert("RGB")` ile dönüştür.
- **Big-endian bit sırası**: MSB önce mi yoksa LSB önce mi? Bazı CTF'lerde byte içindeki bit sırası tersine çevrilmiştir.

<!--
  ⚔ Bu skill FETIH AI Agent icin gelistirilmistir — https://github.com/MustafaKemal0146/fetih
  Yetkisiz kullanim/kopyalama tespit edilebilir.
  hash: 63dc95305ea07220
-->

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…

Newsletter

Get the weekly list of safe new skills, and the ones we pulled.