mirror of
https://github.com/smittix/intercept.git
synced 2026-04-24 06:40:00 -07:00
Fix Bluetooth bytes conversion and WiFi monitor mode detection
- Fix "cannot convert 'str' object to bytes" error in BLE identity engine by adding robust _convert_to_bytes() helper that handles bytes, hex strings, bytearrays, and arrays - Improve DBus scanner to safely handle various data types for manufacturer_data and service_data with proper error handling - Add monitor mode interface detection in WiFi scanner to provide clear error message when quick scan is attempted on monitor mode interface Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -305,8 +305,18 @@ class DBusScanner:
|
||||
if mfr_data:
|
||||
for mid, mdata in mfr_data.items():
|
||||
manufacturer_id = int(mid)
|
||||
if isinstance(mdata, dbus.Array):
|
||||
manufacturer_data = bytes(mdata)
|
||||
# Handle various DBus data types safely
|
||||
try:
|
||||
if isinstance(mdata, (bytes, bytearray)):
|
||||
manufacturer_data = bytes(mdata)
|
||||
elif isinstance(mdata, dbus.Array):
|
||||
manufacturer_data = bytes(mdata)
|
||||
elif isinstance(mdata, (list, tuple)):
|
||||
manufacturer_data = bytes(mdata)
|
||||
elif isinstance(mdata, str):
|
||||
manufacturer_data = bytes.fromhex(mdata)
|
||||
except (TypeError, ValueError) as e:
|
||||
logger.debug(f"Could not convert manufacturer data: {e}")
|
||||
break
|
||||
|
||||
# Extract service UUIDs
|
||||
@@ -319,8 +329,17 @@ class DBusScanner:
|
||||
service_data = {}
|
||||
if 'ServiceData' in props:
|
||||
for uuid, data in props['ServiceData'].items():
|
||||
if isinstance(data, dbus.Array):
|
||||
service_data[str(uuid)] = bytes(data)
|
||||
try:
|
||||
if isinstance(data, (bytes, bytearray)):
|
||||
service_data[str(uuid)] = bytes(data)
|
||||
elif isinstance(data, dbus.Array):
|
||||
service_data[str(uuid)] = bytes(data)
|
||||
elif isinstance(data, (list, tuple)):
|
||||
service_data[str(uuid)] = bytes(data)
|
||||
elif isinstance(data, str):
|
||||
service_data[str(uuid)] = bytes.fromhex(data)
|
||||
except (TypeError, ValueError) as e:
|
||||
logger.debug(f"Could not convert service data for {uuid}: {e}")
|
||||
|
||||
# Extract Class of Device (Classic BT)
|
||||
class_of_device = None
|
||||
|
||||
@@ -1157,6 +1157,30 @@ def reset_identity_engine() -> None:
|
||||
_identity_engine = DeviceIdentityEngine()
|
||||
|
||||
|
||||
def _convert_to_bytes(value) -> Optional[bytes]:
|
||||
"""Convert various data types to bytes safely."""
|
||||
if value is None:
|
||||
return None
|
||||
if isinstance(value, bytes):
|
||||
return value
|
||||
if isinstance(value, bytearray):
|
||||
return bytes(value)
|
||||
if isinstance(value, str):
|
||||
# Assume hex string
|
||||
try:
|
||||
return bytes.fromhex(value)
|
||||
except ValueError:
|
||||
# Not a valid hex string, encode as UTF-8
|
||||
return value.encode('utf-8')
|
||||
if isinstance(value, (list, tuple)):
|
||||
# Array of integers (like dbus.Array)
|
||||
try:
|
||||
return bytes(value)
|
||||
except (TypeError, ValueError):
|
||||
return None
|
||||
return None
|
||||
|
||||
|
||||
def ingest_ble_dict(data: dict) -> DeviceSession:
|
||||
"""
|
||||
Ingest BLE observation from dictionary.
|
||||
@@ -1173,9 +1197,9 @@ def ingest_ble_dict(data: dict) -> DeviceSession:
|
||||
adv_type=data.get('adv_type', 'unknown'),
|
||||
adv_flags=data.get('adv_flags'),
|
||||
manufacturer_id=data.get('manufacturer_id'),
|
||||
manufacturer_data=bytes.fromhex(data['manufacturer_data']) if data.get('manufacturer_data') else None,
|
||||
manufacturer_data=_convert_to_bytes(data.get('manufacturer_data')),
|
||||
service_uuids=data.get('service_uuids', []),
|
||||
service_data=bytes.fromhex(data['service_data']) if data.get('service_data') else None,
|
||||
service_data=_convert_to_bytes(data.get('service_data')),
|
||||
local_name=data.get('local_name', data.get('name')),
|
||||
appearance=data.get('appearance'),
|
||||
packet_length=data.get('packet_length'),
|
||||
|
||||
@@ -265,6 +265,36 @@ class UnifiedWiFiScanner:
|
||||
pass
|
||||
return False
|
||||
|
||||
def _is_monitor_mode_interface(self, interface: str) -> bool:
|
||||
"""
|
||||
Check if interface is currently in monitor mode.
|
||||
|
||||
Returns True if:
|
||||
- Interface name ends with 'mon' (common convention)
|
||||
- iw reports type as 'monitor'
|
||||
"""
|
||||
# Quick check by name convention
|
||||
if interface.endswith('mon'):
|
||||
return True
|
||||
|
||||
# Check actual mode via iw
|
||||
if shutil.which('iw'):
|
||||
try:
|
||||
result = subprocess.run(
|
||||
['iw', interface, 'info'],
|
||||
capture_output=True,
|
||||
text=True,
|
||||
timeout=TOOL_TIMEOUT_DETECT,
|
||||
)
|
||||
if result.returncode == 0:
|
||||
# Look for "type monitor" in output
|
||||
if re.search(r'type\s+monitor', result.stdout, re.IGNORECASE):
|
||||
return True
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
return False
|
||||
|
||||
# =========================================================================
|
||||
# Quick Scan
|
||||
# =========================================================================
|
||||
@@ -299,6 +329,17 @@ class UnifiedWiFiScanner:
|
||||
|
||||
result.interface = iface
|
||||
|
||||
# Check if interface is in monitor mode (can't use quick scan tools on monitor interfaces)
|
||||
if self._is_monitor_mode_interface(iface):
|
||||
result.error = (
|
||||
f"Interface '{iface}' appears to be in monitor mode. "
|
||||
"Quick scan requires a managed mode interface. "
|
||||
"Either use a different interface, disable monitor mode, or use deep_scan() with airodump-ng."
|
||||
)
|
||||
result.is_complete = True
|
||||
result.warnings.append("Monitor mode interfaces don't support standard WiFi scanning")
|
||||
return result
|
||||
|
||||
# Select and run parser based on platform/tools
|
||||
# Try multiple tools with fallback on Linux
|
||||
observations = []
|
||||
|
||||
Reference in New Issue
Block a user