Initial commit — SetecMITM generic IoT MITM framework
Templated from cam-mitm. The camera-specific code (UBox cloud client, CVE verifiers, OAM HMAC signing, fuzzer wordlists) is removed; what's left is the generic core: ARP spoof, DNS spoof, HTTP/HTTPS interception with peek-before-wrap, raw sniffer with conntrack-based original-dst lookup, protocol fingerprinting, intruder detection, packet injection, log rotation, PyQt6 GUI on top of a service Controller. All 'camera' references renamed to 'target' throughout. Configuration moved into ~/.config/setec-mitm/config.json with the Settings tab as the primary editor. Plugin system at targets/<name>/plugin.py for vendor-specific code. See README.md for full setup, plugin authoring, and troubleshooting. Co-authored by Setec Labs.
This commit is contained in:
106
services/sniffer.py
Normal file
106
services/sniffer.py
Normal file
@@ -0,0 +1,106 @@
|
||||
"""Raw packet sniffer — catches all target traffic headed to us on any port"""
|
||||
|
||||
import socket
|
||||
import struct
|
||||
import subprocess
|
||||
from utils.log import log, hexdump, save_raw, C_SUCCESS, C_ERROR, C_TRAFFIC, C_IMPORTANT
|
||||
from utils import proto as proto_id
|
||||
|
||||
|
||||
_orig_dst_cache = {}
|
||||
|
||||
|
||||
def _lookup_orig_dst(src_ip, src_port, proto):
|
||||
key = (src_ip, src_port, proto)
|
||||
if key in _orig_dst_cache:
|
||||
return _orig_dst_cache[key]
|
||||
result = None
|
||||
try:
|
||||
out = subprocess.run(
|
||||
["conntrack", "-L", "-s", src_ip, "-p", proto, "--sport", str(src_port)],
|
||||
capture_output=True, text=True, timeout=2,
|
||||
).stdout
|
||||
for line in out.splitlines():
|
||||
parts = line.split()
|
||||
d_ip = None
|
||||
d_port = None
|
||||
for p in parts:
|
||||
if p.startswith("dst=") and d_ip is None:
|
||||
d_ip = p[4:]
|
||||
elif p.startswith("dport=") and d_port is None:
|
||||
d_port = p[6:]
|
||||
if d_ip and d_port:
|
||||
break
|
||||
if d_ip and d_port:
|
||||
result = f"{d_ip}:{d_port}"
|
||||
break
|
||||
except Exception:
|
||||
result = None
|
||||
_orig_dst_cache[key] = result
|
||||
return result
|
||||
|
||||
|
||||
def run(cfg, flags, running_check):
|
||||
try:
|
||||
sock = socket.socket(socket.AF_PACKET, socket.SOCK_RAW, socket.htons(0x0003))
|
||||
sock.bind((cfg["iface"], 0))
|
||||
sock.settimeout(1)
|
||||
except:
|
||||
log("Sniffer: cannot open raw socket", C_ERROR)
|
||||
return
|
||||
|
||||
flags["sniffer"] = True
|
||||
log("Sniffer: watching all target packets", C_SUCCESS)
|
||||
seen = set()
|
||||
|
||||
while running_check():
|
||||
try:
|
||||
pkt, _ = sock.recvfrom(65535)
|
||||
except socket.timeout:
|
||||
continue
|
||||
except:
|
||||
break
|
||||
if len(pkt) < 34:
|
||||
continue
|
||||
|
||||
eth_proto = struct.unpack("!H", pkt[12:14])[0]
|
||||
if eth_proto != 0x0800:
|
||||
continue
|
||||
|
||||
ip_hdr = pkt[14:34]
|
||||
ihl = (ip_hdr[0] & 0x0F) * 4
|
||||
proto = ip_hdr[9]
|
||||
src_ip = socket.inet_ntoa(ip_hdr[12:16])
|
||||
dst_ip = socket.inet_ntoa(ip_hdr[16:20])
|
||||
|
||||
if src_ip != cfg["target_ip"] or dst_ip != cfg["our_ip"]:
|
||||
continue
|
||||
|
||||
t_start = 14 + ihl
|
||||
|
||||
if proto == 17 and len(pkt) >= t_start + 8:
|
||||
sp, dp = struct.unpack("!HH", pkt[t_start:t_start + 4])
|
||||
if dp == 53:
|
||||
continue
|
||||
payload = pkt[t_start + 8:]
|
||||
key = f"udp:{dp}"
|
||||
if key not in seen:
|
||||
seen.add(key)
|
||||
log(f"SNIFF: new UDP port {sp}->{dp}", C_IMPORTANT)
|
||||
orig = _lookup_orig_dst(src_ip, sp, "udp") or "?"
|
||||
pname = proto_id.detect(payload)
|
||||
proto_id.record(pname)
|
||||
log(f"SNIFF: UDP {cfg['target_ip']}:{sp} -> {dst_ip}:{dp} (orig={orig}) [{pname} {payload[:6].hex()}] ({len(payload)}B)", C_TRAFFIC)
|
||||
log(hexdump(payload), 0)
|
||||
save_raw(cfg["log_dir"], f"sniff_udp{dp}_{sp}", payload)
|
||||
|
||||
elif proto == 6 and len(pkt) >= t_start + 4:
|
||||
sp, dp = struct.unpack("!HH", pkt[t_start:t_start + 4])
|
||||
key = f"tcp:{dp}"
|
||||
if key not in seen:
|
||||
seen.add(key)
|
||||
orig = _lookup_orig_dst(src_ip, sp, "tcp") or "?"
|
||||
log(f"SNIFF: new TCP {cfg['target_ip']}:{sp} -> {dst_ip}:{dp} (orig={orig})", C_IMPORTANT)
|
||||
|
||||
sock.close()
|
||||
flags["sniffer"] = False
|
||||
Reference in New Issue
Block a user