Files
bigbrother/utils/bettercap_api.py
T
n0mad1k 62a1010ab4 Add Phase 1 utility modules: crypto, networking, logging, stealth, resource, permissions, config_loader, bettercap_api
9 files in utils/ providing the shared infrastructure layer:
- crypto: AES-256-GCM file encryption, argon2id/PBKDF2 key derivation, HKDF network unlock, LUKS container management
- networking: interface detection, MAC/IP helpers, BPF compilation via libpcap ctypes, gratuitous ARP, VLAN creation
- logging: encrypted log writer (BBLogger) with rotation, per-module files, stdout suppression for stealth
- stealth: process rename via prctl, cmdline spoofing, sysctl helpers, timestomping, core dump disable
- resource: hardware tier detection (OPi Zero 3 / Pi Zero / generic) via /proc/device-tree and cpuinfo, resource monitoring
- permissions: root/capability checks via capget ctypes, privilege dropping, directory permission enforcement
- config_loader: YAML merge hierarchy (hardware_tiers -> bigbrother -> modules -> stealth -> CLI), tier auto-detection, SIGHUP reload
- bettercap_api: REST client with per-session random credentials, session/events/command methods
2026-03-18 08:11:25 -04:00

99 lines
3.3 KiB
Python

#!/usr/bin/env python3
"""REST client for bettercap API."""
import secrets
import string
from typing import Any, Dict, List, Optional
import requests
from requests.auth import HTTPBasicAuth
class BettercapAPI:
def __init__(
self,
host: str = "127.0.0.1",
port: int = 8083,
user: str = "bb",
password: Optional[str] = None,
timeout: int = 10,
):
self.host = host
self.port = port
self.user = user
self.password = password or self._generate_password()
self.timeout = timeout
self._base_url = f"http://{host}:{port}/api"
self._auth = HTTPBasicAuth(self.user, self.password)
self._session = requests.Session()
self._session.auth = self._auth
self._session.headers.update({"Content-Type": "application/json"})
@staticmethod
def _generate_password(length: int = 32) -> str:
alphabet = string.ascii_letters + string.digits
return "".join(secrets.choice(alphabet) for _ in range(length))
def _request(self, method: str, endpoint: str, **kwargs) -> requests.Response:
url = f"{self._base_url}/{endpoint.lstrip('/')}"
kwargs.setdefault("timeout", self.timeout)
try:
resp = self._session.request(method, url, **kwargs)
resp.raise_for_status()
return resp
except requests.exceptions.ConnectionError:
raise ConnectionError(f"Cannot connect to bettercap at {self.host}:{self.port}")
except requests.exceptions.Timeout:
raise TimeoutError(f"Request to bettercap timed out after {self.timeout}s")
def run(self, command: str) -> Dict[str, Any]:
resp = self._request("POST", "session", json={"cmd": command})
return resp.json()
def get_session(self) -> Dict[str, Any]:
resp = self._request("GET", "session")
return resp.json()
def get_events(self, since: Optional[int] = None) -> List[Dict[str, Any]]:
params = {}
if since is not None:
params["n"] = since
resp = self._request("GET", "events", params=params)
return resp.json()
def is_alive(self) -> bool:
try:
self.get_session()
return True
except (ConnectionError, TimeoutError, requests.exceptions.RequestException):
return False
def start_module(self, module: str) -> Dict[str, Any]:
return self.run(f"{module} on")
def stop_module(self, module: str) -> Dict[str, Any]:
return self.run(f"{module} off")
def set_parameter(self, param: str, value: str) -> Dict[str, Any]:
return self.run(f"set {param} {value}")
def get_hosts(self) -> List[Dict[str, Any]]:
session = self.get_session()
return session.get("lan", {}).get("hosts", [])
def load_caplet(self, caplet_path: str) -> Dict[str, Any]:
return self.run(f"caplet.load {caplet_path}")
@property
def credentials(self) -> Dict[str, str]:
return {"user": self.user, "password": self.password}
@property
def api_flags(self) -> List[str]:
return [
"-api-rest-address", self.host,
"-api-rest-port", str(self.port),
"-api-rest-username", self.user,
"-api-rest-password", self.password,
]