Initial commit — SetecSuite Camera MITM Framework

Original tooling from the Camhak research project (camera teardown of a
rebranded UBIA / Javiscam IP camera). PyQt6 GUI on top of a curses TUI on
top of a service controller; per-service start/stop, intruder detection,
protocol fingerprinting, OAM HMAC signing, CVE verifiers, OTA bucket
probe, firmware fetcher, fuzzer, packet injection.

Tabs: Dashboard, Live Log, Intruders, Cloud API, Fuzzer, Inject, CVEs,
Config, Help. Real-time per-packet protocol detection, conntrack-based
original-destination lookup, log rotation at 1 GiB.

See SECURITY_PAPER.md for the full writeup, site/index.html for the
public report, README.md for usage. Run with:
    sudo /usr/bin/python3 gui.py

Co-authored by Setec Labs.
This commit is contained in:
sssnake
2026-04-09 08:14:18 -07:00
commit 800052acc2
38 changed files with 7148 additions and 0 deletions

74
config.py Normal file
View File

@@ -0,0 +1,74 @@
"""Configuration management"""
import json
import os
DEFAULT_CONFIG = {
"camera_ip": "192.168.1.187",
"camera_mac": "14:92:f9:3e:58:0a",
"our_ip": "192.168.1.172",
"router_ip": "192.168.1.1",
"iface": "enP4p65s0",
"log_dir": os.path.expanduser("~/dumps/mitm_logs"),
"api_base": "https://portal.ubianet.com/api",
"api_email": "",
"api_password": "",
"api_token": "",
"device_uid": "",
"device_cam_user": "",
"device_cam_pwd": "",
"rest_port": 9090,
"fuzzer_threads": 5,
"fuzzer_delay": 0.2,
}
CONFIG_FILE = os.path.expanduser("~/setec_suite/cam-mitm/config.json")
class Config:
def __init__(self):
self._data = dict(DEFAULT_CONFIG)
self.load()
def __getitem__(self, key):
return self._data[key]
def __setitem__(self, key, value):
self._data[key] = value
def get(self, key, default=None):
return self._data.get(key, default)
def keys(self):
return self._data.keys()
def items(self):
return self._data.items()
def update(self, d):
self._data.update(d)
def load(self):
if os.path.exists(CONFIG_FILE):
try:
with open(CONFIG_FILE) as f:
self._data.update(json.load(f))
except:
pass
def save(self):
os.makedirs(os.path.dirname(CONFIG_FILE), exist_ok=True)
with open(CONFIG_FILE, "w") as f:
json.dump(self._data, f, indent=2)
def to_dict(self):
return dict(self._data)
def safe_dict(self):
"""Config dict with sensitive values masked"""
d = dict(self._data)
if d.get("api_password"):
d["api_password"] = "***"
if d.get("api_token"):
d["api_token"] = d["api_token"][:20] + "..."
return d