initial commit
This commit is contained in:
@@ -0,0 +1,83 @@
|
||||
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;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,152 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Text.Json;
|
||||
using System.Text.Json.Nodes;
|
||||
using PureCrack.Util;
|
||||
|
||||
namespace PureCrack.Panel;
|
||||
|
||||
public static class SettingsAutoFix
|
||||
{
|
||||
private const string Loopback = "127.0.0.1";
|
||||
|
||||
private const string BackupSuffix = ".purecrack-backup";
|
||||
|
||||
public static string? FindSettingsJson(string panelExe)
|
||||
{
|
||||
string environmentVariable = Environment.GetEnvironmentVariable("PURE_SETTINGS_JSON");
|
||||
if (!string.IsNullOrEmpty(environmentVariable) && File.Exists(environmentVariable))
|
||||
{
|
||||
return environmentVariable;
|
||||
}
|
||||
string directoryName = Path.GetDirectoryName(panelExe);
|
||||
if (directoryName == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
string text = Path.Combine(directoryName, "Settings.json");
|
||||
if (!File.Exists(text))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
return text;
|
||||
}
|
||||
|
||||
public static bool ReorderIpsToLoopbackFirst(string settingsPath)
|
||||
{
|
||||
//IL_01f5: Unknown result type (might be due to invalid IL or missing references)
|
||||
//IL_01fc: Expected O, but got Unknown
|
||||
//IL_0057: Unknown result type (might be due to invalid IL or missing references)
|
||||
//IL_005d: Unknown result type (might be due to invalid IL or missing references)
|
||||
//IL_023c: Unknown result type (might be due to invalid IL or missing references)
|
||||
//IL_0241: Unknown result type (might be due to invalid IL or missing references)
|
||||
//IL_024d: Expected O, but got Unknown
|
||||
if (!File.Exists(settingsPath))
|
||||
{
|
||||
Log.Warn("settings: " + settingsPath + " not found");
|
||||
return false;
|
||||
}
|
||||
string text;
|
||||
try
|
||||
{
|
||||
text = File.ReadAllText(settingsPath);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Log.Warn("settings: read failed: " + ex.Message);
|
||||
return false;
|
||||
}
|
||||
JsonNode val;
|
||||
try
|
||||
{
|
||||
val = JsonNode.Parse(text, (JsonNodeOptions?)null, default(JsonDocumentOptions));
|
||||
}
|
||||
catch (Exception ex2)
|
||||
{
|
||||
Log.Warn("settings: not valid JSON: " + ex2.Message);
|
||||
return false;
|
||||
}
|
||||
JsonObject val2 = (JsonObject)(object)((val is JsonObject) ? val : null);
|
||||
if (val2 == null)
|
||||
{
|
||||
Log.Warn("settings: top-level isn't a JSON object — skipping reorder");
|
||||
return false;
|
||||
}
|
||||
string text2 = null;
|
||||
JsonArray val3 = null;
|
||||
foreach (KeyValuePair<string, JsonNode> item in val2)
|
||||
{
|
||||
if (string.Equals(item.Key, "IPs", StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
JsonNode value = item.Value;
|
||||
JsonArray val4 = (JsonArray)(object)((value is JsonArray) ? value : null);
|
||||
if (val4 != null)
|
||||
{
|
||||
text2 = item.Key;
|
||||
val3 = val4;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (text2 == null || val3 == null)
|
||||
{
|
||||
Log.Warn("settings: no IPs array — skipping reorder");
|
||||
return false;
|
||||
}
|
||||
if (val3.Count > 0)
|
||||
{
|
||||
JsonNode obj = ((JsonNode)val3)[0];
|
||||
if (string.Equals((obj != null) ? obj.GetValue<string>() : null, "127.0.0.1"))
|
||||
{
|
||||
Log.Info("settings: 127.0.0.1 already first in " + text2);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
List<string> list = new List<string> { "127.0.0.1" };
|
||||
foreach (JsonNode item2 in val3)
|
||||
{
|
||||
if (item2 != null)
|
||||
{
|
||||
string value2 = item2.GetValue<string>();
|
||||
if (!string.Equals(value2, "127.0.0.1", StringComparison.Ordinal))
|
||||
{
|
||||
list.Add(value2);
|
||||
}
|
||||
}
|
||||
}
|
||||
string text3 = settingsPath + ".purecrack-backup";
|
||||
if (!File.Exists(text3))
|
||||
{
|
||||
try
|
||||
{
|
||||
File.Copy(settingsPath, text3);
|
||||
}
|
||||
catch (Exception ex3)
|
||||
{
|
||||
Log.Warn("settings: backup failed: " + ex3.Message);
|
||||
}
|
||||
}
|
||||
JsonArray val5 = new JsonArray((JsonNodeOptions?)null);
|
||||
foreach (string item3 in list)
|
||||
{
|
||||
val5.Add<string>(item3);
|
||||
}
|
||||
((JsonNode)val2)[text2] = (JsonNode)(object)val5;
|
||||
string contents = ((JsonNode)val2).ToJsonString(new JsonSerializerOptions
|
||||
{
|
||||
WriteIndented = true
|
||||
});
|
||||
try
|
||||
{
|
||||
File.WriteAllText(settingsPath, contents);
|
||||
}
|
||||
catch (Exception ex4)
|
||||
{
|
||||
Log.Err("settings: write failed: " + ex4.Message);
|
||||
return false;
|
||||
}
|
||||
Log.Ok("settings: reordered " + text2 + " → [" + string.Join(",", list) + "]");
|
||||
return true;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user