Selamlar arkadaşlar biraz değişik eskiden hazırladığım konunun daha detaylı bir versiyonunu açıklayıcı bir şekilde tekrardan ele alıp resimli bir şekilde anlatılır hale getirmek için uğraşacağım umarım kullanmak isteyen arkadaşlara şimdiden yardımcı olur.
KisMAC, temelde passive wireless packet sniffing prensibi ile çalışır. Aktif olarak ağ ile bağlantı kurmaz bunun yerine monitor mode destekleyen bir wireless network interface üzerinden havadaki 802.11 frame lerini dinler.
Bu süreç içerisinde şu adımları uygular:
Wireless card monitor mode a alınır
- Beacon frame ler dinlenir
- ESSID, BSSID, encryption type ayrıştırılır
- Paketler PCAP formatında loglanır
- Analiz modülleri devreye girer
Monitor Mode ve Paket Yakalama Mantığı Nedir ?
KisMAC’in temelini oluşturan işlem, aslında paket yakalama döngüsüdür. alta vereceğim örnek Python+libpcap Mantığını göstermek içindir:
Kod:
from scapy.all import sniff, Dot11
def packet_handler(pkt):
if pkt.haslayer(Dot11):
if pkt.type == 0 and pkt.subtype == 8: # Beacon frame
ssid = pkt.info.decode(errors="ignore")
bssid = pkt.addr2
print(f"SSID: {ssid} | BSSID: {bssid}")
sniff(iface="wlan0mon", prn=packet_handler, store=0)
Bu kodda:
Dot11 katmanı IEEE 802.11 frame lerini temsil eder
Beacon frame ler ağın varlığını göstermektedir.
SSID ve BSSID pasif şekilde elde edilir.
Şifreleme Yöntemi ve Analizi ( Encryption Detection)
Bir kablosuz ağın güvenliği, kullanılan encryption protocol ile direk ilişkilidir. KisMAC,beacon frame içindeki capability information alanını analiz ederek bu bilgiyi gün yüzüne çıkarır.Mantığı kavrama nız için bir örnek ile anlatayım
Kod:
def detect_encryption(pkt):
cap = pkt.sprintf("{Dot11Beacon.cap%}")
if "privacy" in cap:
return "Encrypted (WEP/WPA)"
else:
return "Open Network"
Bu kod içerisinde:
Kod:
def detect_encryption(pkt):
cap = pkt.sprintf("{Dot11Beacon.cap%}")
if "privacy" in cap:
return "Encrypted (WEP/WPA)"
else:
return "Open Network"
1) Privacy bit set edilmişse ağ şifreli olarak kabul edilir.
2) Detaylı analiz ile WEP,WPA veya WPA2 ayrımı yapabilir.
Handshake ve Güvenlik Analiz Mantığını Kavrayalım.
KisMAC, uygun donanım ile WPA handshake capture işlemini destekler. bu desteklemedeki amaç handshake in analiz edilmesi, doğrudan kırılması değil.Örnek bir handshake tespit mantığı şu şekilde olmaktadır:
Kod:
if pkt.haslayer(Dot11) and pkt.type == 2:
if pkt.addr1 and pkt.addr2:
print("Data frame detected, possible handshake traffic")
Bu kodların anlatmaya çalıştığı şey ise :
Offline analiz için PCAP dosyasına kaydedilmesi
Daha sonrası için güvenlik değerlendirme yapması için.
Bu noktada brute force veya dictionary attack yalnızca yetkili penetration testing senaryolarında değerlendirilmelidir.
Şimdi ise sizlere python üzerinden küçük bir .pcap/ .pcapng dosyasını ofline analiz eden ağları sınıflandıran (Open/WEP/WPA/WPA2/WPA3 gibi) ve rapor üreten bir kod bırakıyorum kodu inceleyerek biraz da olsa fikir sahibi olabilirsiniz.
Kod:
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
wifi_audit_from_pcap.py
Offline 802.11 (Wi-Fi) PCAP analizi: Beacon/Probe Response frame'lerinden SSID/BSSID/Encryption tespiti.
Amaç: Akademik/defansif analiz. Canlı yakalama (sniffing) yapmaz.
Kullanım:
python wifi_audit_from_pcap.py -i capture.pcap -o report.json
python wifi_audit_from_pcap.py -i capture.pcap --csv report.csv
"""
from __future__ import annotations
import argparse
import csv
import json
import sys
from dataclasses import dataclass, asdict
from typing import Dict, Optional, Tuple
try:
from scapy.all import rdpcap
from scapy.layers.dot11 import Dot11, Dot11Beacon, Dot11ProbeResp, Dot11Elt
except Exception as e:
print("Hata: scapy import edilemedi. Kurulum için: pip install scapy", file=sys.stderr)
raise
@dataclass
class NetworkRecord:
ssid: str
bssid: str
channel: Optional[int]
encryption: str
wps: bool
seen_frames: int
def _get_ssid(pkt) -> str:
"""SSID, Dot11Elt(ID=0) içinden okunur. Gizli SSID durumunda boş gelebilir."""
ssid = ""
elt = pkt.getlayer(Dot11Elt)
while elt is not None:
if getattr(elt, "ID", None) == 0: # SSID element
try:
ssid = (elt.info or b"").decode(errors="ignore")
except Exception:
ssid = ""
break
elt = elt.payload.getlayer(Dot11Elt)
return ssid if ssid else "<hidden>"
def _get_channel(pkt) -> Optional[int]:
"""Channel, Dot11Elt(ID=3) DS Parameter Set ile gelebilir."""
elt = pkt.getlayer(Dot11Elt)
while elt is not None:
if getattr(elt, "ID", None) == 3 and elt.info:
# 1 byte channel
return int(elt.info[0])
elt = elt.payload.getlayer(Dot11Elt)
return None
def _has_wps(pkt) -> bool:
"""WPS çoğunlukla vendor specific IE (ID=221) içinde 00:50:F2:04 OUI ile işaretlenir."""
elt = pkt.getlayer(Dot11Elt)
while elt is not None:
if getattr(elt, "ID", None) == 221 and elt.info and len(elt.info) >= 4:
oui = elt.info[:4]
if oui == b"\x00\x50\xF2\x04":
return True
elt = elt.payload.getlayer(Dot11Elt)
return False
def _detect_encryption(pkt) -> str:
"""
Basit sınıflandırma:
- privacy bit yoksa: Open
- RSN (ID=48) varsa: WPA2/WPA3 (heuristic)
- Vendor WPA (ID=221 + 00:50:F2:01) varsa: WPA
- privacy bit var ama RSN/WPA yoksa: muhtemelen WEP (veya eski/özel)
"""
# Dot11Beacon / ProbeResp capability info: "privacy" -> şifreleme var
cap = pkt.sprintf("{Dot11Beacon.cap%}") if pkt.haslayer(Dot11Beacon) else pkt.sprintf("{Dot11ProbeResp.cap%}")
privacy = "privacy" in (cap or "").lower()
has_rsn = False
has_wpa = False
rsn_suggests_wpa3 = False
elt = pkt.getlayer(Dot11Elt)
while elt is not None:
if getattr(elt, "ID", None) == 48: # RSN
has_rsn = True
# WPA3'ü PCAP'ten kesin söylemek zordur; bazı RSN alanları SAE (AKM=8) işaret edebilir.
# Burada basit bir heuristic uyguluyoruz: RSN info içinde 0x00 0x0f 0xac 0x08 dizisi (SAE AKM) aranır.
info = elt.info or b""
if b"\x00\x0f\xac\x08" in info:
rsn_suggests_wpa3 = True
if getattr(elt, "ID", None) == 221 and elt.info and len(elt.info) >= 4:
# WPA vendor IE: 00:50:F2:01
if elt.info[:4] == b"\x00\x50\xF2\x01":
has_wpa = True
elt = elt.payload.getlayer(Dot11Elt)
if not privacy:
return "Open"
if has_rsn and rsn_suggests_wpa3:
return "WPA3 (heuristic)"
if has_rsn:
return "WPA2 (RSN)"
if has_wpa:
return "WPA (vendor IE)"
# privacy var ama RSN/WPA yok: çoğu zaman WEP/legacy
return "WEP/Legacy (heuristic)"
def analyze_pcap(path: str) -> Dict[str, NetworkRecord]:
pkts = rdpcap(path)
networks: Dict[str, NetworkRecord] = {}
for pkt in pkts:
if not pkt.haslayer(Dot11):
continue
# Beacon veya Probe Response’lar ağ bilgisini taşır
if not (pkt.haslayer(Dot11Beacon) or pkt.haslayer(Dot11ProbeResp)):
continue
dot11 = pkt.getlayer(Dot11)
bssid = (dot11.addr2 or "").lower().strip()
if not bssid:
continue
ssid = _get_ssid(pkt)
channel = _get_channel(pkt)
enc = _detect_encryption(pkt)
wps = _has_wps(pkt)
if bssid not in networks:
networks[bssid] = NetworkRecord(
ssid=ssid,
bssid=bssid,
channel=channel,
encryption=enc,
wps=wps,
seen_frames=1,
)
else:
# daha iyi veri gelirse güncelle
rec = networks[bssid]
rec.seen_frames += 1
if rec.ssid == "<hidden>" and ssid != "<hidden>":
rec.ssid = ssid
if rec.channel is None and channel is not None:
rec.channel = channel
# “daha güçlü” sınıflandırmayı koru
# Open < WEP/Legacy < WPA < WPA2 < WPA3
rank = {"Open": 0, "WEP/Legacy (heuristic)": 1, "WPA (vendor IE)": 2, "WPA2 (RSN)": 3, "WPA3 (heuristic)": 4}
if rank.get(enc, 0) > rank.get(rec.encryption, 0):
rec.encryption = enc
rec.wps = rec.wps or wps
return networks
def print_summary(networks: Dict[str, NetworkRecord]) -> None:
items = list(networks.values())
items.sort(key=lambda x: (x.encryption, x.ssid))
print("\nTespit edilen ağlar (offline PCAP analizi):\n")
print(f"{'SSID':30} {'BSSID':17} {'CH':>3} {'ENC':22} {'WPS':>3} {'FRAMES':>6}")
print("-" * 92)
for n in items:
ch = str(n.channel) if n.channel is not None else "-"
wps = "Yes" if n.wps else "No"
print(f"{n.ssid[:30]:30} {n.bssid:17} {ch:>3} {n.encryption[:22]:22} {wps:>3} {n.seen_frames:>6}")
# Basit risk notları (defansif)
open_n = sum(1 for n in items if n.encryption == "Open")
wep_n = sum(1 for n in items if n.encryption.startswith("WEP"))
wps_n = sum(1 for n in items if n.wps)
print("\nDefansif notlar:")
if open_n:
print(f"- {open_n} adet Open ağ görüldü: Kurumsal kullanımda önerilmez.")
if wep_n:
print(f"- {wep_n} adet WEP/Legacy ağ görüldü: Modern standartlara göre zayıf kabul edilir.")
if wps_n:
print(f"- {wps_n} ağda WPS işareti var: Kurumsal güvenlik politikalarında genellikle kapatılması önerilir.")
if not (open_n or wep_n or wps_n):
print("- Bu PCAP’te bariz düşük seviye (Open/WEP/WPS) işaretleri az veya yok.")
def save_json(networks: Dict[str, NetworkRecord], out_path: str) -> None:
payload = {bssid: asdict(rec) for bssid, rec in networks.items()}
with open(out_path, "w", encoding="utf-8") as f:
json.dump(payload, f, ensure_ascii=False, indent=2)
def save_csv(networks: Dict[str, NetworkRecord], out_path: str) -> None:
fields = ["ssid", "bssid", "channel", "encryption", "wps", "seen_frames"]
with open(out_path, "w", newline="", encoding="utf-8") as f:
w = csv.DictWriter(f, fieldnames=fields)
w.writeheader()
for rec in networks.values():
w.writerow(asdict(rec))
def main() -> int:
p = argparse.ArgumentParser(description="Offline Wi-Fi (802.11) PCAP security analyzer (defensive).")
p.add_argument("-i", "--input", required=True, help="PCAP/PCAPNG dosyası (ör: capture.pcap)")
p.add_argument("-o", "--output", help="JSON rapor çıktısı (ör: report.json)")
p.add_argument("--csv", help="CSV rapor çıktısı (ör: report.csv)")
args = p.parse_args()
networks = analyze_pcap(args.input)
if not networks:
print("Bu dosyada Beacon/Probe Response bulunamadı veya 802.11 paketleri yok.", file=sys.stderr)
return 2
print_summary(networks)
if args.output:
save_json(networks, args.output)
print(f"\nJSON rapor kaydedildi: {args.output}")
if args.csv:
save_csv(networks, args.csv)
print(f"CSV rapor kaydedildi: {args.csv}")
return 0
if __name__ == "__main__":
raise SystemExit(main())
Kurulumu ise
Kod:
pip install scapy
Kod:
python wifi_audit_from_pcap.py -i capture.pcap -o report.json --csv report.csv
Kısa bir konu anlatımı olduğunun farkındayım yakın zamanda konu üzerine tekrardan bir yazı yazıp bu sefer anlatmadığım veyahut bu yazıda az belirtiğim şeyleri yazacağım tekrardan umarım işinize yarar iyi forumlar
Saygılarımla.
