首页
社区
课程
招聘
[原创]《游戏修改器DIY之二》
发表于: 2005-1-29 13:32 16804

[原创]《游戏修改器DIY之二》

2005-1-29 13:32
16804

                  《游戏修改器DIY之二》

                     源码下载

  上次我们以一款名叫《潜艇大战》的小游戏作为目标,制作了其相应的修改器,使之成为了不死版的游戏,相信大家在这过程中学到了相关的知识(一年前写的东西了:))。这次我们的目标是《红色警戒2》,制作她的金钱修改器。之所以选择这款游戏作为演示,一方面是出于个人原因:我很喜欢这款游戏;而另一方面则是:这款游戏很具有代表性,相信大多数修改过其金钱数的玩家们都会注意到:她存放金钱的内存地址并不是固定不变的,哪怕重新开始一次任务,她的地址都会改变。与之类似的游戏还有《Mech Commander》等。本篇将教你如何制作此类游戏的修改器。

  目标:《红色警戒2》(繁体中文版:1.006)
  所需工具:《金山游侠III》、
  SOFTICE(版本:4.0.5 Build334+IceDump)、LordPE1.4、
  Microsoft Visual C++ (版本:6.0+SP6)

  第一部分:获得游戏中关键的数据――这是制作游戏修改器的前提。

  首先用《游侠》找到存放金钱数的内存地址(一般情况下会找到三个地址,其中最另类的那个就是我们所需要的):0x68A1B5C,调出SOFTICE,输入下面的命令:bpm 68a1b5c r,回到游戏后SI就产生了中断,你可以看到下面这条指令:

0187:004E2B5A FIADD DWORD PTR [ESI+00000228]

  其中ESI的值为0x068A1934,下指令:d esi+228 即得:0x068A1B5C,其中便是当前的金钱数。追溯这段代码可得:

0187:00494664 MOV EDX,[ECX+24]
0187:00494667 LEA EAX,[ECX+24]
0187:0049466A PUSH EAX
0187:0049466B CALL [EDX+18]
0187:0049466E XOR ECX,ECX
0187:00494670 MOV [ESI],EAX

  在0187:0049466A处下断点,SI每次中断后,EAX的值始终是:0x068A1934,如此时下指令:d eax+228 同样可得:0x068A1B5C。现在情况很明了:其中0x228是个定值,我们现在不必理会,关键的问题是EAX的值,就像前面说到的那样:她的值并不是固定不变的,哪怕重新开始一次任务她的值都会随之改变。我们需要做的工作就是写一段自己的代码,将EAX的值保存在一个固定的位置,然后从该位置取得结果,再加上0x228即可得到存放金钱数的内存地址了。所以,我们需要找一个可写的空白区,来存放我们自己的代码和EAX的值。

  用LordPE查看Game.exe(一定要做好备份!!!用LordPE查看文件后,即使什么也没做,他也会修改我们的文件……),发现.data段符合我们的要求,我选的位置是:0x42ed60(存放EAX的值),和0x42ed80(存放自己的代码),在0x42ed60处写一些字符串,如:vegeta,这样一来,我们可以用s命令快速找到其在内存中的位置,还可以判断该位置是否被程序所用。

  重新开始游戏,SI会在0x0049466A处产生中断。在SI中下指令:

s ds:400000 l ffffffff 'vegeta'

SI提示找到了一个内存地址:018F:0082ED60(0042ED60),这段内存程序并没有占用,现在就可以在0x0082ED80(0042ED80)处写我们自己的代码了。在这之前,我们先修改0x0049466A,让他跳到我们的代码,下指令:

a 49466a

输入:

jmp 82ed80 //跳到我们的代码处执行
nop //补指令长度

修改后的代码为:
0187:0049466A E911A73900 JMP 0082ED80
0187:0049466F 90 NOP
0187:00494670 8906 MOV [ESI],EAX

现在写入我们的代码:

a 82ed80

依次输入:

mov dword ptr [82ed60],eax //将EAX的值保存到:0x82ed60
push eax //\
call [edx+18] //恢复被JMP 0082ED80破坏掉的指令
xor ecx,ecx ///
jmp 00494670 //返回游戏程序继续执行

修改后的代码为:
0187:0082ED80 A360ED8200 MOV [0082ED60],EAX
0187:0082ED85 50 PUSH EAX
0187:0082ED86 FF5218 CALL [EDX+18]
0187:0082ED89 33C9 XOR ECX,ECX
0187:0082ED8B E9E058C6FF JMP 00494670

  检查无误后记下机器码(我习惯用IceDump的抓屏),在0x0082ED85处设断点,F5返回游戏后便会产生中断,此时下指令:

d *0082ED60+228

  这时你就会看到金钱数了……注意:0x0082ED60可是个定值啊!

  第二部分:用VC制作游戏修改器。

  本程序每次运行将增加金钱至60000$。

  程序源码中的重点部分我已经做了相应的注释,这里要说的是:

  1:这段代码同时支持Win9x和NT系统,由于要找到目标进程的ID,所以我枚举了系统中的所有进程,然后根据进程名来确定我们的目标进程,但是,ToolHelp API中的szExeFile在这两种不同的系统中的返回值是有很大差异的:一个带有路径,另一个不带路径(有兴趣的朋友可以参照《如何在NT下获取进程的路径》一文)。所以,在Win9x系统中,本程序需要拷贝到游戏的所在目录中才能正确运行。

  2:要先写我们的代码(0x0082ED80),然后再改写要跳转到我们代码中去的代码(0x0049466A)。

  3:由于《红色警戒2》在程序切换的过程中会暂停游戏,所以在修改金钱数的地方做了一个延迟:以便用户有足够的时间返回游戏,这样游戏才会执行我们的代码,把金钱的内存地址放到0x0082ED60中去。如果没有这个延迟,游戏还没有将金钱地址放到0x0082ED60,ReadProcessMemory()就去获取金钱地址了,那WriteProcessMemory()也就写错了地方……

  4:用Game.exe的备份替换掉修改后的程序,因为在0x0042ED60处我们写了一些字符串。如果不这样做,该修改器第一次运行时则不会正确修改你的金钱。想想为什么会这样?当家庭作业了。

  5:最重要的一点!我十分喜欢这个游戏。做这个修改器只是练手,我平时可是不用她的……

//////////////////////////////////////////////////////////////////////////////////////////

/*
* --《Red Alert 2》v1.006 繁体中文版金钱修改器Demo--
* 作者:赵春生
* 制作时间:15:30 2005-01-27
* 主页: http://timw.yeah.net http://timw.126.com
* 本程序适用于:Win9x/NT
* 代码在Win2000P+SP4 + VC6+SP6测试通过
*/

#include<windows.h>
#include <tlhelp32.h>

int APIENTRY WinMain(HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR lpCmdLine,
int nCmdShow)

{

HANDLE handle=CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS,0);
PROCESSENTRY32* info=new PROCESSENTRY32;
info->dwSize=sizeof(PROCESSENTRY32);
BOOL report;
DWORD PID;
HANDLE hProcess;

char *szName="game.exe";//目标进程名

int i=0;

//OBJ_INFO
unsigned int OBJ_mycode[4]={0x82ED60A3,0x52FF5000,0xE9C93318,0xFFC658E0};
unsigned int OBJ_jumptomycode[2]={0x39A711E9,0x9000};
unsigned int OBJ_money[1]={0xEA60};//60000$
unsigned int OBJ_money_ip[1]={0x0};
unsigned int OBJ_code[1]={0x0};
char OBJ_path[255];//目标所在目录

GetCurrentDirectory(255,OBJ_path);//获取当前目录
strcat(OBJ_path,"\\game.exe");//目标所在目录

report=Process32First(handle,info);

while(report)
{

if((strncmp(strlwr(info->szExeFile), strlwr(szName), strlen(szName)) == 0)||(strncmp(strlwr(info->szExeFile), strlwr(OBJ_path), strlen(OBJ_path)) == 0))
{
PID=info->th32ProcessID;
//打开游戏进程
hProcess=OpenProcess(PROCESS_ALL_ACCESS,false,PID);

ReadProcessMemory(hProcess,(int *)0x0049466A,OBJ_code,1,0);
//获取0x0049466A代码:如为修改前的0x50或修改后的0xE9则继续运行,
//否则可认定游戏版本不符。
if (OBJ_code[0]==0x50||OBJ_code[0]==0xE9)
{
//写入代码
WriteProcessMemory(hProcess,(int *)0x0082ED80,OBJ_mycode,16,0);
WriteProcessMemory(hProcess,(int *)0x0049466A,OBJ_jumptomycode,6,0);

for (i=0;i<10;i++)
{
//取金钱地址
ReadProcessMemory(hProcess,(int *)0x0082ED60,OBJ_money_ip,4,0);

if (OBJ_money_ip[0]==0x0)
{

Sleep(5000);
}
else
{
//如果得到金钱地址则写入“60000$”
WriteProcessMemory(hProcess,(int *)(OBJ_money_ip[0]+0x228),OBJ_money,2,0);
i=10;
}

}

}
else
MessageBox(NULL,"请检查游戏版本。","错误!",NULL);

break;

}

report=Process32Next(handle,info);

if (report==0)
MessageBox(NULL,"游戏还没有启动吧?","错误!",NULL);
}

CloseHandle(hProcess);
return 0;
}

//////////////////////////////////////////////////////////////////////////////////////////

三:以上代码在Win2000P+SP4 + VC6+SP6测试通过。
  源码可从我的个人主页下载。
  http://timw.yeah.net
  http://timw.126.com

  
12:02 2005-1-28附件:gpd2.zip


[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!

收藏
免费 7
支持
分享
最新回复 (19)
雪    币: 519
活跃值: (1223)
能力值: ( LV12,RANK:650 )
在线值:
发帖
回帖
粉丝
2

严重支持
2005-1-29 14:38
0
雪    币: 200
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
3
精华的东西我一般都看不懂
2005-1-29 16:52
0
雪    币: 339
活跃值: (1510)
能力值: ( LV13,RANK:970 )
在线值:
发帖
回帖
粉丝
4
支持!

这些游戏里面,RA2比较有点难度,钱的地址我记得不固定。当初好一阵子找。
2005-1-29 19:03
0
雪    币: 301
活跃值: (300)
能力值: ( LV9,RANK:290 )
在线值:
发帖
回帖
粉丝
5
辛苦了,支持
这篇文章楼主不是第一次发吧,好像以前在哪里看过啊
2005-1-29 19:50
0
雪    币: 267
活跃值: (22)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
6
支持...地址确实是动态的.我向来是用金山的.当然扫描3次就会有结果了的.不过每盘都要这样....

呵呵.
2005-1-29 20:16
0
雪    币: 898
活跃值: (4039)
能力值: ( LV9,RANK:3410 )
在线值:
发帖
回帖
粉丝
7
辛苦
比较喜欢Red Alert
就游戏而言,不喜欢修改金钱之类
游戏只为游戏
2005-1-29 20:36
0
雪    币: 97697
活跃值: (200839)
能力值: (RANK:10 )
在线值:
发帖
回帖
粉丝
8
原创支持...
2005-1-29 21:46
0
雪    币: 222
活跃值: (145)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
9
收藏。。研究。。。
2005-1-29 22:18
0
雪    币: 431
活跃值: (442)
能力值: ( LV12,RANK:530 )
在线值:
发帖
回帖
粉丝
10
最初由 fly 发布
辛苦
比较喜欢Red Alert
就游戏而言,不喜欢修改金钱之类
游戏只为游戏


严重同意。
2005-1-30 11:05
0
雪    币: 200
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
11
看不懂,不过还是支持。。
2005-1-30 15:36
0
雪    币: 342
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
12
如果有vb 写的就更好了
2005-1-30 19:27
0
雪    币: 267
活跃值: (22)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
13
呵呵.

我得游戏只为了看个剧情...

跟着剧情走一把...

最感人得游戏 轩辕剑(山水画风格)3,4 等等.

每次玩好都挺伤感.

用修改器的目的无非就是快速摆脱战斗.使剧情连贯.
当然还要聪明的判断出哪里是必死点(必须死给BOSS看一下)

呵呵.
2005-1-31 22:27
0
雪    币: 339
活跃值: (1510)
能力值: ( LV13,RANK:970 )
在线值:
发帖
回帖
粉丝
14
我打游戏很菜,尤其是RPG,总要改
我有些同学狂改游戏。最搞笑的是有个伙计锁定经验,把不改打死的人打死了,结果游戏出来一个对话框:“你该游戏了吧?”
2005-1-31 23:21
0
雪    币: 431
活跃值: (442)
能力值: ( LV12,RANK:530 )
在线值:
发帖
回帖
粉丝
15
狂晕……
游戏制作人还挺幽默……
2005-2-1 10:03
0
雪    币: 258
活跃值: (230)
能力值: ( LV12,RANK:770 )
在线值:
发帖
回帖
粉丝
16
up。。。。
2005-2-1 10:05
0
雪    币: 205
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
17
char *szName="game.exe";//目标进程名

在VB应怎么实现呢?.........

解决了........................CLASSNAME怎样单独列出呢?thanks

搞定.................
2005-2-5 20:06
0
雪    币: 61
活跃值: (160)
能力值: ( LV9,RANK:170 )
在线值:
发帖
回帖
粉丝
18
支持一下!
2005-2-6 13:07
0
雪    币: 250
活跃值: (103)
能力值: ( LV6,RANK:90 )
在线值:
发帖
回帖
粉丝
19
学习!!收藏。。研究。。。
2005-2-6 21:20
0
雪    币: 200
活跃值: (10)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
20
好经典,收藏了。
2006-4-27 10:10
0
游客
登录 | 注册 方可回帖
返回
//