Time-to-Live ve Steganografi

TTL (Time-to-Live) değeri, ağ iletişiminde kullanılan bir terimdir. Bu değer, bir paketin ağdaki yaşam ömrünü temsil eder ve sayı cinsinden ifade edilir. TTL değerinin temel amacı, yönlendirme sırasında oluşabilecek döngüyü önlemektir. Her bir yönlendirme geçişinde TTL değeri bir azalır. Eğer bir paketin TTL değeri sıfıra ulaşırsa yönlendirici cihaz o paketi çöpe atar. Bu sayede döngü engellenmiş olur.

Aşağıdaki görseli inceleyerek konuyu kavrayalım. Örneğimizde, “PC” cihazı hedefteki “Web Server” cihazına ICMP Echo Request paketleri göndererek sunucunun çalışıp çalışmadığını test eder. Ardından sunucu, çalıştığını bildirmek için ICMP Echo Reply cevapları gönderir.

Sunucu “Linux” tabanlı olduğu için TTL (Time To Live) değeri 64’ten başlar ve her bir yönlendiriciden geçerken 1 azalır. Sonuç olarak, Echo Reply paketi PC cihazına ulaştığında TTL değeri 59 olarak görünür. Bu değerden yola çıkarak, PC cihazı sunucunun Linux tabanlı olduğunu tahmin edebilir. Çünkü farklı işletim sistemleri farklı başlangıç TTL değerleri kullanır:

İşletim SistemiTTL ( Time-to-Live )
Windows128
Linux64
Cisco IOS255

Bugün Türkiye’den çıkıp Yeni Zelanda’daki bir sunucuya ping atılsa bile, paket en fazla 25–30 yönlendiriciden geçer. Dolayısıyla, TTL değeri 128’den başlayıp 59’a düşmez. Bu yüzden, gelen paketin başlangıç TTL değeri göz önüne alınarak işletim sistemi hakkında tahmin yürütülebilir.

Ayrıca, TTL değeri yönlendirme sırasında oluşabilecek döngüleri önlemek için kritik öneme sahiptir. Eğer bir yönlendirme döngüsü oluşursa, TTL her geçişte 1 azalır ve sıfıra ulaştığında paket bir daha yönlendirilmez; ilgili yönlendirici tarafından çöpe atılır. Bu nedenle TTL, hem hedefe ulaşma sürecinin hem de ağ güvenliğinin önemli bir parçasıdır.

Ekran goruntusu 2025 05 30 093239

Web sayfama gerçekleştirdiğim bağlantı testi sonrasında TTL değerini görebiliriz. Yukarıda yaptığımız benzer çıkarımı bu örnekte de uygularsak, web sunucumun Linux tabanlı olduğunu söyleyebiliriz. Ancak TTL değeri zaman zaman değişkenlik gösterebilir, çünkü bir web sunucusuna giderken her zaman aynı yönlendiricilerden geçmeyebiliriz.

Ekran goruntusu 2025 05 30 092818

TTL değeri IPv4 başlığının içerisinde yer almaktadır. Buna benzer bir başlık olan Hop-Limit alanı ise IPv6 başlığının içerisinde yer almaktadır. İki alan da 8 bittir. Aralarında bir fark bulunmamaktadır.

TTL değeri 8 bitten oluşmaktadır. Yani aşağıdaki gibidir. Bu değer maksimum 255 ve minimum 0 olabilmektedir.

TTL Maksimum Değer –> 11111111 = 255

TTL Minimum Değer –> 00000000 = 0

Yukarıda da belirttiğim gibi, dünyanın en uzak noktasındaki bir sunucuya bile ulaşmak genellikle en fazla 25-30 yönlendirici üzerinden gerçekleşir. Bu durumda TTL için 255 gibi yüksek bir başlangıç değeri aslında gereksiz yere fazladır. Yönlendirme için 63 gibi bir değer bile fazlasıyla yeterlidir. Dolayısıyla TTL alanında kullanılan ilk 2 bitin teknik olarak bir işlevi kalmamakta, bu alan bir nevi israf edilmektedir. (Yukarıda işaretli bitler)

Steganografi, bir bilginin başka bir nesnenin içine gizlice saklanması işlemidir. Buradaki amaç, bilginin gizli olduğunu fark ettirmemektir.

Şifreleme (kriptografi) ile arasındaki temel fark, şifrelemede bilginin okunamaz hale getirilmesidir. Yani bilginin varlığı bellidir, ancak içerik anlamlandırılamaz. Steganografide ise bilginin varlığı bile fark edilmez. Örneğin bir görselin içine bir mesaj yerleştirilebilir ve bakıldığında orada herhangi bir mesaj olduğu anlaşılmaz.

