iotsploit-core 0.0.6__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (41) hide show
  1. iotsploit_core/__init__.py +7 -0
  2. iotsploit_core/context.py +27 -0
  3. iotsploit_core/core/__init__.py +0 -0
  4. iotsploit_core/core/base_plugin.py +290 -0
  5. iotsploit_core/core/device_config.py +105 -0
  6. iotsploit_core/core/device_manager.py +942 -0
  7. iotsploit_core/core/device_registry.py +118 -0
  8. iotsploit_core/core/device_scanner.py +74 -0
  9. iotsploit_core/core/device_spec.py +105 -0
  10. iotsploit_core/core/device_store.py +86 -0
  11. iotsploit_core/core/execution_backend.py +464 -0
  12. iotsploit_core/core/execution_queue.py +456 -0
  13. iotsploit_core/core/exploit_manager.py +728 -0
  14. iotsploit_core/core/exploit_spec.py +73 -0
  15. iotsploit_core/core/stream_manager.py +157 -0
  16. iotsploit_core/core/tool_config.py +430 -0
  17. iotsploit_core/core/tool_manager.py +1166 -0
  18. iotsploit_core/core/tool_service.py +936 -0
  19. iotsploit_core/domain/__init__.py +3 -0
  20. iotsploit_core/domain/device.py +70 -0
  21. iotsploit_core/domain/execution_plan.py +29 -0
  22. iotsploit_core/domain/plugin.py +17 -0
  23. iotsploit_core/domain/stream.py +63 -0
  24. iotsploit_core/domain/target.py +243 -0
  25. iotsploit_core/platforms/__init__.py +19 -0
  26. iotsploit_core/platforms/consts.py +25 -0
  27. iotsploit_core/ports/__init__.py +6 -0
  28. iotsploit_core/ports/driver_state_repo.py +15 -0
  29. iotsploit_core/ports/plugin_repo.py +26 -0
  30. iotsploit_core/ports/stream_backend.py +28 -0
  31. iotsploit_core/ports/task_runner.py +22 -0
  32. iotsploit_core/ports/wifi_backend.py +148 -0
  33. iotsploit_core/py.typed +2 -0
  34. iotsploit_core/utils/__init__.py +53 -0
  35. iotsploit_core/utils/exceptions.py +152 -0
  36. iotsploit_core/utils/helpers.py +65 -0
  37. iotsploit_core/utils/iots_logger.py +164 -0
  38. iotsploit_core/utils/result.py +41 -0
  39. iotsploit_core-0.0.6.dist-info/METADATA +117 -0
  40. iotsploit_core-0.0.6.dist-info/RECORD +41 -0
  41. iotsploit_core-0.0.6.dist-info/WHEEL +4 -0
