KnightCTF 2026 — Reconnaissance Writeup
192.168.1.104'ten 192.168.1.102'ye tam 65535 portluk TCP SYN taraması: her yanıtı SYN-ACK (açık) ve RST (kapalı) olarak sınıflandır; hedef tam olarak iki açık port sunuyor.
KnightCTF 2026 — Reconnaissance
Üç paket yakalamalık bir olay-müdahale senaryosunun ilki. Orta ölçekli bir e-öğrenim şirketi olan "Knight Blog" şüpheli trafik fark ediyor ve paket yakalamalarını teslim ediyor. Bu yakalama, keşif (reconnaissance) aşaması.
- Etkinlik: KnightCTF 2026
- Kategori: Network / Forensics
- Soru: hedefte kaç port açık bulundu?
- Flag formatı:
KCTF{number}
1. Yakalama
Arşivde tek bir dosya var: pcap1.pcapng (yaklaşık 7 MB, ~141k paket). Soru yalnızca bu ilk aşamayla ilgili, dolayısıyla tüm iş tek bir taramayı sınıflandırmak.
Senaryo "şüpheli tarama aktivitesi" vaat ediyor; plan şu:
- Taramayı taşıyan TCP konuşmasını bul — tek bir kaynağın tek bir hedefe yaptığı büyük bağlantı denemesi patlaması.
- Hedefin yanıtlarını açık/kapalı olarak ayır: bir porta SYN'e SYN-ACK ile yanıt veriliyorsa açık, RST ile yanıt veriliyorsa kapalı.
- Farklı açık portları say.
2. Yakalamayı okumak
tshark kurulu değildi; bu yüzden pcapng'i hiçbir sistem kütüphanesine ihtiyaç duymadan ayrıştıran Scapy kullandım:
python3 -m venv venv && ./venv/bin/pip install scapyfrom scapy.all import rdpcap, TCP, IP
from collections import Counter
pkts = rdpcap("pcap1.pcapng")
tcp = [p for p in pkts if p.haslayer(TCP) and p.haslayer(IP)]
# ACK'siz SYN = deneme
syns = [p for p in tcp if (p[TCP].flags & 0x02) and not (p[TCP].flags & 0x10)]
# SYN + ACK = açık portun yanıtı
synack = [p for p in tcp if (p[TCP].flags & 0x12) == 0x12]
print("packets:", len(pkts), "tcp:", len(tcp))
print(Counter((p[IP].src, p[IP].dst) for p in syns).most_common(3))packets: 141259 tcp: 135532
SYN (no ACK) packets: 65574
SYN-ACK packets: 39
top SYN sources:
('192.168.1.104', '192.168.1.102') 65558
('192.168.1.110', '192.168.1.102') 7
('192.168.1.103', '57.155.141.115') 2Tek bir konuşma baskın: 192.168.1.104, 192.168.1.102'ye 65.558 çıplak SYN gönderiyor. Tarayan taraf (192.168.1.104) hedefi (192.168.1.102) süpürüyor; diğer tüm kaynaklar arka plan trafiği. Taranan küme 65.535 TCP portunun tamamını kapsıyor.
3. Açık mı, kapalı mı
Hedefin yanıtlarında yalnızca iki bayrak kombinasyonu önemli: SYN+ACK (0x12) portun açık olduğunu, RST (0x04) kapalı olduğunu gösterir.
scanner, target = "192.168.1.104", "192.168.1.102"
resp = {}
for p in tcp:
if p[IP].src == target and p[IP].dst == scanner:
port = p[TCP].sport
if (p[TCP].flags & 0x12) == 0x12:
resp[port] = "SYN-ACK"
elif p[TCP].flags & 0x04:
resp.setdefault(port, "RST")
open_ports = sorted(pt for pt, r in resp.items() if r == "SYN-ACK")
print("ports responded:", len(resp))
print("OPEN:", open_ports)ports responded: 65535
OPEN: [22, 80]Denenen 65.535 portun hepsi yanıt verdi ve tam olarak ikisi SYN-ACK ile yanıt verdi: SSH (22) ve HTTP (80). Geri kalan her şey RST döndü. Daha önce görülen büyük SYN-ACK sayısı (tarayıcıya 23 paket) o iki porttaki yeniden iletimden ibaret — bir SYN taraması el sıkışmayı hiç tamamlamaz, bu yüzden hedef SYN-ACK'ini yeniden gönderir.
Diğer daha küçük konuşmalarla çapraz kontrol bunu doğruluyor: hedefe dokunan her kaynak aynı iki portta yanıtlandı ve {22, 80} dışındaki hiçbir port RST dışında bir şey döndürmedi.
SYN-ACK from 192.168.1.102 grouped by scanner:
(192.168.1.102, 192.168.1.104) -> [22, 80]
(192.168.1.102, 192.168.1.110) -> [80]
(192.168.1.102, 192.168.1.101) -> [80]
ALL open ports on target 192.168.1.102: [22, 80]4. Yanıt
192.168.1.102'ye karşı yapılan keşif taraması 2 açık port buldu:
22/tcp— SSH80/tcp— HTTP
5. Flag
KCTF{2}Ne düşünüyorsun?
Tepki bırakarak geri bildirim ver