İşte bu nedenle, TTL alanında yer alan ve yönlendirme açısından işlevi olmayan ilk 2 bit, steganografi amacıyla kullanılabilir. Bu iki bit içine gizli bir mesaj yerleştirilerek, sistemler arasında fark edilmeden iletişim kurulabilir.

Bunun için Python programlama dilinde, “Scapy” kütüphanesini kullanarak ağ paketleri oluşturup göndereceğiz. Kütüphaneyi yüklemek için aşağıdaki komutu çalıştırabilirsiniz. (Kodlar sayfanın en altında yer almaktadır.)

pip install scapy (Windows)
sudo pip3 install scapy (Linux)

Öncelikle iki farklı Python dosyasına ihtiyacımız olacak. Bunlar şunlardır:

  • Encoder.py
  • Decoder.py

İlk olarak “Encoder.py” dosyasıyla başlayalım. Bu araç, mesajı gönderecek kişi tarafından kullanılacaktır. Aşağıda gerçekleştirilecek adımları inceleyebilirsiniz.

1- Öncelikle kullanıcı, göndermek istediği mesajı girecektir. Örneğin, karşı tarafa “merhaba” mesajını iletmek istiyor olabilir.

2- Daha sonra, bu mesajdaki karakterler önce ASCII tablosundaki karşılıklarına, ardından da bu karşılıklar hexadecimal (yani 16’lık sayı sistemi) formatına dönüştürülecektir. (İngiliz alfabesinde olmayan bir karakter varsa örneğin “ü” “Unicode” karşılığına bakılır.”)

  • Örneğin “m” ve “e” harfleri için bu işlemi adım adım uygulayalım.
    “m” harfi, ASCII tablosunda 109 sayısına karşılık gelir.
    109 sayısı, hexadecimal (16’lık sayı sistemi) karşılığı olarak 6D şeklindedir.
    Bu değeri ikili (binary) sisteme çevirdiğimizde ise sonuç 01101101 olur.
  • Buradaki bitler, ikili gruplar (her biri 2 bit) halinde parçalara ayrılır.
  • 01-10-11-01
  • Ardından, bu parçalar sırayla TTL değerinin ilk 2 bitine yerleştirilir. Yukarıda da belirtildiği gibi, TTL değerinin 63 olması paketin hedefe ulaşması için yeterlidir. Bu sayede, örneğin “m” harfinin binary gösterimini aşağıdaki gibi TTL alanına parça parça ekleyebiliriz.
  • 01111111 = TTL(127) –> 1. ICMP Echo Request Paketi
  • 10111111 = TTL(191) –> 2. ICMP Echo Request Paketi
  • 11111111 = TTL(255) –> 3. ICMP Echo Request Paketi
  • 01111111 = TTL(127) –> 4. ICMP Echo Request Paketi
  • “e” harfi için aynı işlem uygulandığında, TTL değerleri aşağıdaki gibi olacaktır.
  • 01-10-01-01 = “e”
  • 01111111 = TTL(127) –> 5. ICMP Echo Request Paketi
  • 10111111 = TTL(191) –> 6. ICMP Echo Request Paketi
  • 01111111 = TTL(127) –> 7. ICMP Echo Request Paketi
  • 01111111 = TTL(127) –> 8. ICMP Echo Request Paketi
  • TTL değerlerimiz mesaj gönderirken şu şekilde değer alabilirler. (63,127,191,255) Ama tabi ki “Lokalde” bu değerlerde olabilirler. Eğer farklı bir ağa gideceksek bu değerler yönlendiricilerden geçeceği için tabi ki de geçtiği yönlendirici kadar azalacaktır.

3-Son olarak, bu mesajlar “ICMP Echo Request” yani ping paketleri aracılığıyla hedefe gönderilir.

Decoder.py ise alıcı cihazda çalıştırılacak araçtır. Bu araç, gönderici cihaz tarafından iletilen mesajın çözümlenmesini sağlayacaktır. Alıcı cihaz, aşağıdaki adımları takip edecektir.

1- Gönderici cihazın gönderdiği “ICMP Echo Request” paketleri, Wireshark yazılımı kullanılarak yakalanır ve “.pcap” uzantılı dosya olarak kaydedilir. Daha sonra, decoder.py aracı çalıştırılır ve “.pcap” dosyası ile kaynak IP adresi belirtilir.

2- Gönderilen her paketin TTL değeri okunur. Bu TTL değerlerinin ilk 2 biti diğer bitlerden ayrılır. Bu bitler yan yana koyulur ve 1 byte elde edilir.(Byte sayısı karakterlerin çeşidine göre değişmektedir. Örneğin ASCII karakterleri 1byte kabul edilmektedir.)

