using System.Diagnostics; using System.Runtime.InteropServices; using XFEExtension.NetCore.DelegateExtension; using XFEExtension.NetCore.MemoryEditor.Manager; namespace XFEExtension.NetCore.MemoryEditor; /// /// 内存编辑器 /// public partial class MemoryEditor : MemoryListenerManagerBase, IDisposable { private bool disposedValue; private MemoryListenerManager listenerManager = new(); /// /// 当指定地址的内存值变化时触发 /// public event XFEEventHandler? ValueChanged; /// /// 当监听器监听状态改变时触发 /// public event XFEEventHandler? ListeningStateChanged; /// /// 当前进程结束时触发 /// public event EventHandler? CurrentProcessExit; /// /// 目标进程启动时触发 /// public event EventHandler? CurrentProcessEntered; /// /// 当前目标进程 /// public Process? CurrentProcess { get => listenerManager.CurrentProcess; set => listenerManager.CurrentProcess = value; } /// /// 进程句柄 /// public nint ProcessHandler { get => listenerManager.ProcessHandler; set => listenerManager.ProcessHandler = value; } /// /// 目标进程名称 /// public string ProcessName { get => listenerManager.ProcessName; set => listenerManager.ProcessName = value; } /// /// 内存监听器 /// public MemoryListenerManager ListenerManager { get { return listenerManager; } set { listenerManager = value; } } /// /// 当目标进程退出后,是否自动重新获取进程 /// public bool AutoReacquireProcess { get => listenerManager.AutoReacquireProcess; set => listenerManager.AutoReacquireProcess = value; } /// /// 自动重新获取进程的检测频率(单位毫秒) /// public int AutoReacquireProcessFrequency { get => listenerManager.ReacquireProcessFrequency; set => listenerManager.ReacquireProcessFrequency = value; } /// /// 进程句柄权限(不懂勿填) /// public ProcessAccessFlags ProcessAccessFlags { get => listenerManager.ProcessAccessFlags; set => listenerManager.ProcessAccessFlags = value; } /// /// 进程位数类型(32/64) /// public ProcessType ProcessBiteType { get; set; } /// /// 等待目标进程出现 /// /// 进程名称 /// 检测频率 /// public async Task WaitProcessEnter(string? processName = null, int frequency = 500) => await listenerManager.WaitProcessEnter(processName, frequency); /// /// 读取指定地址的内存 /// /// 目标类型(int,float,long等) /// 指定地址 /// 读取结果 /// 是否读取成功 public bool ReadMemory(nint address, out T result) where T : struct => ReadMemory(ProcessHandler, address, out result); /// /// 读取指定地址的内存 /// /// 指定地址 /// 读取长度 /// 读取结果 /// 是否读取成功 public bool ReadMemory(nint address, int size, out byte[] buffer) => ReadMemory(ProcessHandler, address, size, out buffer); /// /// 在指定内存地址中写入数据 /// /// 数据类型(int,float,long等) /// 目标地址 /// 待写入值 /// 是否写入成功 public bool WriteMemory(nint address, T source) where T : struct => WriteMemory(ProcessHandler, address, source); /// /// 解析基址对应的实际地址 /// /// 模块名称(基址的进程部分,可以是DLL等) /// 基址的地址部分 /// 基址的偏移组 /// 实际地址 public nint ResolvePointerAddress(string moduleName, nint baseAddress, params nint[] offsets) => CurrentProcess is null ? default : ResolvePointerAddress(CurrentProcess, moduleName, baseAddress, ProcessBiteType, offsets); /// /// 解析基址对应的实际地址 /// /// 模块地址(基址的进程部分,可以是DLL等) /// 基址的地址部分 /// 基址的偏移组 /// 实际地址 public nint ResolvePointerAddress(nint moduleBaseAddress, int baseAddress, params nint[] offsets) => CurrentProcess is null ? default : ResolvePointerAddress(CurrentProcess, moduleBaseAddress, baseAddress, ProcessBiteType, offsets); internal override StaticMemoryListener AddStaticListener(string customName, nint memoryAddress, TimeSpan? frequency, Type type, bool startListen) => ListenerManager.AddStaticListener(customName, memoryAddress, frequency, type, startListen); internal override DynamicMemoryListener AddDynamicListener(string customName, Func memoryAddressGetFunc, TimeSpan? frequency, Type type, bool startListen) => ListenerManager.AddDynamicListener(customName, memoryAddressGetFunc, frequency, type, startListen); internal override UpdatableMemoryListener AddUpdatableListener(string customName, Func memoryAddressUpdateFunc, TimeSpan? frequency, Type type, bool startListen) => ListenerManager.AddUpdatableListener(customName, memoryAddressUpdateFunc, frequency, type, startListen); /// public override void ClearListeners() => ListenerManager.ClearListeners(); /// public override void RemoveListener(string customName) => ListenerManager.RemoveListener(customName); /// public override Task StopListener(string customName) => ListenerManager.StopListener(customName); /// public override Task StopListeners() => ListenerManager.StopListeners(); /// /// 内存编辑器 /// /// 进程位数类型(32/64) public MemoryEditor(ProcessType processBiteType = ProcessType.Bit64) { ProcessBiteType = processBiteType; ListenerManager.ValueChanged += (sender, e) => ValueChanged?.Invoke(sender, e); ListenerManager.CurrentProcessExit += (sender, e) => CurrentProcessExit?.Invoke(sender, e); ListenerManager.CurrentProcessEntered += (sender, e) => CurrentProcessEntered?.Invoke(sender, e); } /// /// 内存编辑器 /// /// 进程 /// 进程位数类型(32/64) public MemoryEditor(Process process, ProcessType processType = ProcessType.Bit64) { CurrentProcess = process; ProcessBiteType = processType; ListenerManager.ValueChanged += (sender, e) => ValueChanged?.Invoke(sender, e); ListenerManager.ListeningStateChanged += (sender, e) => ListeningStateChanged?.Invoke(sender, e); ListenerManager.CurrentProcessExit += (sender, e) => CurrentProcessExit?.Invoke(sender, e); ListenerManager.CurrentProcessEntered += (sender, e) => CurrentProcessEntered?.Invoke(sender, e); } /// /// 内存编辑器 /// /// 进程名称 /// 进程位数类型(32/64) public MemoryEditor(string processName, ProcessType processType = ProcessType.Bit64) { CurrentProcess = Process.GetProcessesByName(processName).First(); ProcessBiteType = processType; ListenerManager.ValueChanged += (sender, e) => ValueChanged?.Invoke(sender, e); ListenerManager.ListeningStateChanged += (sender, e) => ListeningStateChanged?.Invoke(sender, e); ListenerManager.CurrentProcessExit += (sender, e) => CurrentProcessExit?.Invoke(sender, e); ListenerManager.CurrentProcessEntered += (sender, e) => CurrentProcessEntered?.Invoke(sender, e); } /// /// 内存编辑器 /// /// 进程PID /// 进程位数类型(32/64) public MemoryEditor(int processId, ProcessType processType = ProcessType.Bit64) { CurrentProcess = Process.GetProcessById(processId); ProcessBiteType = processType; ListenerManager.ValueChanged += (sender, e) => ValueChanged?.Invoke(sender, e); ListenerManager.ListeningStateChanged += (sender, e) => ListeningStateChanged?.Invoke(sender, e); ListenerManager.CurrentProcessExit += (sender, e) => CurrentProcessExit?.Invoke(sender, e); ListenerManager.CurrentProcessEntered += (sender, e) => CurrentProcessEntered?.Invoke(sender, e); } /// /// 释放资源 /// /// protected virtual void Dispose(bool disposing) { if (!disposedValue) { if (disposing) { ListenerManager.Dispose(); } disposedValue = true; } } /// /// 释放资源 /// public void Dispose() { Dispose(disposing: true); GC.SuppressFinalize(this); } #region 静态方法 /// /// 获取程序句柄 /// /// 进程ID /// 进程访问权限 /// public static nint GetProcessHandle(int processId, ProcessAccessFlags flags) { nint processHandle = OpenProcess((int)flags, false, processId); return processHandle; } /// /// 获取程序句柄 /// /// 进程名称 /// 进程访问权限 /// public static nint GetProcessHandle(string processName, ProcessAccessFlags flags) { nint processHandle = OpenProcess((int)flags, false, Process.GetProcessesByName(processName).First().Id); return processHandle; } /// /// 读取指定地址的内存 /// /// 目标类型(int,float,long等) /// 进程句柄 /// 指定地址 /// 读取结果 /// 是否读取成功 public static bool ReadMemory(nint processHandle, nint address, out T result) where T : struct { unsafe { var size = Marshal.SizeOf(); var buffer = new byte[size]; var boolResult = ReadProcessMemory(processHandle, address, buffer, (uint)size, out _); fixed (byte* pBuffer = buffer) { result = Marshal.PtrToStructure((nint)pBuffer); } return boolResult; } } /// /// 读取指定地址的内存 /// /// 进程句柄 /// 指定地址 /// 读取的长度 /// 读取结果 /// 是否读取成功 public static bool ReadMemory(nint processHandle, nint address, int size, out byte[] buffer) { unsafe { buffer = new byte[size]; var boolResult = ReadProcessMemory(processHandle, address, buffer, (uint)size, out _); return boolResult; } } /// /// 读取指定地址的内存
/// 如非有意使用,请转到 ///
/// 进程句柄 /// 指定地址 /// 目标类型(int,float,long等) /// 读取结果 public static object? ReadMemory(nint processHandle, nint address, Type type) { unsafe { var size = Marshal.SizeOf(type); var buffer = new byte[size]; if (ReadProcessMemory(processHandle, address, buffer, (uint)size, out _)) { fixed (byte* pBuffer = buffer) { return Marshal.PtrToStructure((nint)pBuffer, type); } } return null; } } /// /// 在指定内存中写入数据 /// /// 数据类型(int,float,long等) /// 进程句柄 /// 目标地址 /// 待写入值 /// 是否写入成功 public static bool WriteMemory(nint processHandle, nint address, T source) where T : struct { var buffer = StructureToByteArray(source); return WriteProcessMemory(processHandle, address, buffer, (uint)buffer.Length, out _); } /// /// 解析基址对应的实际地址 /// /// 主进程 /// 模块名称(基址的进程部分,可以是DLL等) /// 基址的地址部分 /// 目标进程类型 /// 基址的偏移组 /// 实际地址 public static nint ResolvePointerAddress(Process process, string moduleName, nint baseAddress, ProcessType processType, params nint[] offsets) => ResolvePointerAddress(process, GetModuleBaseAddress(process, moduleName), baseAddress, processType, offsets); /// /// 解析基址对应的实际地址 /// /// 主进程 /// 模块地址(基址的进程部分,可以是DLL等) /// 基址的地址部分 /// 目标进程类型 /// 基址的偏移组 /// 实际地址 public static nint ResolvePointerAddress(Process process, nint moduleBaseAddress, nint baseAddress, ProcessType processType, params nint[] offsets) { var resolvedAddress = moduleBaseAddress + baseAddress; if (processType == ProcessType.Bit32) { foreach (nint offset in offsets) { var success = ReadMemory(process.Handle, resolvedAddress, out int nextAddress); if (!success || nextAddress == nint.Zero) return nint.Zero; var pointerValue = new nint(nextAddress); resolvedAddress = pointerValue + offset; } } else { foreach (nint offset in offsets) { var success = ReadMemory(process.Handle, resolvedAddress, out long nextAddress); if (!success || nextAddress == nint.Zero) return nint.Zero; var pointerValue = new nint(nextAddress); resolvedAddress = pointerValue + offset; } } return resolvedAddress; } /// /// 通过模块名称获取模块地址 /// /// 模块所在进程 /// 模块名称 /// public static nint GetModuleBaseAddress(Process process, string moduleName) { var module = process.Modules.Cast().FirstOrDefault(m => m.ModuleName.Equals(moduleName, StringComparison.OrdinalIgnoreCase)); return module != null ? module.BaseAddress : nint.Zero; } internal static Process? GetGameProcessByName(string processName) { var processes = Process.GetProcessesByName(processName); return processes.Length > 0 ? processes[0] : null; } private static byte[] StructureToByteArray(T source) where T : struct { var size = Marshal.SizeOf(); var buffer = new byte[size]; IntPtr ptr = Marshal.AllocHGlobal(size); Marshal.StructureToPtr(source, ptr, true); Marshal.Copy(ptr, buffer, 0, size); Marshal.FreeHGlobal(ptr); return buffer; } #endregion #region DLL引用 [LibraryImport("kernel32.dll")] internal static partial nint OpenProcess(int dwDesiredAccess, [MarshalAs(UnmanagedType.Bool)] bool bInheritHandle, int dwProcessId); [LibraryImport("kernel32.dll", SetLastError = true)] [return: MarshalAs(UnmanagedType.Bool)] internal static partial bool WriteProcessMemory(nint hProcess, nint lpBaseAddress, [In] byte[] lpBuffer, uint nSize, out int lpNumberOfBytesWritten); [LibraryImport("kernel32.dll")] [return: MarshalAs(UnmanagedType.Bool)] internal static partial bool ReadProcessMemory(nint hProcess, nint lpBaseAddress, [Out] byte[] lpBuffer, uint dwSize, out int lpNumberOfBytesRead); #endregion }