|
|
- #nullable enable
- using System;
- using System.Collections.Generic;
- using System.IO;
- using System.Linq;
- using System.Runtime.InteropServices;
- using System.Text;
- using System.Threading.Tasks;
-
- namespace IPA.AntiMalware.ComAPI
- {
- internal class AmsiMemoryStream : IAmsiStream, IDisposable
- {
- private readonly string contentName;
- private readonly byte[] data;
- private readonly GCHandle dataHandle;
-
- private readonly IntPtr session;
- private bool disposedValue;
-
- public AmsiMemoryStream(string contentName, byte[] data, IntPtr session)
- {
- this.data = data;
- dataHandle = GCHandle.Alloc(data, GCHandleType.Pinned);
- this.session = session;
- this.contentName = contentName;
- }
-
- public unsafe void GetAttribute([In] AmsiAttribute attribute, [In] uint dataSize, [Out] byte* buffer, out uint writtenData)
- {
- switch (attribute)
- {
- case AmsiAttribute.AppName:
- writtenData = WriteWString(AmsiConstants.AppName, dataSize, buffer);
- return;
- case AmsiAttribute.Session:
- *(IntPtr*)buffer = session;
- writtenData = (uint)sizeof(IntPtr);
- return;
-
- case AmsiAttribute.ContentName:
- writtenData = WriteWString(contentName, dataSize, buffer);
- return;
-
- case AmsiAttribute.ContentSize:
- *(ulong*)buffer = (ulong)data.Length;
- writtenData = sizeof(ulong);
- return;
-
- case AmsiAttribute.ContentAddress:
- // because our data is pinned, it can't move while this object exists so we can pass out the fixed address
- fixed (byte* dataAddr = data)
- {
- *(byte**)buffer = dataAddr;
- }
- writtenData = (uint)sizeof(IntPtr);
- return;
-
- default:
- throw new NotImplementedException(); // return e_notimpl
- }
-
- static unsafe uint WriteWString(string str, uint dataSize, byte* buffer)
- {
- fixed (char* name = str)
- {
- return (uint)Encoding.Unicode.GetBytes(name, str.Length, buffer, (int)dataSize);
- }
- }
- }
-
- public unsafe void Read([In] ulong position, [In] uint dataSize, [Out] byte* buffer, out uint readSize)
- {
- if (position >= (ulong)data.Length)
- {
- throw new EndOfStreamException();
- }
-
- fixed (byte* dataPtr = data)
- {
- var toRead = Math.Min((ulong)data.Length - position, dataSize);
- Buffer.MemoryCopy(dataPtr + position, buffer, dataSize, toRead);
- readSize = (uint)toRead;
- }
- }
-
- protected virtual void Dispose(bool disposing)
- {
- if (!disposedValue)
- {
- if (disposing)
- {
- // no managed stae to dispose
- }
-
- dataHandle.Free();
- disposedValue = true;
- }
- }
-
- ~AmsiMemoryStream()
- {
- // Do not change this code. Put cleanup code in 'Dispose(bool disposing)' method
- Dispose(disposing: false);
- }
-
- public void Dispose()
- {
- // Do not change this code. Put cleanup code in 'Dispose(bool disposing)' method
- Dispose(disposing: true);
- GC.SuppressFinalize(this);
- }
- }
- }
|