代码
var processName = "War3";
var process = MemoryUtils.GetProcessByProcessName(processName);
if (process == null)
{
throw new Exception($"没有找到进程:{processName },请先启动后,再使用该功能");
}
var _memoryUtils = new MemoryUtils(process.Id);
var address = _memoryUtils.GetMemoryAddress("Game.dll", 0x00BE87A4, 0x30, 0x1F0, 0x8C)
var myValue1 = _memoryUtils.ReadToInt(address)
_memoryUtils.WriteInt(address, 99999);
var myValue2 = _memoryUtils.ReadToFloat(address)
_memoryUtils.WriteFloat(address, 0.5f);
MemoryUtils.cs
using System;
using System.Diagnostics;
using System.Runtime.InteropServices;
using System.Text;
namespace MyUtils;
public class MemoryUtils
{
#region API
[DllImport("kernel32.dll", EntryPoint = "ReadProcessMemory")]
private static extern bool ReadProcessMemory(IntPtr hProcess, IntPtr lpBaseAddress, byte[] lpBuffer, int dwSize, IntPtr lpNumberOfBytesRead);
[DllImport("kernel32.dll", EntryPoint = "WriteProcessMemory")]
private static extern bool WriteProcessMemory(IntPtr hProcess, IntPtr lpBaseAddress, byte[] lpBuffer, int dwSize, IntPtr lpNumberOfBytesWritten);
[DllImport("kernel32.dll", EntryPoint = "OpenProcess")]
private static extern IntPtr OpenProcess(int dwDesiredAccess, bool bInheritHandle, int dwProcessId);
[DllImport("kernel32.dll")]
private static extern void CloseHandle(IntPtr hObject);
#endregion
private IntPtr _handle = IntPtr.Zero;
private int _pid = 0;
public MemoryUtils(int pid)
{
_pid = pid;
_handle = OpenProcess(0x1F0FFF, false, pid);
}
~MemoryUtils()
{
CloseHandle(_handle);
}
#region Read
public byte[] ReadToBytes(IntPtr address, int size)
{
byte[] buffer = new byte[size];
ReadProcessMemory(_handle, address, buffer, size, IntPtr.Zero);
return buffer;
}
public T ReadObject<T>(IntPtr address) where T : struct
{
var buffer = ReadToBytes(address, Marshal.SizeOf(typeof(T)));
var bufferAddress = Marshal.AllocHGlobal(buffer.Length);
Marshal.Copy(buffer, 0, bufferAddress, buffer.Length);
var structure = (T)Marshal.PtrToStructure(bufferAddress, typeof(T));
Marshal.FreeHGlobal(bufferAddress);
return structure;
}
public char ReadToChar(IntPtr address)
{
byte[] buffer = ReadToBytes(address, sizeof(char));
return BitConverter.ToChar(buffer, 0);
}
public short ReadToShort(IntPtr address)
{
byte[] buffer = ReadToBytes(address, sizeof(short));
return BitConverter.ToInt16(buffer, 0);
}
public int ReadToInt(IntPtr address)
{
byte[] buffer = ReadToBytes(address, sizeof(int));
return BitConverter.ToInt32(buffer, 0);
}
public long ReadToLong(IntPtr address)
{
byte[] buffer = ReadToBytes(address, sizeof(long));
return BitConverter.ToInt64(buffer, 0);
}
public float ReadToFloat(IntPtr address)
{
byte[] buffer = ReadToBytes(address, sizeof(float));
return BitConverter.ToSingle(buffer, 0);
}
public double ReadToDouble(IntPtr address)
{
byte[] buffer = ReadToBytes(address, sizeof(double));
return BitConverter.ToDouble(buffer, 0);
}
public string ReadToString(IntPtr address, int stringSize)
{
byte[] buffer = ReadToBytes(address, stringSize);
return BitConverter.ToString(buffer);
}
#endregion
#region Write
public bool WriteByteArray(IntPtr address, byte[] byteData)
{
return WriteProcessMemory(_handle, address, byteData, byteData.Length, IntPtr.Zero);
}
public bool WriteChar(IntPtr address, char value)
{
return WriteByteArray(address, BitConverter.GetBytes(value));
}
public bool WriteShort(IntPtr address, short value)
{
return WriteByteArray(address, BitConverter.GetBytes(value));
}
public bool WriteInt(IntPtr address, int value)
{
return WriteByteArray(address, BitConverter.GetBytes(value));
}
public bool WriteLong(IntPtr address, long value)
{
return WriteByteArray(address, BitConverter.GetBytes(value));
}
public bool WriteFloat(IntPtr address, float value)
{
return WriteByteArray(address, BitConverter.GetBytes(value));
}
public bool WriteDouble(IntPtr address, double value)
{
return WriteByteArray(address, BitConverter.GetBytes(value));
}
public bool WriteString(IntPtr address, string value)
{
return WriteByteArray(address, Encoding.Default.GetBytes(value));
}
#endregion
#region Utils
public static int GetPidByProcessName(string processName)
{
return GetProcessByProcessName(processName)?.Id ?? 0;
}
public static Process GetProcessByProcessName(string processName)
{
var processArr = Process.GetProcessesByName(processName);
if (processArr.Length > 0)
{
return processArr[0];
}
return null;
}
public static IntPtr FindWindow(string title)
{
var processArray = Process.GetProcesses();
foreach (var item in processArray)
{
if (item.MainWindowTitle.IndexOf(title) != -1)
{
return item.MainWindowHandle;
}
}
return IntPtr.Zero;
}
public IntPtr GetModuleBaseAddress(string moduleName)
{
var process = Process.GetProcessById(_pid);
IntPtr baseAddress = default;
for (int i = 0; i < process.Modules.Count; i++)
{
var item = process.Modules[i];
if (item.ModuleName == moduleName)
{
baseAddress = item.BaseAddress;
break;
}
}
return baseAddress;
}
public IntPtr GetMemoryAddress(string moduleName, params IntPtr[] offsetArray)
{
if ((offsetArray?.Length ?? 0) == 0)
{
throw new Exception("至少需要一个偏移");
}
IntPtr addr = IntPtr.Zero;
var addrVal = GetModuleBaseAddress(moduleName);
for (int i = 0; i < offsetArray.Length; i++)
{
addr = addrVal + offsetArray[i];
addrVal = (IntPtr)ReadToInt(addr);
}
return addr;
}
public static IntPtr GetWindowHwndByProcessName(string processName)
{
var hwnd = MemoryUtils.GetProcessByProcessName(processName)?.MainWindowHandle ?? IntPtr.Zero;
if (hwnd == IntPtr.Zero)
{
throw new Exception($"没有找到[{processName}]进程..");
}
return hwnd;
}
#endregion
#region 进制转换
public static int ConvertFrom16To10(string value)
{
return Convert.ToInt32(value, 16);
}
public static int ConvertFrom16To10(IntPtr value)
{
return Convert.ToInt32(Convert.ToString(value, 10));
}
public static string ConvertFrom10To16(IntPtr value)
{
return value.ToString("x");
}
public static string ConvertFrom16Or10To2(IntPtr value)
{
return Convert.ToString(value, 2);
}
public static int ConvertFrom2To10(string value)
{
return Convert.ToInt32(value, 2);
}
#endregion
}
例子
https://github.com/xxxxue/war3-72bian