using System; using System.Diagnostics; using System.IO; using System.Net; using System.Net.Sockets; using System.Threading; using PureCrack.Util; namespace PureCrack.Panel; public static class PanelLauncher { public static string BundledPanelPath => Path.Combine(Workspace.Root, "panel", "PureRAT.exe"); public static string DevPanelPath => Path.GetFullPath(Path.Combine(new string[5] { Workspace.Root, "..", "..", "panel", "PureRAT.exe" })); public static string FindExe() { string environmentVariable = Environment.GetEnvironmentVariable("PURE_PANEL_EXE"); if (!string.IsNullOrEmpty(environmentVariable)) { if (File.Exists(environmentVariable)) { return environmentVariable; } Log.Warn("PURE_PANEL_EXE points at " + environmentVariable + " but file doesn't exist — falling back to bundled"); } if (File.Exists(BundledPanelPath)) { return BundledPanelPath; } if (File.Exists(DevPanelPath)) { return DevPanelPath; } throw new FileNotFoundException("PureRAT.exe not found. Looked at:\n - " + BundledPanelPath + " (deployed layout)\n - " + DevPanelPath + " (running from bin\\Release\\ in source tree)\nEither copy PureRAT.exe to one of those, or set PURE_PANEL_EXE env var.\nSee " + Path.Combine(Path.GetDirectoryName(BundledPanelPath), "README.md") + " for bundling instructions."); } public static Process Launch(string panelExe) { Log.Info("launching panel: " + panelExe); Process process = Process.Start(new ProcessStartInfo { FileName = panelExe, UseShellExecute = true, WorkingDirectory = (Path.GetDirectoryName(panelExe) ?? Workspace.Root) }) ?? throw new InvalidOperationException("Process.Start returned null"); Log.Ok($"panel started (PID {process.Id})"); return process; } public static bool WaitForListener(int port, TimeSpan timeout, CancellationToken ct = default(CancellationToken)) { DateTime dateTime = DateTime.UtcNow + timeout; Log.Info($"waiting for panel to bind :{port} (timeout {timeout.TotalSeconds:0}s)"); int num = 0; while (DateTime.UtcNow < dateTime && !ct.IsCancellationRequested) { num++; try { using TcpClient tcpClient = new TcpClient(); if (tcpClient.ConnectAsync(IPAddress.Loopback, port).Wait(500, ct) && tcpClient.Connected) { Log.Ok($":{port} is up (after {num} probes)"); return true; } } catch (Exception) { } Thread.Sleep(500); } return false; } }