iotsploit-exploits 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 (30) hide show
  1. iotsploit_exploits/__init__.py +1 -0
  2. iotsploit_exploits/adb_check/__init__.py +0 -0
  3. iotsploit_exploits/adb_check/adb_check.py +493 -0
  4. iotsploit_exploits/demo/__init__.py +0 -0
  5. iotsploit_exploits/demo/async_sleep_attack.py +106 -0
  6. iotsploit_exploits/demo/stream_data_attack.py +184 -0
  7. iotsploit_exploits/flood_attack/__init__.py +0 -0
  8. iotsploit_exploits/flood_attack/flood_attack.py +129 -0
  9. iotsploit_exploits/flood_attack/syn_flood_attack.py +233 -0
  10. iotsploit_exploits/greatfet_echo.py +103 -0
  11. iotsploit_exploits/greatfet_rubber_duck.py +417 -0
  12. iotsploit_exploits/hydra_cracker/weak_pass.txt +471 -0
  13. iotsploit_exploits/hydra_cracker/weak_pass_simple.txt +5 -0
  14. iotsploit_exploits/hydra_ssh_attack.py +159 -0
  15. iotsploit_exploits/ip_scan/__init__.py +0 -0
  16. iotsploit_exploits/ip_scan/ip_scan.py +196 -0
  17. iotsploit_exploits/nmap_scan/__init__.py +0 -0
  18. iotsploit_exploits/nmap_scan/nmap_scan.py +207 -0
  19. iotsploit_exploits/plugin_ssh.py +146 -0
  20. iotsploit_exploits/rubber_duck_scripts/linux_infogather.txt +126 -0
  21. iotsploit_exploits/rubber_duck_scripts/windows_payload.txt +93 -0
  22. iotsploit_exploits/serial/__init__.py +0 -0
  23. iotsploit_exploits/serial/picocom_serial_reader.py +704 -0
  24. iotsploit_exploits/simple_rubber_duck.py +183 -0
  25. iotsploit_exploits/wifi_scan/__init__.py +0 -0
  26. iotsploit_exploits/wifi_scan/wifi_scan.py +242 -0
  27. iotsploit_exploits-0.0.6.dist-info/METADATA +65 -0
  28. iotsploit_exploits-0.0.6.dist-info/RECORD +30 -0
  29. iotsploit_exploits-0.0.6.dist-info/WHEEL +4 -0
  30. iotsploit_exploits-0.0.6.dist-info/entry_points.txt +16 -0
