C#读写进程内存的值

本文是模仿CE(Cheat Engine)软件修改单机游戏内存功能。

新建窗体应用程序MemoryReadWriteDemo,将默认的Form1重命名为FormReadWriteMemory。窗体FormReadWriteMemory设计如下:

一、新建内存读写类MemoryUtil.cs.源程序如下:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Runtime.InteropServices;

namespace MemoryReadWriteDemo
{
    /// <summary>
    /// 内存操作【读、写】类
    /// 模仿CE软件(Cheat Engine)读写单机游戏内存
    /// </summary>
    public class MemoryUtil
    {
        /// <summary>
        /// 打开进程,返回进程句柄
        /// </summary>
        /// <param name="dwDesiredAccess">渴望得到的访问权限(标志),0x1F0FFF表示最高权限</param>
        /// <param name="bInheritHandle">是否继承句柄</param>
        /// <param name="dwProcessId">进程标示符</param>
        /// <returns></returns>
        [DllImport("kernel32.dll", EntryPoint = "OpenProcess")]
        public static extern IntPtr OpenProcess(int dwDesiredAccess, bool bInheritHandle, int dwProcessId);

        /// <summary>
        /// 读内存
        /// </summary>
        /// <param name="hProcess">远程进程句柄。 被读取者</param>
        /// <param name="lpBaseAddress">远程进程中内存地址。 从具体何处读取</param>
        /// <param name="lpBuffer">本地进程中内存地址. 函数将读取的内容写入此处 </param>
        /// <param name="nSize">要传送的字节数。要写入多少</param>
        /// <param name="lpNumberOfBytesRead">实际传送的字节数. 函数返回时报告实际写入多少</param>
        /// <returns></returns>
        [DllImport("kernel32.dll", EntryPoint = "ReadProcessMemory")]
        public static extern bool ReadProcessMemory(IntPtr hProcess, IntPtr lpBaseAddress, IntPtr lpBuffer, int nSize, IntPtr lpNumberOfBytesRead);

        /// <summary>
        /// 写内存
        /// </summary>
        /// <param name="hProcess">由OpenProcess返回的进程句柄</param>
        /// <param name="lpBaseAddress">要写的内存首地址</param>
        /// <param name="lpBuffer">指向要写的数据的指针</param>
        /// <param name="nSize">要写入的字节数</param>
        /// <param name="lpNumberOfBytesWritten">实际数据的长度</param>
        /// <returns></returns>
        [DllImport("kernel32.dll", EntryPoint = "WriteProcessMemory")]
        public static extern bool WriteProcessMemory(IntPtr hProcess, IntPtr lpBaseAddress, int[] lpBuffer, int nSize, IntPtr lpNumberOfBytesWritten);

        /// <summary>
        /// 关闭内核对象
        /// </summary>
        /// <param name="hObject">欲关闭的对象句柄</param>
        [DllImport("kernel32.dll")]
        private static extern void CloseHandle(IntPtr hObject);

        /// <summary>
        /// 读取指定内存的值
        /// </summary>
        /// <param name="processName">进程名</param>
        /// <param name="baseAddress">内存地址</param>
        /// <param name="memoryValue">返回的内存值</param>
        /// <returns></returns>
        public static bool ReadMemoryInt(string processName, int baseAddress, out int memoryValue)
        {
            memoryValue = -1;
            int processId = -1;
            //找出指定进程名的第一个进程
            System.Diagnostics.Process[] processes = System.Diagnostics.Process.GetProcessesByName(processName);
            if (processes.Length > 0)
            {
                processId = processes[0].Id;
            }
            byte[] buffer = new byte[4];
            try
            {
                //获取缓冲区地址 :固定数组元素的不安全地址
                IntPtr byteAddress = Marshal.UnsafeAddrOfPinnedArrayElement(buffer, 0);
                //获取进程的最高权限
                IntPtr hProcess = OpenProcess(0x1F0FFF, false, processId);
                //将指定内存中的值读入缓冲区 
                ReadProcessMemory(hProcess, (IntPtr)baseAddress, byteAddress, 4, IntPtr.Zero);
                CloseHandle(hProcess);
                memoryValue = Marshal.ReadInt32(byteAddress);
                return true;
            }
            catch (Exception ex)
            {
                Console.WriteLine($"读取内存出错:{ex.Message}");
                return false;
            }
        }

        /// <summary>
        /// 向指定的内存写入值
        /// </summary>
        /// <param name="processName">进程名</param>
        /// <param name="baseAddress">内存地址</param>
        /// <param name="memoryValue">写入的内存值</param>
        /// <returns></returns>
        public static bool WriteMemoryInt(string processName, int baseAddress, int memoryValue)
        {
            int processId = -1;
            //找出指定进程名的第一个进程
            System.Diagnostics.Process[] processes = System.Diagnostics.Process.GetProcessesByName(processName);
            if (processes.Length > 0)
            {
                processId = processes[0].Id;
            }
            try
            {
                IntPtr hProcess = OpenProcess(0x1F0FFF, false, processId); //0x1F0FFF 最高权限 
                WriteProcessMemory(hProcess, (IntPtr)baseAddress, new int[] { memoryValue }, 4, IntPtr.Zero);
                CloseHandle(hProcess);
                return true;
            }
            catch (Exception ex)
            {
                Console.WriteLine($"写入内存出错:{ex.Message}");
                return false;
            }
        }

    }
}
 

二、FormReadWriteMemory窗体按钮绑定事件如下:(忽略设计器自动生成的代码)

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace MemoryReadWriteDemo
{
    public partial class FormReadWriteMemory : Form
    {
        public FormReadWriteMemory()
        {
            InitializeComponent();
        }

        private void btnOpenProcess_Click(object sender, EventArgs e)
        {
            int processId = -1;
            //找出指定进程名的第一个进程
            string processName = txtProcessName.Text.Trim();            
            System.Diagnostics.Process[] processes = System.Diagnostics.Process.GetProcessesByName(processName);
            if (processes.Length > 0)
            {
                processId = processes[0].Id;
            }
            if (processId != -1)
            {
                MessageBox.Show($"仙剑奇侠传三游戏进程已打开,进程ID:{processId}");
            }
            else 
            {
                MessageBox.Show("没有找到仙剑奇侠传三游戏进程!\n请先打开运行游戏");
            }
        }

        private void btnReadMemory_Click(object sender, EventArgs e)
        {
            int memoryValue;
            MemoryUtil.ReadMemoryInt(txtProcessName.Text.Trim(), Convert.ToInt32(txtMemoryAddress.Text.Trim(), 16), out memoryValue);
            txtMemoryValueDecimal.Text = memoryValue.ToString();
            txtMemoryValue.Text = memoryValue.ToString("X8");
            MessageBox.Show($"{memoryValue}");
        }

        private void btnWriteMemory_Click(object sender, EventArgs e)
        {
            bool result = MemoryUtil.WriteMemoryInt(txtProcessName.Text.Trim(), Convert.ToInt32(txtMemoryAddress.Text.Trim(), 16), int.Parse(txtMemoryValueDecimal.Text));
            MessageBox.Show($"写入值的结果:{result}");
        }
    }
}
三、程序测试运行如图:

 

  • 3
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

斯内科

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值