欢迎来到 嗅灵易学

零基础也能上手的脚本技术课,一对一答疑带你入门

《游戏修改器DIY之三》——用C#读写游戏进程内存

《游戏修改器DIY之三》——用C#读写游戏进程内存

《游戏修改器DIY之三》
——用C#读写游戏进程内存
天津 赵春生

    这是《游戏修改器DIY》系列的第三篇,通过前两篇拙作相信大家对游戏修改器的制作有了初步的了解,前两篇使用的编程工具是“Microsoft Visual C++ 6.0”,而这次将使用“Microsoft Visual C# 2005 Express Edition”。在C#中使用API可不像在C/C++那么简单,因为对我来说,C#还很陌生……
    本篇不再赘述游戏修改器的原理了,如果对此不了解的朋友可先看看我写的前两篇拙作或其他相关资料。

一:在C#中使用API。
    首先要导入一个namespace,以便简化后面的代码输入:
    using System.Runtime.InteropServices;

    其次要使用DllImport引入API函数,如:
    [DllImport("user32.dll", CharSet = CharSet.Auto)]
    public static extern int MessageBox(IntPtr hWnd, String text, String caption, uint type);

    现在就可以使用了,如:
    MessageBox(new IntPtr(0), "Hello World!", "Hello Dialog", 0);

    为了使用方便,我制作了一个简单的类:
    class ProcessMemoryWorkApi
{
    //HANDLE OpenProcess(
    //    DWORD dwDesiredAccess,// access flag
    //    BOOL bInheritHandle, // handle inheritance flag
    //    DWORD dwProcessId  // process identifier
    //    );
    [DllImport("kernel32.dll")]
    public static extern
        IntPtr OpenProcess(UInt32 dwDesiredAccess, Int32 bInheritHandle, UInt32 dwProcessId);
    //BOOL CloseHandle(
    //    HANDLE hObject  // handle to object to close
    //    );
    [DllImport("kernel32.dll")]
    public static extern
        Int32 CloseHandle(IntPtr hObject);
    //BOOL WriteProcessMemory(
    //    HANDLE hProcess, // handle to process whose memory is written to
    //    LPVOID lpBaseAddress, // address to start writing to
    //    LPVOID lpBuffer, // pointer to buffer to write data to
    //    DWORD nSize, // number of bytes to write
    //    LPDWORD lpNumberOfBytesWritten  // actual number of bytes written
    //    );
    [DllImport("kernel32.dll")]
    public static extern
        Int32 WriteProcessMemory(IntPtr hProcess, IntPtr lpBaseAddress, uint[] lpBuffer, UInt32 nSize, IntPtr lpNumberOfBytesWritten);
    //BOOL ReadProcessMemory(
    //    HANDLE hProcess, // handle of the process whose memory is read
    //    LPCVOID lpBaseAddress, // address to start reading
    //    LPVOID lpBuffer, // address of buffer to place read data
    //    DWORD nSize, // number of bytes to read
    //    LPDWORD lpNumberOfBytesRead  // address of number of bytes read
    //    );
    [DllImport("kernel32.dll")]
    public static extern
        Int32 ReadProcessMemory(IntPtr hProcess, IntPtr lpBaseAddress, uint[] lpBuffer, UInt32 nSize, IntPtr lpNumberOfBytesRead);
}

二:用C#制作游戏修改器。
    游戏是大家熟悉的“三维弹球”,这是WinXP自带的一款游戏,目的是修改她的分数,选这个游戏的原因是因为大家都能很容易地得到她,而且修改起来也很方便:取0x1025040中的值,然后与0x52相加,即可得到存放游戏分数的地址。
    单击“Go”按钮,可显示当前分数,并将分数改为:“999600000”),关键代码如下:

private void button_go_Click(object sender, EventArgs e)
        {
            IntPtr PinballHandle;
            IntPtr PinballScoreAddressPointer = (IntPtr)0x1025040;  //内存0x1025040中的值+0x52->PinballScoreAddress
            uint[] PinballScoreAddress = new uint[1];               //游戏分数的内存地址
            uint[] PinballScoreWrite = new uint[] { 0x3B94AF80 };   //将分数改为:999600000
            uint[] PinballScoreRead = new uint[1];                  //用来存放当前分数
            //"3D Pinball"在“Windows 任务管理器”中显示为"PINBALL.EXE",但作为
            //GetProcessesByName的参数使用时并不能包含扩展名".EXE"。
            System.Diagnostics.Process[] PinballProcessID
                = System.Diagnostics.Process.GetProcessesByName("PINBALL"); //根据进程名获取进程ID
            if (PinballProcessID.Length != 0)
            {
                PinballHandle = ProcessMemoryWorkApi.OpenProcess(0x1F0FFF, 0, (UInt32)PinballProcessID[0].Id);  //PROCESS_ALL_ACCESS=0x1F0FFF
                ProcessMemoryWorkApi.ReadProcessMemory(PinballHandle, PinballScoreAddressPointer, PinballScoreAddress, 4, (IntPtr)0);//通过指针得到PinballScoreAddress
                PinballScoreAddress[0] = PinballScoreAddress[0] + 0x52; //PinballScoreAddress+0x52才是游戏分数的内存地址
                ProcessMemoryWorkApi.ReadProcessMemory(PinballHandle, (IntPtr)PinballScoreAddress[0], PinballScoreRead, 4, (IntPtr)0);      //当前游戏分数
                MessageBox.Show("当前分数为: " + PinballScoreRead[0].ToString() + "\n" + "分数即将被修改成: 999600000", "ProcessMemoryWork_Demo");
                ProcessMemoryWorkApi.WriteProcessMemory(PinballHandle, (IntPtr)PinballScoreAddress[0], PinballScoreWrite, 4, (IntPtr)0);    //修改游戏分数
                ProcessMemoryWorkApi.CloseHandle(PinballHandle);
            }
            else
                MessageBox.Show("\"3D Pinball\" 还没有运行吧?", "ProcessMemoryWork_Demo");
        }

三:相关提示。
    刚刚接触C#不久,对OOP也一知半解,写此文只为抛砖引玉,谢谢!
    本程序代码测试环境:
    WinXP (Professional SP2)
    Microsoft Visual Studio 2005 (Installed Edition: C# Express)
    Version 8.0.50727.762  (SP.050727-7600)
    Microsoft .NET Framework
    Version 2.0.50727
    《游戏修改器DIY》/《游戏修改器DIY之二》可通过搜索引擎或访问我的Blog获得。
    Blog:
    http://timw.yeah.net
    http://timw.126.com
20:35 2007-04-27

注意:上传附件及图片大小不得大于30M。

⚠️ 版权声明:
本博客所有内容(含教程、源码、工具)仅供个人技术学习与研究交流使用,严禁商用、倒卖、二次分发及非法用途
未经作者书面授权,任何组织或个人不得转载、复制或用于其他平台,违者将追究相关责任。

0 0 0 举报
复制成功