C++编写红警3 1.12版本修改器
首先准备好游戏和工具,工具包括Cheat engine,OllyDbg,VisualStudio,版本无所谓。然后观察游戏目录结构,因为我这里是安装版的,游戏网站对游戏文件做了一点改动,把RA3.exe给我隐藏了,有的游戏网站会把游戏的exe文件改成dll文件,就是改了个后缀名,然后强制让你用网站的下载器或者登录器开启游戏,特别流氓。
修改器制作过程如下:
查找真正的游戏进程
CE配合OD查找基址
使用MFC创建基本对话框并编写代码
测试
查找真正的游戏进程
我们直接使用CE修改游戏数据的时候,发现有两个游戏进程,修改带版本号的那个才会管用。为什么会有两个进程呢,因为我们用RA3.exe启动的游戏,它的功能是显示splash窗口,然后创建真正的游戏进程。如果用RA3.exe启动游戏的话,我发现OD没办法附加到游戏进程进行分析,所以我才去找真的游戏进程对应的exe文件。
图片中第二个才是真正的游戏进程,因为忘了原版游戏是不是带exe后缀名了,反正我这个是不带的,我找到后自己加上的。如何找到它并自己启动它呢?当然是OD分析RA3.exe了。也很简单,RA3.exe的作用就是创建游戏进程啊,所以下断CreateProcess函数就好了。为啥要这么麻烦?在任务管理器里面找到相应的进程,然后打开文件位置不是马上就定位了吗?事实是,理论可行,我这样做了只是定位到Data文件夹,没有定位到ra3_1.12.game文件,而且直接加上exe后缀启动游戏会崩溃。崩溃是因为没有传启动参数。好了,bp CreateProcessA下断。发现根本断不下来,好吧,换bp CreateProcessW,这次断了。
好了,我们知道它是如何启动的了,知道参数了,直接新建快捷方式加上参数启动试试~~记得把ra3.exe的参数去了,我们不需它。
双击启动…..不出所料的成功! 然后我们也知道了根目录下那么多SkuDef文件是怎么用的了~
到这里我们知道了红警3的真正的游戏进程了。
CE配合OD查找基址
接下来就是查找基址了。千篇一律的CE反复查找工作,应该没啥难度,找吧~
我们以金钱为例说明吧~ (写博客好累~我比较懒~我想我可爱的小女朋友了~ ) :(
好了,打开游戏创建一个对局,我是随便创建的,起始资金10000都懒的改,CE慢慢定位金钱的当前地址吧~ 初次搜索10000,花点钱,在搜索,在花点钱,在搜索,剩下5个,然后不好筛选了,那就改改试试,发现就一个管用 (我这里是倒数第二个,估计大家的也是~)那就是它了 too easy~
然后当然是查找是谁访问了它啊
然后找到了第一级偏移(以后我简称一偏)
在搜索十六进制的05795910,看看出啥
就一个,然后在看看谁访问了它~~
出了数组,形如 mov eax,[ecx+eax*4] 这样的都是数组,偏移查找也是一样的。不过这里要说明白,偏移应该是eax*4,但是明显eax的值是那么大的数,它是mov之后的结果,我们这里没办法知道mov之前eax的值,所以没办法,上OD吧,难受的不是上OD,而是我们已经用CE的调试器附加了游戏,OD无法附加了,一切还得重来~~哭瞎了 我本来就懒,还得重来 :(
没办法,来吧,注意看mov eax,[ecx+eax*4] 的地址是0083BE32,好吧,关了游戏,关了CE,然后OD启动游戏,ctrl+G来到0083BE32
和CE显示的东西一样,说明找对对方了。这个函数很小啊,大家猜猜它是干啥的 :)
然后在函数头部下断,为啥是头部呢?事实上只要是mov eax,dword ptr ds:[ecx+eax*4]一句前面就行,但是 我们发现了jb 关键字,不知道它是不是会跳转,(仔细观察分析会发现跳转了确实会影响eax的值,但是就不会执行下面的了,所以在mov eax,dword ptr ds:[ecx+eax*4]上一句下断就行)所以在头部走一边吧。F2,回游戏,结果马上断了,F8跟进,到地方
eax为0,早知道就直接猜了,费这么大劲干啥,呃呃呃,我真的很懒。。。。
好了,二级偏移有了,0 也就是mov eax,dword ptr ds:[ecx+0],三级偏移应该找ecx的值,开游戏,上CE,重复来一次。。。
第二次来到这里
eax*4为0,忽略,ecx为3ED2E40,就找它。
找到很多地址访问3ED2E40,然后随便再找一个,发现只有第一个是不变的,后面的都错了
好了,找第一个发现三偏是E4。再找
这里发现访问的太多了,每个跟进发现偏移都不同,这时候我们要大胆的猜,因为之前的地址都是03多少,这里我们也大胆的认为这里也是03开头的地址。。。。然后就找到了四偏,28
再找,发现基址
然后加个指针验证一下
完全正确
不容易啊,折腾好几次啊
使用MFC创建基本对话框并编写代码
终于可以写代码了。
MFC创建个对话框,随便托几个控件,写写提示,我就不管好看不好看了。
加上定时器实时判断游戏是否开启,并实时读取各种数值
我在OnInitDialog()中写的。
头文件的变量声明,包括函数和控件的成员变量。
OnTimer函数,不截图了,太长。
“`C++
void CRA3CheatDlg::OnTimer(UINT_PTR nIDEvent)
{
hWinmine = FindWindowA(NULL, “命令与征服:红色警戒3”);
GetWindowThreadProcessId(hWinmine, &dwPID); //获取进程标识
if (dwPID == 0)
{
m_Status = “获取PID失败”;
UpdateData(FALSE);
return;
}
hProcess = OpenProcess(PROCESS_ALL_ACCESS, false, dwPID);
if (hProcess == NULL)
{m_Status = "进程打开失败";UpdateData(FALSE);return;
}m_Status = "进程打开成功";
GetDlgItem(IDC_STATIC1)->SetWindowTextW(m_Status);switch (nIDEvent)
{
case GAME_PROCESS_STATUS:case READ_FINANCING:if (0 == ReadProcessMemory(hProcess, (LPVOID)(FinancingBaseAddress), &FinancingBaseAddressValue, sizeof(DWORD), &dwSize)){return;}ReadProcessMemory(hProcess, (LPVOID)(FinancingBaseAddressValue + FirstOffset), &FirstOffsetValue, sizeof(DWORD), &dwSize);ReadProcessMemory(hProcess, (LPVOID)(FirstOffsetValue + SecondOffset), &SeconfOffsetValue, sizeof(DWORD), &dwSize);ReadProcessMemory(hProcess, (LPVOID)(SeconfOffsetValue + ThirdOffset), &ThirdOffsetValue, sizeof(DWORD), &dwSize);ReadProcessMemory(hProcess, (LPVOID)(ThirdOffsetValue + ForthOffset), &ForthOffsetValue, sizeof(DWORD), &dwSize);m_CurrentFinancing.Format(_T("%d"), ForthOffsetValue);GetDlgItem(IDC_STATIC2)->SetWindowTextW(m_CurrentFinancing);case READ_POWER:default:break;
}
}
好了,到此金钱的代码写完了。测试
游戏数值变了,成功~~~
这是资金,电力道理一样。有了c++版本的,其他各个语言的就没问题了。我在新浪微博上写了植物大战僵尸的易语言的源码,想看易语言版本的搜索TC王者就能找到。
写了一下午的博客,希望大家会觉得有用,我偷懒不写电力的了。真的好懒。。。
吐槽表弟,我都写完教程了,你咋还没写出外挂。。。。
然后,大家要是想看视频教程的话,下方留言,人多了我就出视频。
最后。。。我把代码传到csdn了,然后是用vs2017写的,很多同学可能不可直接打开。。代码还是可以看的。http://download.csdn.net/download/tc00tc/9930994
四季更迭衷情秋,三生缘定我心彤