@@ -0,0 +1,417 @@
1
+ #!/usr/bin/python3
2
+
3
+ import pluggy
4
+ from typing import Optional, Any
5
+ import asyncio
6
+ import os
7
+ import re
8
+ from importlib.resources import files
9
+ from facedancer.errors import EndEmulation
10
+ from iotsploit_core.core.exploit_spec import ExploitResult, AsyncExploitResult
11
+ from iotsploit_core.core.base_plugin import BasePlugin
12
+ from facedancer.devices.keyboard import USBKeyboardDevice
13
+ from facedancer.classes.hid.keyboard import KeyboardModifiers
14
+ from iotsploit_core.utils import iots_logger
15
+
16
+ hookimpl = pluggy.HookimplMarker("exploit_mgr")
17
+
18
+ class RubberDuckPlugin(BasePlugin):
19
+ def __init__(self):
20
+ super().__init__({
21
+ 'Name': 'Rubber Duck',
22
+ 'Description': 'Emulates a USB keyboard to type keystrokes automatically (USB Rubber Duck).',
23
+ 'License': 'GPL',
24
+ 'Author': ['iotsploit'],
25
+ 'RequiresRoot': False,
26
+ 'Parameters': {
27
+ 'payload': {
28
+ 'type': 'str',
29
+ 'required': False,
30
+ 'description': 'Commands to type (each line will be executed as a separate command)',
31
+ 'default': 'echo Hello from Rubber Duck!\nid\nls -la\n'
32
+ },
33
+ 'delay_before_typing': {
34
+ 'type': 'int',
35
+ 'required': False,
36
+ 'description': 'Time to wait in seconds before starting to type',
37
+ 'default': 2
38
+ },
39
+ 'delay_between_lines': {
40
+ 'type': 'float',
41
+ 'required': False,
42
+ 'description': 'Time to wait in seconds between typing each line',
43
+ 'default': 0.5
44
+ },
45
+ 'delay_after_typing': {
46
+ 'type': 'int',
47
+ 'required': False,
48
+ 'description': 'Time to wait in seconds after typing completes before ending the emulation',
49
+ 'default': 1
50
+ },
51
+ 'script_file': {
52
+ 'type': 'str',
53
+ 'required': False,
54
+ 'description': 'Path to a script file containing commands to type',
55
+ 'default': ''
56
+ },
57
+ 'payload_format': {
58
+ 'type': 'str',
59
+ 'required': False,
60
+ 'description': 'Format of the payload: "plain" for plain text or "ducky" for DuckyScript format',
61
+ 'default': 'plain'
62
+ },
63
+ 'target_os': {
64
+ 'type': 'str',
65
+ 'required': False,
66
+ 'description': 'Target operating system for built-in scripts: "windows", "linux", or "none" for custom script',
67
+ 'default': 'none'
68
+ }
69
+ }
70
+ })
71
+ self.device = None
72
+ self.running = False
73
+ self.logger = iots_logger.get_logger("rubber_duck")
74
+
75
+ # Resolve built-in payloads from packaged resources.
76
+ _scripts = files("iotsploit_exploits") / "rubber_duck_scripts"
77
+ self.script_files = {
78
+ 'windows': str(_scripts / 'windows_payload.txt'),
79
+ 'linux': str(_scripts / 'linux_infogather.txt')
80
+ }
81
+
82
+ # Define special key mappings
83
+ self.special_keys = {
84
+ 'CTRL': KeyboardModifiers.MOD_LEFT_CTRL,
85
+ 'SHIFT': KeyboardModifiers.MOD_LEFT_SHIFT,
86
+ 'ALT': KeyboardModifiers.MOD_LEFT_ALT,
87
+ 'GUI': KeyboardModifiers.MOD_LEFT_META,
88
+ 'WINDOWS': KeyboardModifiers.MOD_LEFT_META,
89
+ 'COMMAND': KeyboardModifiers.MOD_LEFT_META, # Mac Command key
90
+ 'OPTION': KeyboardModifiers.MOD_LEFT_ALT, # Mac Option key
91
+ 'ESC': 0x29,
92
+ 'ESCAPE': 0x29,
93
+ 'ENTER': 0x28,
94
+ 'RETURN': 0x28,
95
+ 'TAB': 0x2B,
96
+ 'SPACE': 0x2C,
97
+ 'BACKSPACE': 0x2A,
98
+ 'DELETE': 0x4C,
99
+ 'INSERT': 0x49,
100
+ 'HOME': 0x4A,
101
+ 'END': 0x4D,
102
+ 'PAGEUP': 0x4B,
103
+ 'PAGEDOWN': 0x4E,
104
+ 'UP': 0x52,
105
+ 'DOWN': 0x51,
106
+ 'LEFT': 0x50,
107
+ 'RIGHT': 0x4F,
108
+ 'F1': 0x3A,
109
+ 'F2': 0x3B,
110
+ 'F3': 0x3C,
111
+ 'F4': 0x3D,
112
+ 'F5': 0x3E,
113
+ 'F6': 0x3F,
114
+ 'F7': 0x40,
115
+ 'F8': 0x41,
116
+ 'F9': 0x42,
117
+ 'F10': 0x43,
118
+ 'F11': 0x44,
119
+ 'F12': 0x45,
120
+ 'CAPSLOCK': 0x39,
121
+ }
122
+
123
+ @hookimpl
124
+ def initialize(self, device_plugin: Optional[Any] = None):
125
+ self.logger.info("Initializing RubberDuckPlugin")
126
+
127
+ def custom_facedancer_main(self, device, coroutine):
128
+ """
129
+ Custom implementation of Facedancer's main function that doesn't parse command line arguments.
130
+ This is needed when running inside Django where sys.argv contains Django's arguments.
131
+ """
132
+ self.logger.info("Starting custom Facedancer emulation")
133
+ try:
134
+ # Directly call the device's emulate method with our coroutine
135
+ device.emulate(coroutine)
136
+ self.logger.info("Facedancer emulation completed successfully")
137
+ except EndEmulation as e:
138
+ self.logger.info(f"Facedancer emulation ended: {str(e)}")
139
+ except KeyboardInterrupt:
140
+ self.logger.info("Facedancer emulation interrupted by user")
141
+ except Exception as e:
142
+ raise e
143
+
144
+ async def _parse_ducky_script(self, script):
145
+ """Parse a DuckyScript formatted script into executable commands"""
146
+ commands = []
147
+ delay = 0.5 # Default delay in seconds
148
+
149
+ for line in script.splitlines():
150
+ line = line.strip()
151
+ if not line or line.startswith('REM'): # Comment line
152
+ continue
153
+
154
+ # Handle delay commands
155
+ if line.startswith('DELAY '):
156
+ try:
157
+ delay_ms = int(line.split(' ', 1)[1])
158
+ commands.append(('DELAY', delay_ms / 1000)) # Convert to seconds
159
+ except (ValueError, IndexError):
160
+ self.logger.warning(f"Invalid delay command: {line}")
161
+ continue
162
+
163
+ # Handle STRING command (regular typing)
164
+ if line.startswith('STRING '):
165
+ text = line[7:] # Extract text after 'STRING '
166
+ commands.append(('STRING', text))
167
+ continue
168
+
169
+ # Handle modifier + key combinations like "GUI r"
170
+ parts = line.split()
171
+ if len(parts) == 2 and parts[0] in self.special_keys:
172
+ modifier = parts[0]
173
+ key = parts[1]
174
+ commands.append(('MOD_KEY', (modifier, key)))
175
+ continue
176
+
177
+ # Handle multiple special keys like "CTRL ALT DELETE"
178
+ if all(part in self.special_keys for part in parts):
179
+ commands.append(('KEYS', parts))
180
+ continue
181
+
182
+ self.logger.warning(f"Unrecognized DuckyScript command: {line}")
183
+
184
+ return commands
185
+
186
+ async def _execute_special_keys(self, key_combination):
187
+ """Execute a special key combination"""
188
+ modifiers = 0
189
+ keys = []
190
+
191
+ for key in key_combination:
192
+ if key in ['CTRL', 'SHIFT', 'ALT', 'GUI', 'WINDOWS', 'COMMAND', 'OPTION']:
193
+ modifiers |= self.special_keys[key]
194
+ else:
195
+ keys.append(self.special_keys[key])
196
+
197
+ if not keys: # If only modifiers, add a blank key
198
+ keys = [0]
199
+
200
+ for key in keys:
201
+ # Use type_scancode instead of press_key/release_all_keys
202
+ await self.device.type_scancode(key, modifiers=modifiers, duration=0.05)
203
+
204
+ def _prepare_payload(self, parameters):
205
+ """Prepare payload from parameters - works both in sync and async contexts"""
206
+ parameters = parameters or {}
207
+ delay_before_typing = int(parameters.get('delay_before_typing',
208
+ self.info['Parameters']['delay_before_typing']['default']))
209
+ delay_between_lines = float(parameters.get('delay_between_lines',
210
+ self.info['Parameters']['delay_between_lines']['default']))
211
+ delay_after_typing = int(parameters.get('delay_after_typing',
212
+ self.info['Parameters']['delay_after_typing']['default']))
213
+ payload_format = parameters.get('payload_format',
214
+ self.info['Parameters']['payload_format']['default'])
215
+ target_os = parameters.get('target_os',
216
+ self.info['Parameters']['target_os']['default'])
217
+
218
+ # Determine payload source (target_os, script_file, or direct payload)
219
+ script_file = parameters.get('script_file', self.info['Parameters']['script_file']['default'])
220
+
221
+ # If target_os is specified, use the corresponding built-in script
222
+ if target_os != 'none' and target_os in self.script_files:
223
+ script_file = self.script_files[target_os]
224
+ self.logger.info(f"Using built-in {target_os} script: {script_file}")
225
+ # For built-in scripts, automatically set payload format to ducky
226
+ payload_format = 'ducky'
227
+
228
+ payload = parameters.get('payload', self.info['Parameters']['payload']['default'])
229
+
230
+ if script_file and os.path.exists(script_file):
231
+ self.logger.info(f"Reading payload from script file: {script_file}")
232
+ try:
233
+ with open(script_file, 'r') as f:
234
+ payload = f.read()
235
+ except Exception as e:
236
+ self.logger.error(f"Error reading script file: {str(e)}")
237
+ return None, None, None, f"Failed to read script file: {str(e)}"
238
+ elif script_file and not os.path.exists(script_file):
239
+ self.logger.error(f"Script file not found: {script_file}")
240
+ return None, None, None, f"Script file not found: {script_file}"
241
+
242
+ return payload, payload_format, {
243
+ 'delay_before_typing': delay_before_typing,
244
+ 'delay_between_lines': delay_between_lines,
245
+ 'delay_after_typing': delay_after_typing
246
+ }, None
247
+
248
+ @hookimpl
249
+ def execute(self, target: Optional[Any] = None, parameters: Optional[dict] = None):
250
+ """
251
+ Primary execution method - synchronous version.
252
+ This is the preferred entry point for Celery tasks.
253
+ """
254
+ self.logger.info("Executing RubberDuckPlugin")
255
+
256
+ try:
257
+ # Check if we already have a running instance
258
+ if self.running:
259
+ return ExploitResult(False, "An instance is already running", {})
260
+
261
+ # Prepare payload and get configuration
262
+ payload, payload_format, config, error = self._prepare_payload(parameters)
263
+ if error:
264
+ return ExploitResult(False, error, {})
265
+
266
+ # Initialize USB device
267
+ self.logger.info("Initializing USB keyboard device...")
268
+ try:
269
+ self.device = USBKeyboardDevice()
270
+ self.logger.info(f"USB keyboard device initialized")
271
+ except Exception as e:
272
+ self.logger.error(f"Failed to initialize USB keyboard device: {str(e)}")
273
+ return ExploitResult(False, f"Failed to initialize USB keyboard device: {str(e)}", {})
274
+
275
+ # Set running flag
276
+ self.running = True
277
+
278
+ # Define our typing coroutine
279
+ async def process_commands():
280
+ try:
281
+ self.logger.info(f"Waiting {config['delay_before_typing']} seconds before typing...")
282
+ await asyncio.sleep(config['delay_before_typing'])
283
+
284
+ # Parse the payload based on format
285
+ if payload_format.lower() == 'ducky':
286
+ self.logger.info("Parsing payload as DuckyScript")
287
+ commands = await self._parse_ducky_script(payload)
288
+ else:
289
+ # Plain text format - each line is a command to type
290
+ self.logger.info("Using plain text payload format")
291
+ commands = [('STRING', line) for line in payload.splitlines()]
292
+
293
+ # Process typing commands
294
+ self.logger.info("Running typing commands...")
295
+
296
+ total_commands = len(commands)
297
+ for i, (cmd_type, cmd_data) in enumerate(commands):
298
+ if not self.running:
299
+ self.logger.info("Typing interrupted")
300
+ break
301
+
302
+ try:
303
+ if cmd_type == 'DELAY':
304
+ self.logger.info(f"Waiting for {cmd_data} seconds...")
305
+ await asyncio.sleep(cmd_data)
306
+ elif cmd_type == 'STRING':
307
+ self.logger.info(f"Typing text ({i+1}/{total_commands}): {cmd_data}")
308
+ await self.device.type_string(cmd_data)
309
+ # Add enter key at the end of each command line for plain text mode
310
+ if payload_format.lower() == 'plain':
311
+ await self.device.type_scancode(0x28) # ENTER key
312
+ await asyncio.sleep(0.05)
313
+ elif cmd_type == 'KEYS':
314
+ self.logger.info(f"Executing key combination ({i+1}/{total_commands}): {' '.join(cmd_data)}")
315
+ await self._execute_special_keys(cmd_data)
316
+
317
+ # Handle MOD_KEY (modifier + regular key)
318
+ elif cmd_type == 'MOD_KEY':
319
+ modifier, key = cmd_data
320
+ self.logger.info(f"Executing modifier + key ({i+1}/{total_commands}): {modifier} {key}")
321
+ modifiers = self.special_keys[modifier]
322
+
323
+ # If key is a special key, use its scancode
324
+ if key.upper() in self.special_keys:
325
+ scancode = self.special_keys[key.upper()]
326
+ # Otherwise, type it as a regular character
327
+ else:
328
+ # First press the modifier key
329
+ await self.device.type_string(key, modifiers=modifiers)
330
+ await asyncio.sleep(0.05)
331
+ continue
332
+
333
+ # Use type_scancode with modifier
334
+ await self.device.type_scancode(scancode, modifiers=modifiers, duration=0.05)
335
+
336
+ # Report progress
337
+ progress = (i + 1) / total_commands
338
+ self.logger.info(f"Progress: {progress:.1%}")
339
+
340
+ # Wait between commands
341
+ if i < total_commands - 1:
342
+ await asyncio.sleep(config['delay_between_lines'])
343
+
344
+ except Exception as e:
345
+ self.logger.error(f"Error executing command {i+1}: {str(e)}")
346
+
347
+ self.logger.info(f"Typing complete. Waiting {config['delay_after_typing']} seconds before ending...")
348
+ await asyncio.sleep(config['delay_after_typing'])
349
+
350
+ # Clean end of the emulation
351
+ self.logger.info("Exiting facedancer emulation...")
352
+ raise EndEmulation("Typing completed successfully")
353
+
354
+ except Exception as e:
355
+ self.logger.error(f"Error in command processing: {str(e)}")
356
+ if hasattr(e, '__traceback__'):
357
+ import traceback
358
+ self.logger.error(''.join(traceback.format_tb(e.__traceback__)))
359
+ raise # Re-raise the exception
360
+
361
+ try:
362
+ # Use our custom Facedancer main function to avoid argument parsing issues
363
+ self.logger.info("Starting Facedancer execution...")
364
+ self.custom_facedancer_main(self.device, process_commands())
365
+ self.logger.info("Facedancer execution completed successfully")
366
+ except Exception as e:
367
+ self.logger.error(f"Error in Facedancer execution: {str(e)}")
368
+ if hasattr(e, '__traceback__'):
369
+ import traceback
370
+ self.logger.error(''.join(traceback.format_tb(e.__traceback__)))
371
+ self.running = False
372
+ return ExploitResult(False, f"Facedancer execution failed: {str(e)}", {})
373
+
374
+ # Return success - at this point the operation is complete
375
+ return ExploitResult(True, "RubberDuck executed successfully", {
376
+ "status": "complete",
377
+ "message": "Device has typed all commands"
378
+ })
379
+
380
+ except Exception as e:
381
+ self.running = False
382
+ self.logger.error(f"Error during RubberDuck execution: {str(e)}")
383
+ if hasattr(e, '__traceback__'):
384
+ import traceback
385
+ self.logger.error(''.join(traceback.format_tb(e.__traceback__)))
386
+ return ExploitResult(False, f"RubberDuck failed: {str(e)}", {})
387
+ finally:
388
+ # Reset the running flag
389
+ self.running = False
390
+
391
+ @hookimpl
392
+ def cleanup(self):
393
+ """Clean up resources when plugin execution is finished"""
394
+ self.logger.info("Cleaning up RubberDuckPlugin")
395
+
396
+ try:
397
+ # Signal any running operations to stop
398
+ self.running = False
399
+
400
+ # Disconnect the device if it exists
401
+ if hasattr(self, 'device') and self.device:
402
+ try:
403
+ self.logger.info("Disconnecting USB keyboard device...")
404
+ self.device.disconnect()
405
+ self.logger.info("Keyboard Device disconnected")
406
+ except Exception as e:
407
+ self.logger.error(f"Error disconnecting device: {str(e)}")
408
+ finally:
409
+ self.device = None
410
+
411
+ self.logger.info("Cleanup completed successfully")
412
+
413
+ except Exception as e:
414
+ self.logger.error(f"Error during cleanup: {str(e)}")
415
+ if hasattr(e, '__traceback__'):
416
+ import traceback
417
+ self.logger.error(''.join(traceback.format_tb(e.__traceback__)))