Files
VXUG-Papers/Hells Gate/C# Implementation/SharpHellsGate/Module/MemoryUtil.cs
T
2020-10-11 00:53:07 -05:00

143 lines
5.9 KiB
C#

using System;
using System.IO;
using System.Runtime.InteropServices;
using System.Text;
namespace SharpHellsGate.Module {
/// <summary>
/// Used to manipulate and extract information from a memory stream.
/// In this case the memory stream is the NTDLL module.
/// </summary>
public class MemoryUtil : IDisposable {
/// <summary>
/// The memory stream representation of the NTDLL module.
/// </summary>
protected Stream ModuleStream { get; set; }
/// <summary>
/// Dispose the memory stream when no longer needed.
/// </summary>
~MemoryUtil() => Dispose();
/// <summary>
/// Dispose the memory stream when no longer needed.
/// </summary>
public void Dispose() {
this.ModuleStream.Dispose();
this.ModuleStream.Close();
GC.SuppressFinalize(this);
}
/// <summary>
/// Extract a structure from the memory stream.
/// </summary>
/// <typeparam name="T">The Type of the structure to extract.</typeparam>
/// <param name="offset">The offset in the memory stream where the structure is located.</param>
/// <returns>The structure populated or the default structure.</returns>
protected T GetStructureFromBlob<T>(Int64 offset) where T : struct {
Span<byte> bytes = this.GetStructureBytesFromOffset<T>(offset);
if (Marshal.SizeOf<T>() != bytes.Length)
return default;
IntPtr ptr = Marshal.AllocHGlobal(Marshal.SizeOf<T>());
Marshal.Copy(bytes.ToArray(), 0, ptr, bytes.Length);
T s = Marshal.PtrToStructure<T>(ptr);
Marshal.FreeHGlobal(ptr);
return s;
}
/// <summary>
/// Extract the code from a native Windows function.
/// </summary>
/// <param name="offset">The location of the function in the memory stream.</param>
/// <returns>The 24 bytes representing the code of the function.</returns>
protected Span<byte> GetFunctionOpCode(Int64 offset) {
Span<byte> s = stackalloc byte[24];
this.ModuleStream.Seek(offset, SeekOrigin.Begin);
this.ModuleStream.Read(s);
return s.ToArray();
}
/// <summary>
/// Extract a DWORD value from the memory stream.
/// </summary>
/// <param name="offset">The location of the DWORD in the memory stream.</param>
/// <returns>The value of the DWORD.</returns>
protected UInt32 ReadPtr32(Int64 offset) {
Span<byte> s = stackalloc byte[4];
this.ModuleStream.Seek(offset, SeekOrigin.Begin);
this.ModuleStream.Read(s);
return BitConverter.ToUInt32(s);
}
/// <summary>
/// Extract a QWORD value from the memory stream.
/// </summary>
/// <param name="offset">The location of the QWORD in the memory stream.</param>
/// <returns>The value of the QWORD.</returns>
protected UInt64 ReadPtr64(Int64 offset) {
Span<byte> s = stackalloc byte[8];
this.ModuleStream.Seek(offset, SeekOrigin.Begin);
this.ModuleStream.Read(s);
return BitConverter.ToUInt64(s);
}
/// <summary>
/// Extract a WORD value from the memory stream.
/// </summary>
/// <param name="offset">The location of the WORD in the memory stream.</param>
/// <returns>The value of the WORD.</returns>
protected UInt16 ReadUShort(Int64 offset) {
Span<byte> s = stackalloc byte[2];
this.ModuleStream.Seek(offset, SeekOrigin.Begin);
this.ModuleStream.Read(s);
return BitConverter.ToUInt16(s);
}
/// <summary>
/// Extract an ASCII string from the memory stream.
/// </summary>
/// <param name="offset">The location of the ASCII string in the memory stream.</param>
/// <returns>The ASCII string.</returns>
protected string ReadAscii(Int64 offset) {
int length = 0;
this.ModuleStream.Seek(offset, SeekOrigin.Begin);
while (this.ModuleStream.ReadByte() != 0x00)
length++;
Span<byte> s = length <= 1024 ? stackalloc byte[length] : new byte[length];
this.ModuleStream.Seek(offset, SeekOrigin.Begin);
this.ModuleStream.Read(s);
return Encoding.ASCII.GetString(s);
}
/// <summary>
/// Extract the byte representation of a structure from the memory stream.
/// </summary>
/// <typeparam name="T">The Type of the structure to extract from the memory stream.</typeparam>
/// <param name="offset">The location of the structure in the memory stream.</param>
/// <returns>The structure as byte span.</returns>
protected Span<byte> GetStructureBytesFromOffset<T>(Int64 offset) where T : struct {
Span<byte> s = stackalloc byte[Marshal.SizeOf<T>()];
this.ModuleStream.Seek(offset, SeekOrigin.Begin);
this.ModuleStream.Read(s);
return s.ToArray();
}
/// <summary>
/// Get a specific amount of bytes at a specific location in the memory stream.
/// </summary>
/// <param name="offset">The location of the bytes to extract from the memory stream.</param>
/// <param name="size">The number of bytes to extract from the memory stream at a give location.</param>
/// <returns>The desired bytes as a byte span.</returns>
protected Span<byte> GetBytesFromOffset(Int64 offset, int size) {
Span<byte> s = size >= 1024 ? new byte[size] : stackalloc byte[size];
this.ModuleStream.Seek(offset, SeekOrigin.Begin);
this.ModuleStream.Read(s);
return s.ToArray();
}
}
}