Universal 2026 — Carrier Lock Çözüm Yazısı
Otomatik olarak çerçevelenmeyi reddeden ham bir uydu aşağı bağlantısı. CCSDS telemetri yapısını tanıyın, PN9 sözde-rastgeleleştiricisini geri alın, uzay paketi akışını yeniden birleştirin; bayrak, parçalanmış bir mesaj taşıyan tek bir sanal kanaldan çıkıyor.
Universal 2026 — Carrier Lock
Bir uzay adli bilişim sorusu. Bize bir yer istasyonunun zayıf, tekrarlayan bir yayından çektiği "ham bitler" veriliyor — çerçeveleme yok, üst veri yok, sadece bir blob. Görev, taşıyıcıya kilitlenip ne taşıdığını okumak.
- Etkinlik: Universal 2026
- Kategori: Adli Bilişim (Forensics)
- Dosya:
downlink.bin - Bayrak formatı:
uctf{...}
1. Blob
$ file downlink.bin
downlink.bin: data
$ ls -l downlink.bin
-rw-r--r-- 1 user staff 22616 downlink.binTanınabilir hiçbir kapsayıcısı olmayan, yüksek entropili 22.616 bayt "veri". İpucu, otomatik olarak çerçevelenemediğini söylüyordu ki bu uzay telemetrisi için normaldir: bir kod çözücü, analistin önce bulması gereken bir işaretçiye senkronize olur.
2. Çerçeve işaretçisini bulma
CCSDS telemetri transfer çerçeveleri 4 baytlık bir Attached Sync Marker ile sınırlandırılır. Bunu aradığımızda eşit aralıklı isabetler dönüyor:
data = open("downlink.bin", "rb").read()
i, offsets = 0, []
while True:
j = data.find(b"\x1a\xcf\xfc\x1d", i)
if j == -1:
break
offsets.append(j)
i = j + 4
print(len(offsets)) # 22
print([b - a for a, b in zip(offsets, offsets[1:])]) # [1028, 1028, ...]1A CF FC 1D CCSDS Attached Sync Marker'dır. Toplam 22 tane var, her biri 1028 bayt arayla: 4 baytlık işaretçi artı 1024 baytlık transfer çerçevesi. Bu da 22 × 1028 = 22.616 bayt eder — dosyanın tamamı, tam olarak.
Yani yakalama, 22 sabit uzunlukta transfer çerçevesidir. Ama çerçeve gövdeleri hâlâ gürültü, çünkü CCSDS çerçeveleri iletilmeden önce sözde-rastgeleleştirilir.
3. PN9 sözde-rastgeleleştiricisini geri alma
CCSDS, uzun özdeş bit dizilerinden kaçınmak için bir PN9 rastgeleleştiricisi (polinom x⁸ + x⁷ + x⁵ + x³ + 1) uygular. Bu, sabit bir diziyle bayt bazında XOR'dur ve her transfer çerçevesinin başında sıfırlanır. LFSR'yi yeniden uygulayıp her 1024 baytlık gövdeyi XOR'lamak bunu geri alır:
def pn9(n):
reg, out = 0xFF, bytearray()
for _ in range(n):
b = 0
for _ in range(8):
b = (b << 1) | (reg & 1)
fb = ((reg >> 7) ^ (reg >> 5) ^ (reg >> 3) ^ (reg >> 0)) & 1
reg = ((reg >> 1) | (fb << 7)) & 0xFF
out.append(b)
return bytes(out)
ks = pn9(1024)
frames = [bytes(a ^ b for a, b in zip(data[o+4:o+1028], ks)) for o in offsets]Artık her çerçevenin ilk altı baytı temiz biçimde çözülüyor — bunlar CCSDS birincil başlığıdır:
frame 0 header: 0a b0 00 00 18 00
frame 1 header: 0a b0 01 01 18 0e
frame 2 header: 0a b0 02 02 18 ...Sürüm bitleri, uzay aracı kimliği (171) ve çerçeve sayaçları olması gerektiği gibi artıyor. Rastgeleleştirici gitti ve çerçeveler gerçek.
4. Paket akışını yeniden birleştirme
Her çerçevenin 1018 baytlık veri alanı (1024 eksi 6 baytlık birincil başlık) kendi içinde tamamlanmış değildir. Çerçeve çerçeve ayrıştırmak frame 1'de anında taşır — paket akışı çerçeve sınırları boyunca süreklidir. Veri alanlarını tek bir akışta birleştirip CCSDS Space Packet yapısıyla (6 baytlık başlık) yürümek bunu düzeltir:
stream = b"".join(f[6:] for f in frames)
o, counts = 0, {}
while o + 6 <= len(stream):
b0, b1, b2, b3, b4, b5 = stream[o:o+6]
apid = ((b0 & 0x07) << 8) | b1
dl = ((b4 << 8) | b5) + 1 # uzunluk alanı (boyut - 1)
payload = stream[o+6:o+6+dl]
counts[apid] = counts.get(apid, 0) + 1
o += 6 + dl
print(counts)
# {200: 424, 300: 424, 400: 424, 250: 9, 2047: 1}Üç uygulama kimliği baskın (200, 300, 400 ve her biri 424 paket) — bu ev idaresi telemetrisi, tekrarlayan ve sıkıcı bir desen. APID 2047 tek bir 0x90 baytı paketi, saf dolgu. Ve APID 250 tam dokuz kez görünüyor. İşte ilginç olan bu.
5. APID 250 üzerindeki mesaj
Sadece APID-250 yüklerini çıkarıp paket sıra sayısına (başlığın üçüncü baytı) göre sıralamak mesajı yeniden birleştirir:
msg = [(pkt_seq, payload) for ... if apid == 250]
flag = "".join(p for _, p in sorted(msg))
print(flag)# dosya sırası (ev idaresiyle iç içe, sırasız):
# 'uctf' '1g' '{s1g' 'n4l_' '1n}' '0wn_' '0r' 'unkn' '0f_'
# sıra sayısına göre 0..8 sıralandıktan sonra:
uctf{s1gn4l_0f_unkn0wn_0r1g1n}Bayrak metni dokuz küçük pakete bölünmüş ve telemetri akışı boyunca dağıtılmıştı. 0'dan 8'e kadar sıra sayıları onları tekrar sıraya koyuyor.
6. Bayrak
uctf{s1gn4l_0f_unkn0wn_0r1g1n}Bilinmeyen kaynaklı sinyal. Zincir — senkron işaretçisi, PN9 geri rastgeleleştirmesi, sürekli paket yeniden birleştirme, sıra düzeni — herhangi bir CCSDS yakalaması için standart iş akışıdır. Üç aşamalı tuzak şudur: çerçeveler işaretçiyi bulana kadar gürültü gibi görünür, geri rastgeleleştirene kadar çöp gibi görünür ve veri alanlarını çerçeve başına değil de tek bir sürekli akış olarak ele alana kadar bozuk görünür.
Ne düşünüyorsun?
Tepki bırakarak geri bildirim ver