Files
IoT_PreTester_Demo/V4.5/django_project/IoTAnalyzer/analyze/analyze_pcap.py
T
2026-06-24 14:53:14 +02:00

132 lines
4.3 KiB
Python

from scapy.all import rdpcap, Raw, DNS, DNSQR
try:
from scapy.layers.tls.all import TLS
except ImportError:
# Fallback or mock if TLS not available, though we use a try-except block in usage
TLS = None
import re
import os
from IoTAnalyzer.models import UrlRaw, HashRaw
def analyze_pcap_file(pcap_file, raw_dataset_id):
"""
Analyzes a PCAP file and stores found hashes and URLs in the database.
"""
print("Start analyzing...")
# Adjust the path to the file
# Check multiple locations for the file
possible_paths = [
os.path.join('/app/files/uploads', pcap_file), # Mounted frontend uploads
os.path.join('/app/files', pcap_file), # Shared files
os.path.join('Frontend', 'iot-pre-tester-frontend', 'public', 'filesAttachment', pcap_file), # Local dev fallback
]
filepath = None
for path in possible_paths:
if os.path.exists(path):
filepath = path
break
if not filepath:
print(f"Fehler: Datei {pcap_file} nicht gefunden in: {possible_paths}")
return
# Regular expressions for hashes and URLs
hash_pattern = re.compile(r"\b[a-fA-F0-9]{32,64}\b") # MD5, SHA1, SHA256
# Stricter URL pattern:
# 1. Requires http://, https://, or www. (Standard)
# 2. OR Naked domain with AT LEAST 2 dots (e.g. sub.domain.com) to catch cloud URLs but avoid "J.mINT"
url_pattern = re.compile(
r"\b(?:"
r"(?:https?://|www\.)(?:[a-zA-Z0-9.-]+\.[a-zA-Z]{2,6})" # Protocol/www required
r"|"
r"(?:[a-zA-Z0-9-]+\.){2,}[a-zA-Z]{2,6}" # Naked domain with >= 2 dots
r"|"
r"\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}" # IPv4
r")"
r"(?:/[a-zA-Z0-9._%/-]*)?\b"
)
# Load PCAP file
try:
packets = rdpcap(filepath)
except Exception as e:
print(f"Fehler beim Öffnen der PCAP-Datei: {e}")
return
found_hashes = set()
found_urls = set()
# Analyze packets
for pkt in packets:
# 1. DNS Queries (Reliable source for domains)
if pkt.haslayer(DNS) and pkt[DNS].qd:
try:
qname = pkt[DNS].qd.qname.decode('utf-8', errors='ignore')
if qname.endswith('.'):
qname = qname[:-1]
if qname:
found_urls.add(qname)
except Exception:
pass
# 2. TLS Server Name Indication (SNI)
# Attempt to extract SNI if TLS layer is present
if TLS and pkt.haslayer(TLS):
try:
# Iterate through TLS messages to find ClientHello and extensions
if hasattr(pkt[TLS], 'msg'):
for msg in pkt[TLS].msg:
if hasattr(msg, 'ext'):
for ext in msg.ext:
if hasattr(ext, 'servernames'):
for servername in ext.servernames:
if hasattr(servername, 'servername'):
sni = servername.servername.decode('utf-8', errors='ignore')
if sni:
found_urls.add(sni)
except Exception:
pass
# 3. Raw Payload (Fallback with strict regex)
if pkt.haslayer(Raw): # Check whether the packet has a payload
payload = pkt[Raw].load.decode(errors='ignore')
# Search for hashes
found_hashes.update(hash_pattern.findall(payload))
# Search for URLs
found_urls.update(url_pattern.findall(payload))
# Store results in the database
save_urls_to_database(found_urls, raw_dataset_id)
save_hashes_to_database(found_hashes, raw_dataset_id)
print("Done analyzing.")
def save_urls_to_database(urls, raw_dataset_id):
"""
Stores extracted URLs in the database.
"""
for url in urls:
UrlRaw.objects.create(
raw_dataset_id=raw_dataset_id,
url=url
)
def save_hashes_to_database(hashes, raw_dataset_id):
"""
Stores extracted hashes in the database.
"""
for hash_value in hashes:
HashRaw.objects.create(
raw_dataset_id=raw_dataset_id,
hash_value=hash_value
)