Advertisement
Guest User

Untitled

a guest
Mar 18th, 2025
75
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 5.33 KB | None | 0 0
  1. from pwnagotchi import plugins
  2. import logging
  3. import subprocess
  4. import os
  5. import json
  6. import sys
  7. from multiprocessing.pool import ThreadPool
  8.  
  9. class QuickDic(plugins.Plugin):
  10.     __author__ = 'silentree12th'
  11.     __version__ = '1.5'
  12.     __license__ = 'GPL3'
  13.     __description__ = 'Run a quick dictionary scan against captured handshakes.'
  14.     __dependencies__ = {
  15.         'apt': ['aircrack-ng'],
  16.     }
  17.     __defaults__ = {
  18.         'enabled': True,
  19.         'wordlist_folder': '/home/pi/wordlists/',
  20.         'progress_file': '/home/pi/quickdic_progress.json',
  21.         'face': '(·ω·)',
  22.     }
  23.  
  24.     def __init__(self):
  25.         self.text_to_set = ""
  26.         self.progress = self.load_progress()
  27.  
  28.     def on_loaded(self):
  29.         logging.info('[quickdic] plugin loaded')
  30.         self.options.setdefault('face', '(·ω·)')
  31.         self.options.setdefault('wordlist_folder', '/home/pi/wordlists/')
  32.         self.options.setdefault('progress_file', '/home/pi/quickdic_progress.json')
  33.         self.options.setdefault('enabled', True)
  34.  
  35.         # Restart with PyPy for better performance
  36.         if sys.executable.endswith("python3"):
  37.             logging.info("[quickdic] Restarting with PyPy...")
  38.             os.execv("/usr/bin/pypy3", ["pypy3"] + sys.argv)
  39.  
  40.         # Check if aircrack-ng is installed
  41.         check = subprocess.run(["dpkg", "-l", "aircrack-ng"], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
  42.         if b"aircrack-ng" in check.stdout:
  43.             logging.info('[quickdic] aircrack-ng is installed')
  44.         else:
  45.             logging.warning('[quickdic] aircrack-ng is not installed!')
  46.  
  47.     def load_progress(self):
  48.         """Load progress from the progress file."""
  49.         try:
  50.             with open(self.options['progress_file'], 'r') as f:
  51.                 return json.load(f)
  52.         except FileNotFoundError:
  53.             return {}
  54.  
  55.     def save_progress(self):
  56.         """Save progress to the progress file."""
  57.         with open(self.options['progress_file'], 'w') as f:
  58.             json.dump(self.progress, f)
  59.  
  60.     def try_wordlist(self, args):
  61.         """Attempt to crack the handshake using a specific wordlist."""
  62.         wordlist, filename, bssid = args
  63.         wl_path = os.path.join(self.options['wordlist_folder'], wordlist)
  64.         output_file = f"{filename}.{wordlist}.cracked"
  65.  
  66.         cmd = ["aircrack-ng", filename, "-w", wl_path, "-l", output_file, "-q", "-b", bssid]
  67.  
  68.         try:
  69.             proc = subprocess.run(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, timeout=300)
  70.             if proc.returncode == 0:
  71.                 with open(output_file, 'r') as f:
  72.                     pwd = f.read().strip()
  73.                 return (wordlist, True, pwd)
  74.             return (wordlist, False, None)
  75.         except Exception as e:
  76.             logging.error(f"[quickdic] Error processing {wordlist}: {str(e)}")
  77.             return (wordlist, False, None)
  78.  
  79.     def on_handshake(self, agent, filename, access_point, client_station):
  80.         """Handle a captured handshake."""
  81.         display = agent.view()
  82.         bssid = access_point['mac']
  83.  
  84.         # Skip if already processed
  85.         if filename in self.progress:
  86.             logging.info(f'[quickdic] Handshake {filename} already processed. Skipping...')
  87.             return
  88.  
  89.         # Verify handshake
  90.         result = subprocess.run(["aircrack-ng", filename], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
  91.         if b"1 handshake" not in result.stdout:
  92.             logging.info('[quickdic] No valid handshake')
  93.             return
  94.         else:
  95.             logging.info('[quickdic] Handshake confirmed')
  96.  
  97.         # Get wordlists
  98.         wordlist_dir = self.options['wordlist_folder']
  99.         try:
  100.             files = sorted(os.listdir(wordlist_dir))
  101.         except Exception as e:
  102.             logging.error(f"[quickdic] Error reading wordlist folder: {e}")
  103.             return
  104.  
  105.         wordlists = [f for f in files if f.endswith('.txt')]
  106.         if not wordlists:
  107.             logging.warning("[quickdic] No wordlist files found.")
  108.             return
  109.  
  110.         # Process wordlists in parallel
  111.         pool = ThreadPool(processes=2)
  112.         args = [(f, filename, bssid) for f in wordlists]
  113.         results = pool.map(self.try_wordlist, args)
  114.         pool.close()
  115.         pool.join()
  116.  
  117.         # Check results
  118.         found = False
  119.         for wordlist, success, pwd in results:
  120.             if success:
  121.                 logging.info(f"[quickdic] Password found: {pwd}")
  122.                 self.text_to_set = f"Cracked password: {pwd}"
  123.                 display.set('face', self.options['face'])
  124.                 display.set('status', self.text_to_set)
  125.                 display.update(force=True)
  126.                 found = True
  127.                 break
  128.  
  129.         # Update progress
  130.         self.progress[filename] = "found" if found else "not found"
  131.         self.save_progress()
  132.  
  133.         if not found:
  134.             logging.info("[quickdic] No password found in any wordlist.")
  135.  
  136.     def on_ui_update(self, ui):
  137.         """Update the Pwnagotchi UI."""
  138.         if self.text_to_set:
  139.             ui.set('face', self.options['face'])
  140.             ui.set('status', self.text_to_set)
  141.             self.text_to_set = ""
  142.  
  143.     def on_unload(self, ui):
  144.         """Handle plugin unload."""
  145.         with ui._lock:
  146.             logging.info('[quickdic] plugin unloaded')
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement