首页
社区
课程
招聘
[原创]《游戏修改器DIY之三》——用C#读写游戏进程内存
发表于: 2007-4-29 15:31 21957

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

2007-4-29 15:31
21957

《游戏修改器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”(图1),关键代码如下:


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


[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课

上传的附件:
收藏
免费 7
支持
分享
最新回复 (19)
雪    币: 405
活跃值: (10)
能力值: ( LV9,RANK:1130 )
在线值:
发帖
回帖
粉丝
2
期待中~~~~~~~~
2007-4-29 18:52
0
雪    币: 208
活跃值: (51)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
3
原本很简单的代码,为何硬要绕个大弯用复杂的东西实现
api方面c++ delphi快n倍
c#适用于企业开发
2007-4-30 00:40
0
雪    币: 370
活跃值: (15)
能力值: ( LV9,RANK:170 )
在线值:
发帖
回帖
粉丝
4
我喜欢C#编成风格,C只用来做console app
另外想问:
[DllImport("kernel32.dll")]
    public static extern
        Int32 ReadProcessMemory(IntPtr hProcess, IntPtr lpBaseAddress, uint[] lpBuffer, UInt32 nSize, IntPtr lpNumberOfBytesRead);

这种声明能不能像VB引用某函数一样有个工具专门生成相应代码?
2007-4-30 01:31
0
雪    币: 133
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
5
[QUOTE=快雪时晴;303103]我喜欢C#编成风格,C只用来做console app
另外想问:
[DllImport("kernel32.dll")]
    public static extern
        Int32 ReadProcessMemory(IntPtr hProcess, I...[/QUOTE]

这个工具好像是可以.名字:api_exp.exe

你也可以去http://www.pinvoke.net/ 看看.
2007-4-30 08:38
0
雪    币: 370
活跃值: (15)
能力值: ( LV9,RANK:170 )
在线值:
发帖
回帖
粉丝
6
非常感谢,api_exp.exe似乎找不到了,
那个pinvoke不错
2007-4-30 16:52
0
雪    币: 888
活跃值: (2375)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
7
继前两篇后。。又出第三了?
学习。。。支持
2007-5-1 10:06
0
雪    币: 200
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
8
谢谢提供这么好的文章,我是学习CS的,又让我增长了知识..
2007-5-1 10:17
0
雪    币: 431
活跃值: (442)
能力值: ( LV12,RANK:530 )
在线值:
发帖
回帖
粉丝
9
用C#写内存修改器只是出于好奇,看看能不能实现。

还是根据需要自己写代码吧,工具出来的有时不太适合自己的需要。
2007-5-1 15:49
0
雪    币: 184
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
10
我想看1,2,在那里啊搜不到
2007-7-23 23:24
0
雪    币: 184
活跃值: (65)
能力值: ( LV6,RANK:90 )
在线值:
发帖
回帖
粉丝
11
.net运行速度极慢,不适合用来做这种类型的开发.
2007-7-24 10:53
0
雪    币: 325
活跃值: (97)
能力值: ( LV13,RANK:530 )
在线值:
发帖
回帖
粉丝
12
又来了...我特指'net运行速度极慢' 这句话.至于后面一句.酌情考虑.以后Vista普及了情况会变.
2007-7-24 17:40
0
雪    币: 204
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
13
如果能做成动画讲解那该多好啊.
2007-7-24 19:33
0
雪    币: 431
活跃值: (442)
能力值: ( LV12,RANK:530 )
在线值:
发帖
回帖
粉丝
14
1和2可搜索这里的帖子,也可去我BLOG看.

BLOG地址:
http://blog.csdn.net/prince_vegeta/archive/2005/03/02/308025.aspx
http://blog.csdn.net/prince_vegeta/archive/2005/03/02/308047.aspx
或:
http://vegeta.blog.enorth.com.cn/article/865.shtml
http://vegeta.blog.enorth.com.cn/article/875.shtml
2007-7-25 13:38
0
雪    币: 144
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
15
地址怎么找的 汗啊
2007-7-29 10:26
0
雪    币: 431
活跃值: (442)
能力值: ( LV12,RANK:530 )
在线值:
发帖
回帖
粉丝
16
用游侠找出存放分数的内存地址后,用OD跟踪.
2007-7-29 15:20
0
雪    币: 200
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
17
很喜欢游戏修改器但原理还不是非常通..
2007-7-29 21:47
0
雪    币: 200
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
18
1,2篇的地址在哪里啊?
2007-7-29 23:16
0
雪    币: 431
活跃值: (442)
能力值: ( LV12,RANK:530 )
在线值:
发帖
回帖
粉丝
19
看14楼。

2007-7-30 09:21
0
雪    币: 166
活跃值: (62)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
20
好的工具一定要试试
2007-8-4 10:20
0
游客
登录 | 注册 方可回帖
返回
//