3- Bu byte değerleri Hexadecimal karşılığına çevrilir. Ardından da UTF-8 metne çevirir ve mesaj ekrana yazdırılır.

Şimdi uygulamalı olarak TTL kullanarak gizli mesaj gönderme sürecini gerçekleştirelim. Uygulamamız, görselde belirtilen IP adreslerine sahip cihazlar arasında yapılacaktır.

Ekran goruntusu 2025 05 30 105416

Encoder.py aracını çalıştırarak, önce göndermek istediğimiz mesajı, ardından hedef cihazın IP adresini belirtelim.

Ekran goruntusu 2025 05 30 105735

Gönderme işlemi devam ederken, hedef cihaz üzerinde “Wireshark” ile paketleri dinleyelim. Hedef cihazdan gelen paketleri görmek için Wireshark üzerinde aşağıdaki filtreyi kullanabiliriz.

ip.src==192.168.1.132
Ekran goruntusu 2025 05 30 110519

Ardından, bu dosyayı kaydedelim ve alıcı cihazda “decoder.py” aracını çalıştıralım. Kaydettiğimiz “.pcap” veya “.pcapng” uzantılı dosyanın yolunu programa girelim. (“.pcap” ve “.pcapng” aynı dosya türüdür; “.pcapng”, Wireshark’ın yeni sürümlerinde kullanılan “next generation” uzantısıdır.) Sonrasında, kaynak IP adresini girip mesajın çözülmesini bekleyelim.

Ekran goruntusu 2025 05 30 110818

Bu işlem, IPv4’te olduğu gibi teorik olarak IPv6 için de uygulanabilir.

# encoder.py
from scapy.all import IP, ICMP, send 
import binascii 


def encode_message_to_ttl_bits(message):
   
    hex_data = binascii.hexlify(message.encode('utf-8')).decode('utf-8')
    
 
    bin_data = bin(int(hex_data, 16))[2:].zfill(len(hex_data) * 4)
    
    
    bit_pairs = [bin_data[i:i+2].ljust(2, '0') for i in range(0, len(bin_data), 2)]
    return bit_pairs


def make_ttl_with_bits(bits):
    return int(bits + '111111', 2)  


def send_message_ttl(message, target_ip):
    bit_pairs = encode_message_to_ttl_bits(message) 
    print("[*] Bit pairs to embed:", bit_pairs)

    
    for bits in bit_pairs:
        ttl_value = make_ttl_with_bits(bits)  
        packet = IP(dst=target_ip, ttl=ttl_value)/ICMP() 
        send(packet, verbose=False)  
    print("[+] Mesaj başarıyla gönderildi.")  


if __name__ == "__main__":
    msg = input("Göndermek istediğiniz mesajı girin: ")  
    ip = input("Hedef IP adresini girin: ")  
    send_message_ttl(msg, ip)

# decoder.py
from scapy.all import rdpcap, IP
import binascii

def extract_ttl_bits_from_pcap(pcap_file, source_ip=None):
    packets = rdpcap(pcap_file)
    bitstream = ""

    for pkt in packets:
        if IP in pkt:
            
            if source_ip and pkt[IP].src != source_ip:
                continue

            ttl = pkt[IP].ttl
            ttl_bits = format(ttl, '08b')
            high2bits = ttl_bits[:2]
            bitstream += high2bits

    return bitstream

def bits_to_utf8(bitstream):
    
    if len(bitstream) % 8 != 0:
        bitstream = bitstream[:-(len(bitstream) % 8)]

    bytes_list = [bitstream[i:i+8] for i in range(0, len(bitstream), 8)]
    hex_string = ''.join(format(int(b, 2), '02x') for b in bytes_list)

    try:
        decoded = bytes.fromhex(hex_string).decode('utf-8')
        return decoded
    except Exception as e:
        return f"[!] UTF-8 çözümleme hatası: {str(e)}"

def main():
    pcap_path = input("PCAP dosyasının yolunu girin: ").strip()
    source_ip = input("İsteğe bağlı: Sadece bu IP'den gelen paketleri çöz (Enter = tüm IP'ler): ").strip()
    if source_ip == "":
        source_ip = None

    bitstream = extract_ttl_bits_from_pcap(pcap_path, source_ip)
    print(f"[*] Toplanan bit akışı: {bitstream}")
    
    message = bits_to_utf8(bitstream)
    print(f"[+] Çözülen mesaj: {message}")

if __name__ == "__main__":
    main()

Daha fazla bilgisayar-ağları içeriği için takipte kalın…

About Hüseyin Pala 156 Articles
Junior Network Specialist

Be the first to comment

Leave a Reply

Your email address will not be published.


*