@@ -0,0 +1,118 @@
1
+ from __future__ import annotations
2
+
3
+ import logging
4
+ from typing import Dict, List, Optional
5
+
6
+ from iotsploit_core.core.device_config import DeviceConfigManager
7
+ from iotsploit_core.core.device_scanner import CompositeDeviceScanner, PluginDeviceScanner
8
+ from iotsploit_core.core.device_store import DeviceStore
9
+ from iotsploit_core.domain.device import Device
10
+
11
+ logger = logging.getLogger(__name__)
12
+
13
+ class DeviceRegistry:
14
+ _instance = None
15
+
16
+ def __new__(cls, *args, **kwargs):
17
+ if cls._instance is None:
18
+ cls._instance = super(DeviceRegistry, cls).__new__(cls)
19
+ cls._instance._initialized = False
20
+ return cls._instance
21
+
22
+ def __init__(
23
+ self,
24
+ *,
25
+ driver_manager,
26
+ device_store: DeviceStore | None = None,
27
+ config_manager: DeviceConfigManager | None = None,
28
+ scanner: CompositeDeviceScanner | None = None,
29
+ ):
30
+ if not self._initialized:
31
+ if driver_manager is None:
32
+ raise TypeError("DeviceRegistry requires 'driver_manager' (inject via adapter factory).")
33
+ self.device_store = device_store or DeviceStore()
34
+ self.config_manager = config_manager or DeviceConfigManager()
35
+ self.driver_manager = driver_manager
36
+ self.scanner = scanner or CompositeDeviceScanner(self.device_store)
37
+ self._initialized = True
38
+
39
+ @classmethod
40
+ def get_instance(
41
+ cls,
42
+ *,
43
+ driver_manager,
44
+ device_store: DeviceStore | None = None,
45
+ config_manager: DeviceConfigManager | None = None,
46
+ scanner: CompositeDeviceScanner | None = None,
47
+ ) -> "DeviceRegistry":
48
+ """Get singleton instance (requires injection on first initialization)."""
49
+
50
+ inst = cls(
51
+ driver_manager=driver_manager,
52
+ device_store=device_store,
53
+ config_manager=config_manager,
54
+ scanner=scanner,
55
+ )
56
+ return inst
57
+
58
+ def initialize(self):
59
+ """初始化设备注册表"""
60
+ logger.debug("Initializing device registry...")
61
+
62
+ # 清理现有的扫描器
63
+ self.scanner.clear_scanners()
64
+
65
+ # 为每个驱动创建扫描器
66
+ for driver_name, driver in self.driver_manager.drivers.items():
67
+ scanner = PluginDeviceScanner(self.device_store, driver)
68
+ self.scanner.add_scanner(scanner)
69
+ logger.debug(f"Added scanner for driver: {driver_name}")
70
+
71
+ # 加载配置的设备
72
+ try:
73
+ stored_configs = self.config_manager.load_configs()
74
+ if stored_configs.get('devices'):
75
+ for device_config in stored_configs['devices']:
76
+ try:
77
+ device = self.device_store._dict_to_device(device_config)
78
+ self.device_store.register_device(device, source="static")
79
+ logger.debug(f"Loaded static device: {device.device_id}")
80
+ except Exception as e:
81
+ logger.error(f"Error loading device from config: {e}")
82
+ except Exception as e:
83
+ logger.error(f"Error loading stored configurations: {e}")
84
+
85
+ def scan_devices(self) -> List[Device]:
86
+ """扫描所有可用设备"""
87
+ try:
88
+ discovered_devices = self.scanner.scan()
89
+ # 注册发现的设备
90
+ for device in discovered_devices:
91
+ try:
92
+ self.device_store.register_device(device, source="dynamic")
93
+ except Exception as e:
94
+ logger.error(f"Error registering discovered device: {e}")
95
+ return discovered_devices
96
+ except Exception as e:
97
+ logger.error(f"Error during device scan: {e}")
98
+ return []
99
+
100
+ def merge_devices(self, stored_configs: Dict, discovered_devices: List[Device]):
101
+ """合并存储的配置和发现的设备"""
102
+ # 处理发现的设备
103
+ for device in discovered_devices:
104
+ try:
105
+ self.device_store.register_device(device, source="dynamic")
106
+ except Exception as e:
107
+ logger.error(f"Error registering dynamic device: {e}")
108
+
109
+ # 处理存储的配置
110
+ if stored_configs.get('devices'):
111
+ for device_config in stored_configs['devices']:
112
+ try:
113
+ device_id = device_config.get('device_id')
114
+ if device_id and device_id not in self.device_store.devices:
115
+ device = self.device_store._dict_to_device(device_config)
116
+ self.device_store.register_device(device, source="static")
117
+ except Exception as e:
118
+ logger.error(f"Error registering static device: {e}")
@@ -0,0 +1,74 @@
1
+ from typing import List, Dict, Type
2
+ import logging
3
+ from iotsploit_core.domain.device import Device
4
+ from iotsploit_core.core.device_store import DeviceStore
5
+ from iotsploit_core.core.base_plugin import BaseDeviceDriver
6
+
7
+ logger = logging.getLogger(__name__)
8
+
9
+ class DeviceScanner:
10
+ """设备扫描器基类"""
11
+ def __init__(self, device_store: DeviceStore):
12
+ self.device_store = device_store
13
+
14
+ def scan(self) -> List[Device]:
15
+ """执行设备扫描"""
16
+ return self._perform_scan()
17
+
18
+ def _perform_scan(self) -> List[Device]:
19
+ """实际的扫描实现"""
20
+ raise NotImplementedError("Subclasses must implement _perform_scan()")
21
+
22
+ class PluginDeviceScanner(DeviceScanner):
23
+ """使用插件系统的设备扫描器"""
24
+ def __init__(self, device_store: DeviceStore, driver: BaseDeviceDriver):
25
+ super().__init__(device_store)
26
+ self.driver = driver
27
+
28
+ def _perform_scan(self) -> List[Device]:
29
+ """使用驱动执行扫描"""
30
+ try:
31
+ logger.info(f"Scanning devices using driver: {self.driver.__class__.__name__}")
32
+ result = self.driver.scan()
33
+
34
+ if not result:
35
+ logger.info("No devices found")
36
+ return []
37
+
38
+ devices = result if isinstance(result, list) else [result]
39
+ for device in devices:
40
+ self.device_store.register_device(device, source="dynamic")
41
+
42
+ return devices
43
+
44
+ except Exception as e:
45
+ logger.error(f"Error scanning devices: {str(e)}")
46
+ return []
47
+
48
+ class CompositeDeviceScanner(DeviceScanner):
49
+ """组合多个扫描器的复合扫描器"""
50
+ def __init__(self, device_store: DeviceStore):
51
+ super().__init__(device_store)
52
+ self.scanners: List[DeviceScanner] = []
53
+
54
+ def clear_scanners(self):
55
+ """清理所有已注册的扫描器"""
56
+ self.scanners = []
57
+
58
+ def add_scanner(self, scanner: DeviceScanner):
59
+ """添加一个扫描器"""
60
+ self.scanners.append(scanner)
61
+
62
+ def _perform_scan(self) -> List[Device]:
63
+ """执行所有注册的扫描器"""
64
+ all_devices = []
65
+ for scanner in self.scanners:
66
+ try:
67
+ # 直接调用 _perform_scan 避免重复注册
68
+ devices = scanner._perform_scan()
69
+ all_devices.extend(devices)
70
+ except Exception as e:
71
+ logger.error(f"Error in scanner {scanner.__class__.__name__}: {str(e)}")
72
+ continue
73
+
74
+ return all_devices
@@ -0,0 +1,105 @@
1
+ import pluggy
2
+ import warnings
3
+ from iotsploit_core.domain.device import Device
4
+ from typing import List, Optional
5
+ from enum import Enum
6
+
7
+ hookspec = pluggy.HookspecMarker("device_mgr")
8
+
9
+ """
10
+ Scan -> Init -> Connect -> Commands -> Close
11
+ """
12
+
13
+
14
+ class DeviceState(Enum):
15
+ """Device lifecycle states"""
16
+ UNKNOWN = "unknown"
17
+ DISCOVERED = "discovered" # After scan
18
+ INITIALIZED = "initialized" # After init
19
+ CONNECTED = "connected" # After connect
20
+ ACTIVE = "active" # During command execution
21
+ DISCONNECTED = "disconnected" # After close
22
+ ERROR = "error" # Error state
23
+
24
+ class DevicePluginSpec:
25
+ """Specification for device plugin lifecycle management"""
26
+
27
+ @hookspec
28
+ def scan(self) -> List[Device]:
29
+ """Scan for available devices.
30
+ First step in device lifecycle.
31
+
32
+ Returns:
33
+ list[Device]: A list of discovered devices matching the configuration.
34
+ """
35
+
36
+ @hookspec
37
+ def initialize(self, device: Device) -> bool:
38
+ """Initialize the plugin for a specific device.
39
+ Second step in device lifecycle.
40
+
41
+ Args:
42
+ device: Device to initialize
43
+
44
+ Returns:
45
+ bool: True if initialization successful
46
+ """
47
+
48
+ @hookspec
49
+ def connect(self, device: Device) -> bool:
50
+ """Connect to the device.
51
+ Third step in device lifecycle.
52
+
53
+ Args:
54
+ device: Device to connect to
55
+
56
+ Returns:
57
+ bool: True if connection successful
58
+ """
59
+
60
+ @hookspec
61
+ def command(self, device: Device, command: str) -> Optional[str]:
62
+ """Send a command to the device.
63
+ Only available in CONNECTED state.
64
+
65
+ Args:
66
+ device: Target device
67
+ command: Command string to execute
68
+
69
+ Returns:
70
+ Optional[str]: Command response if any
71
+ """
72
+
73
+ @hookspec
74
+ def reset(self, device: Device) -> bool:
75
+ """Reset the device to its initial state.
76
+ Can be called from any state except UNKNOWN.
77
+
78
+ Args:
79
+ device: Device to reset
80
+
81
+ Returns:
82
+ bool: True if reset successful
83
+ """
84
+
85
+ @hookspec
86
+ def close(self, device: Device) -> bool:
87
+ """Close the device connection.
88
+ Final step in device lifecycle.
89
+
90
+ Args:
91
+ device: Device to close
92
+
93
+ Returns:
94
+ bool: True if closed successfully
95
+ """
96
+
97
+ @hookspec
98
+ def execute(self, device: Device, target: str):
99
+ """Execute an action on the target using the device."""
100
+ warnings.warn(
101
+ "The 'execute' method is deprecated and will be removed in a future release. "
102
+ "Please use the 'command' method instead.",
103
+ DeprecationWarning,
104
+ stacklevel=2
105
+ )
@@ -0,0 +1,86 @@
1
+ from typing import Dict, Optional
2
+ import logging
3
+ from iotsploit_core.domain.device import Device, DeviceType, SerialDevice, SocketCANDevice, USBDevice
4
+ from iotsploit_core.core.device_config import DeviceConfigManager
5
+
6
+ logger = logging.getLogger(__name__)
7
+
8
+ class DeviceStore:
9
+ def __init__(self):
10
+ self.devices = {}
11
+ self.device_sources = {}
12
+ self.config_manager = DeviceConfigManager()
13
+
14
+ def register_device(self, device: Device, source: str = "dynamic"):
15
+ """注册设备并保存其配置"""
16
+ self.devices[device.device_id] = device
17
+ self.device_sources[device.device_id] = source
18
+
19
+ def get_device(self, device_id: str) -> Optional[Device]:
20
+ device = self.devices.get(device_id)
21
+ if not device:
22
+ config = self.config_manager.get_device_config(device_id)
23
+ if config:
24
+ return self._dict_to_device(config)
25
+ return device
26
+
27
+ def _device_to_dict(self, device: Device) -> Dict:
28
+ """将设备对象转换为字典"""
29
+ base_dict = {
30
+ "device_id": device.device_id,
31
+ "name": device.name,
32
+ "device_type": device.device_type.value,
33
+ "attributes": device.attributes
34
+ }
35
+
36
+ if isinstance(device, SerialDevice):
37
+ base_dict.update({
38
+ "port": device.port,
39
+ "baud_rate": device.baud_rate
40
+ })
41
+ elif isinstance(device, USBDevice):
42
+ base_dict.update({
43
+ "vendor_id": device.vendor_id,
44
+ "product_id": device.product_id
45
+ })
46
+ elif isinstance(device, SocketCANDevice):
47
+ base_dict.update({
48
+ "interface": device.interface
49
+ })
50
+
51
+ return base_dict
52
+
53
+ def _dict_to_device(self, data: Dict) -> Device:
54
+ """从字典创建设备对象"""
55
+ device_type = DeviceType(data["device_type"])
56
+
57
+ if device_type == DeviceType.Serial:
58
+ return SerialDevice(
59
+ device_id=data["device_id"],
60
+ name=data["name"],
61
+ port=data.get("port", ""),
62
+ baud_rate=data.get("baud_rate", 115200),
63
+ attributes=data.get("attributes", {})
64
+ )
65
+ elif device_type == DeviceType.USB:
66
+ return USBDevice(
67
+ device_id=data["device_id"],
68
+ name=data["name"],
69
+ vendor_id=data.get("vendor_id", ""),
70
+ product_id=data.get("product_id", ""),
71
+ attributes=data.get("attributes", {})
72
+ )
73
+ elif device_type == DeviceType.CAN:
74
+ return SocketCANDevice(
75
+ device_id=data["device_id"],
76
+ name=data["name"],
77
+ interface=data.get("interface", "can0"),
78
+ attributes=data.get("attributes", {})
79
+ )
80
+ else:
81
+ return Device(
82
+ device_id=data["device_id"],
83
+ name=data["name"],
84
+ device_type=device_type,
85
+ attributes=data.get("attributes", {})
86
+ )