Rehber › Teknikler
Teknikler

XOR Şifreleme Mantığı ve CTF'te Çözümü

XOR, CTF crypto sorularında en sık karşına çıkacak temel işlemlerden biri; korkutucu görünür ama mantığı bir kez oturunca çok basittir. Bu rehberde XOR'un ne olduğunu, tek-byte ve tekrarlı anahtar farkını ve "ALTAY{" ipucuyla anahtarı nasıl bulacağını çalışan Python örnekleriyle öğreneceksin.

Özet
  • XOR (⊕) bit düzeyinde çalışır: aynı bitler 0, farklı bitler 1 verir.
  • Anahtarla iki kez XOR yaparsan orijinal veriye dönersin; şifreleme ve çözme aynı işlemdir.
  • Tek-byte anahtar 256 ihtimalle brute-force ile kolayca kırılır.
  • Bilinen bir açık metin parçası (örneğin ALTAY{) anahtarı doğrudan verebilir.
  • Tekrarlı anahtarda önce anahtar uzunluğunu, sonra her byte'ı ayrı ayrı çözersin.

XOR nedir?

XOR (özel VEYA, işareti ya da programlamada ^) iki biti karşılaştıran bir mantık işlemidir. Kuralı tek cümlede özetlenir: bitler farklıysa 1, aynıysa 0 verir.

Doğruluk tablosu şöyle:

Bilgisayarda her karakter aslında bir byte'tır (8 bit). XOR'u byte'lara uyguladığımızda her bit çifti için bu kuralı işletiriz. Python'da denemesi çok kolay:

a = 0b1010   # 10
b = 0b0110   # 6
print(a ^ b) # 1100 -> 12

Bir metni şifrelemek için metnin her byte'ını bir anahtar byte'ıyla XOR'larız. İşte tüm mesele bu kadar.

XOR'un sihirli özelliği: geri döndürülebilirlik

XOR'u CTF'te bu kadar sevimli yapan tek bir özellik var: aynı anahtarla iki kez XOR yaparsan başladığın yere dönersin. Yani:

metin ^ anahtar = sifreli
sifreli ^ anahtar = metin

Formül olarak A ^ B ^ B = A. Çünkü bir sayı kendisiyle XOR'lanınca 0 olur (B ^ B = 0) ve herhangi bir şey 0 ile XOR'lanınca değişmez (A ^ 0 = A).

Bunun pratik sonucu şu: XOR'da şifreleme ve çözme aynı işlemdir. Ayrı bir "çözme fonksiyonu" yazmana gerek yok; şifreliyi tekrar anahtarla XOR'larsan düz metin çıkar. Bu yüzden CTF'te "anahtarı bul" ile "mesajı çöz" çoğu zaman aynı adımdır.

Tek-byte XOR ve brute-force

En basit hali, tüm mesajın tek bir byte ile (0 ile 255 arası bir sayı) XOR'lanmasıdır. Buna tek-byte XOR denir. Anahtar tek byte olduğu için sadece 256 ihtimal vardır; hepsini tek tek deneyip anlamlı olanı seçmek saniyeler sürer. Buna brute-force (kaba kuvvet) diyoruz.

Elinde hex olarak verilmiş bir şifreli metin olsun. Tüm anahtarları dene ve içinde okunabilir/ipuçlu bir şey aran:

sifreli = bytes.fromhex("2e2b26203f...")  # örnek veri

for anahtar in range(256):
    cozum = bytes([b ^ anahtar for b in sifreli])
    if b"ALTAY{" in cozum:          # bilinen ipucu
        print(anahtar, cozum)

Burada if b"ALTAY{" in cozum satırı işin kalbi: doğru anahtarı bulduğunda çıktının içinde tanıdık bir kalıp belirir. Bir ipucun yoksa, çıktının çoğunlukla harf ve boşluklardan oluşup oluşmadığına (yazdırılabilir karakter oranına) bakarak da eleyebilirsin.

Tekrarlı anahtar (repeating-key) XOR

Anahtar tek byte yerine bir kelime olursa işler biraz zorlaşır. Tekrarlı anahtar XOR'da anahtar mesaj boyunca döne döne uygulanır: birinci karakter anahtarın 1. byte'ıyla, ikinci karakter 2. byte'ıyla... anahtar bitince baştan başlar.

Uygulaması yine kısa. Aşağıdaki fonksiyon hem şifreler hem çözer, çünkü XOR simetriktir:

def xor(veri, anahtar):
    return bytes([b ^ anahtar[i % len(anahtar)]
                  for i, b in enumerate(veri)])

print(xor(b"merhaba", b"key"))

Buradaki i % len(anahtar) ifadesi anahtarın başa sarmasını sağlar. Tekrarlı anahtarı brute-force ile denemek pratik değildir (ihtimaller çok fazla); onun yerine önce anahtar uzunluğunu tahmin edip, sonra her pozisyonu ayrı bir tek-byte XOR problemi gibi çözersin. Yani problemi küçük parçalara bölersin.

Known plaintext: ALTAY{ ipucuyla anahtarı bulmak

CTF crypto sorularında en güçlü kozun, düz metnin bir kısmını zaten biliyor olmandır. Buna known plaintext (bilinen açık metin) denir. Flag'ler çoğunlukla belli bir önekle başlar; örneğin ALTAY{. Şifreli metnin ilk byte'larının hangi düz byte'lara denk geldiğini biliyorsan, anahtarı XOR'un tersinden çekip çıkarabilirsin.

Mantık yine A ^ B ^ B = A'dan geliyor: sifreli ^ metin = anahtar. Şöyle:

sifreli = bytes.fromhex("....")   # şifreli metin
bilinen = b"ALTAY{"               # tahmin ettiğimiz baş

anahtar = bytes([c ^ p for c, p in zip(sifreli, bilinen)])
print(anahtar)

Çıkan anahtar okunabilir, anlamlı bir kelimeye benziyorsa (örneğin tekrar eden bir desen ya da düzgün bir sözcük) doğru yoldasın demektir. Bulduğun anahtarı tekrarlı XOR ile tüm mesaja uygularsan gerisi açılır. İpucu önekin uzunluğu, bulabileceğin anahtar byte sayısını belirler; anahtar daha kısaysa tekrarından tamamını çıkarabilirsin.

CTF'te XOR sorusunu nasıl tanır ve çözersin

Bir soruda şu işaretleri görürsen aklına XOR gelsin:

  1. Sana hex ya da base64 bir veri verilmiş ama doğrudan çözünce anlamsız çıkıyor.
  2. Açıklamada "key", "XOR", "one-time pad" gibi ipuçları geçiyor.
  3. Veri, bilinen bir formattan (PNG, ZIP başlığı gibi) sadece "kaymış" görünüyor.

Pratik yol haritan: önce tek-byte olduğunu varsayıp 256 anahtarı brute-force et; olmazsa bilinen bir açık metin parçasıyla anahtarı çekmeyi dene; anahtar birden çok byte çıkıyorsa tekrarlı XOR olarak, önce uzunluğu bulup sonra parça parça çöz. CyberChef gibi araçların "XOR Brute Force" adımı da bu işi görsel yapar, ama mantığı elle kavramak seni her soruda ayakta tutar.

Bu teknikleri kendi elinle denemeden oturmaz. Crypto kategorisindeki challenge'lara geçip küçük bir XOR sorusuyla başla; takıldığın noktada Rehber sayfasındaki diğer başlangıç yazılarına göz at. CTF'in ne olduğuna dair genel bir zemine ihtiyacın varsa önce CTF Nedir? yazısını okumak iyi olur.

Not: Buradaki tüm örnekler eğitim amaçlıdır ve yalnızca sana ait ya da yetkili olduğun ortamlarda, CTF antrenman sahalarında denenmelidir.

Sıkça Sorulan Sorular

XOR gerçekten güvenli bir şifreleme mi?

Tek başına, sabit ve kısa bir anahtarla kullanıldığında hayır. Tek-byte XOR 256 denemeyle, tekrarlı anahtar ise frekans analizi ve known plaintext ile kolayca kırılır. Bu yüzden gerçek sistemlerde XOR tek başına değil, AES gibi modern algoritmaların bir parçası olarak kullanılır.

Şifreli metin hex verilmiş, önce ne yapmalıyım?

Hex'i önce byte'lara çevir (Python'da bytes.fromhex ile). Sonra tek-byte olduğunu varsayıp 256 anahtarı brute-force et ve çıktılarda ALTAY{ gibi tanıdık bir kalıp ara. Bulamazsan tekrarlı anahtar ihtimalini değerlendir.

Anahtarı bilmeden nasıl çözebiliyorum?

İki ana yol var: tek-byte ise tüm 256 ihtimali deneyip anlamlı çıktıyı seçersin (brute-force), ya da düz metnin bir kısmını (flag öneki gibi) biliyorsan onu şifreliyle XOR'layıp anahtarı doğrudan çekersin (known plaintext).

Tek-byte mi yoksa tekrarlı anahtar mı olduğunu nasıl anlarım?

Önce tek-byte varsay: 256 denemeden biri baştan sona anlamlı metin veriyorsa tek-byte'tır. Hiçbir tek anahtar tüm mesajı düzeltmiyor ama başlangıç anlamlı çıkıyorsa muhtemelen anahtar birden çok byte, yani tekrarlıdır.

Bunları elle mi yapmalıyım yoksa araç mı kullanmalıyım?

İkisi de olur. CyberChef gibi araçlar XOR brute-force'u hızlı yapar, ancak birkaç satırlık Python yazarak mantığı kendin kurmak seni beklenmedik varyasyonlara hazırlar. CTF'te asıl kazandıran, aracın altındaki mantığı anlamandır.

Hadi pratiğe dök

Bu rehberdeki teknikleri Kriptografi kategorisindeki gerçek challenge’larda dene.

Kriptografi Challenge’ları →

Devam et