174 lines
5.6 KiB
C#
174 lines
5.6 KiB
C#
using EonaCat.Win32Api.WindowsAPI;
|
|
using System;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using System.Runtime.InteropServices;
|
|
using System.Text;
|
|
using System.Threading.Tasks;
|
|
|
|
namespace EonaCat.MemoryManager
|
|
{
|
|
public class MemoryManager
|
|
{
|
|
private readonly IntPtr _processHandle;
|
|
|
|
public MemoryManager(IntPtr processHandle)
|
|
{
|
|
_processHandle = processHandle;
|
|
}
|
|
|
|
public byte[] ReadBytes(IntPtr address, int size)
|
|
{
|
|
byte[] buffer = new byte[size];
|
|
ApiKernel32.ReadProcessMemory(_processHandle, address, buffer, size, out _);
|
|
return buffer;
|
|
}
|
|
|
|
public void WriteBytes(IntPtr address, byte[] data)
|
|
{
|
|
ApiKernel32.WriteProcessMemory(_processHandle, address, data, data.Length, out _);
|
|
}
|
|
|
|
public IntPtr ReadPointer(IntPtr baseAddress, int[] offsets)
|
|
{
|
|
IntPtr address = baseAddress;
|
|
byte[] buffer = new byte[IntPtr.Size];
|
|
|
|
for (int i = 0; i < offsets.Length; i++)
|
|
{
|
|
ApiKernel32.ReadProcessMemory(_processHandle, address, buffer, buffer.Length, out _);
|
|
address = (IntPtr)(IntPtr.Size == 4 ? BitConverter.ToInt32(buffer, 0) : BitConverter.ToInt64(buffer, 0));
|
|
address = IntPtr.Add(address, offsets[i]);
|
|
}
|
|
|
|
return address;
|
|
}
|
|
|
|
public T ReadValue<T>(IntPtr address) where T : unmanaged
|
|
{
|
|
int size = Marshal.SizeOf<T>();
|
|
byte[] buffer = ReadBytes(address, size);
|
|
|
|
unsafe
|
|
{
|
|
fixed (byte* ptr = buffer)
|
|
{
|
|
return *(T*)ptr;
|
|
}
|
|
}
|
|
}
|
|
|
|
public void WriteValue<T>(IntPtr address, T value) where T : unmanaged
|
|
{
|
|
int size = Marshal.SizeOf<T>();
|
|
byte[] buffer = new byte[size];
|
|
|
|
unsafe
|
|
{
|
|
fixed (byte* ptr = buffer)
|
|
{
|
|
*(T*)ptr = value;
|
|
}
|
|
}
|
|
|
|
WriteBytes(address, buffer);
|
|
}
|
|
|
|
public T ReadStruct<T>(IntPtr address) where T : class
|
|
{
|
|
int size = Marshal.SizeOf<T>();
|
|
byte[] buffer = ReadBytes(address, size);
|
|
GCHandle handle = GCHandle.Alloc(buffer, GCHandleType.Pinned);
|
|
T value = Marshal.PtrToStructure<T>(handle.AddrOfPinnedObject());
|
|
handle.Free();
|
|
return value;
|
|
}
|
|
|
|
public void WriteStruct<T>(IntPtr address, T value) where T : class
|
|
{
|
|
int size = Marshal.SizeOf<T>();
|
|
byte[] buffer = new byte[size];
|
|
IntPtr ptr = Marshal.AllocHGlobal(size);
|
|
Marshal.StructureToPtr(value, ptr, false);
|
|
Marshal.Copy(ptr, buffer, 0, size);
|
|
Marshal.FreeHGlobal(ptr);
|
|
WriteBytes(address, buffer);
|
|
}
|
|
|
|
public object ReadValue(IntPtr address, Type type)
|
|
{
|
|
int size = Marshal.SizeOf(type);
|
|
byte[] buffer = ReadBytes(address, size);
|
|
|
|
GCHandle handle = GCHandle.Alloc(buffer, GCHandleType.Pinned);
|
|
object value = Marshal.PtrToStructure(handle.AddrOfPinnedObject(), type);
|
|
handle.Free();
|
|
return value;
|
|
}
|
|
|
|
public void WriteValue(IntPtr address, object value, Type type)
|
|
{
|
|
int size = Marshal.SizeOf(type);
|
|
byte[] buffer = new byte[size];
|
|
IntPtr ptr = Marshal.AllocHGlobal(size);
|
|
Marshal.StructureToPtr(value, ptr, false);
|
|
Marshal.Copy(ptr, buffer, 0, size);
|
|
Marshal.FreeHGlobal(ptr);
|
|
WriteBytes(address, buffer);
|
|
}
|
|
|
|
public string ReadStringAscii(IntPtr address, int maxLength)
|
|
{
|
|
byte[] buffer = ReadBytes(address, maxLength);
|
|
int length = Array.IndexOf<byte>(buffer, 0);
|
|
if (length < 0) length = maxLength;
|
|
return System.Text.Encoding.ASCII.GetString(buffer, 0, length);
|
|
}
|
|
|
|
public string ReadStringUnicode(IntPtr address, int maxLength)
|
|
{
|
|
byte[] buffer = ReadBytes(address, maxLength * 2);
|
|
int length = 0;
|
|
for (int i = 0; i < maxLength; i++)
|
|
{
|
|
if (buffer[i * 2] == 0 && buffer[i * 2 + 1] == 0)
|
|
{
|
|
length = i;
|
|
break;
|
|
}
|
|
}
|
|
if (length == 0) length = maxLength;
|
|
return System.Text.Encoding.Unicode.GetString(buffer, 0, length * 2);
|
|
}
|
|
|
|
public void WriteStringAscii(IntPtr address, string value)
|
|
{
|
|
byte[] buffer = System.Text.Encoding.ASCII.GetBytes(value + '\0');
|
|
WriteBytes(address, buffer);
|
|
}
|
|
|
|
public void WriteStringUnicode(IntPtr address, string value)
|
|
{
|
|
byte[] buffer = System.Text.Encoding.Unicode.GetBytes(value + '\0');
|
|
WriteBytes(address, buffer);
|
|
}
|
|
|
|
public T[] ReadArray<T>(IntPtr address, int count) where T : unmanaged
|
|
{
|
|
int size = Marshal.SizeOf<T>() * count;
|
|
byte[] buffer = ReadBytes(address, size);
|
|
T[] result = new T[count];
|
|
Buffer.BlockCopy(buffer, 0, result, 0, size);
|
|
return result;
|
|
}
|
|
|
|
public void WriteArray<T>(IntPtr address, T[] array) where T : unmanaged
|
|
{
|
|
int size = Marshal.SizeOf<T>() * array.Length;
|
|
byte[] buffer = new byte[size];
|
|
Buffer.BlockCopy(array, 0, buffer, 0, size);
|
|
WriteBytes(address, buffer);
|
|
}
|
|
}
|
|
}
|