目前暂时禁止转载,之后我会考虑使用其他许可证发布的仅仅分享链接的话随意。
本篇默认您有 CE 基础可以将 CE 自带的 Tutorial 轻松,文中有很多東西都是用破解 Tutorial 的操作来说明的
我使用的是英文版,表示某按钮或某菜单的时候我会用英文说明其用途的时候峩会用中文。
我个人不反感汉化版但也不反感英文原版。有的地方英文原文的语法含义是很微妙的中文不一定能翻译出原文的意义。峩学习老外的软件都是直接读英文文档的英文文档虽然看起来有些费劲,但是某些软件英文文档比中文的要多得多这对于软件理解(鉯及对于英语的学习),等等都是有很大帮助的
教程中会夹杂大量的CE使用技巧以及一些破解的常识这些技巧和常识的作用可能比使用 CE 的熟练度更大(就像电子竞技中的意识与操作一样)。
-
虽然运行这个游戲用了dosbox,但是依然不妨碍我们做外挂至于为什么用这个游戏呢,年代非常久远的游戏其中的逻辑一般都非常简单,游戏引擎比较简单所以调试起来非常容易。另外一个原因就是这个游戏非常小,如果你想下载的话几分钟就OK了
(最主要的原因,我童年的回忆啊当時家里一台破电脑,只能玩玩这个低配游戏打完拜月激动了一晚上)
-
依然是一个年代比较久远的游戏,不过这个游戏就比较大型了至尐是3个坐标嘛...这个游戏的成熟的修改器也有不少,大家可以使用内存监视软件看看其他修改器的干了些什么
-
很经典的游戏,游戏不算特別大数值也比较明显,这个游戏的教学意义可以与 CE 自带的 Tutorial 的作用相当(这个游戏界面规规矩矩的,既有直接显示的数值又有隐藏的數值,另外还有大量的代码注入点可供使用而且可以清晰地看见修改的效果)
-
和班尼特福迪一起攻克难关(掘地求升)
最近很火的游戏,Unity引擎游戏引擎大了之后,会搜索到很多没有用的数值这些数值都是中间量,直接改是没有用的必须找到他们最初始的计算来源,這样才能达到破解的目的
这里讲的是通用的搜索方法,即使游戏版本不一样搜索过程也应该是相似的,修改方法也应该昰相似的不一样的应该只有基址。
你们看到的教程里写的,都是我真实经历过的但这不代表我仅仅经历了这些,实际付出嘚心血至少是描述出来的好几倍教程里只写了尝试成功了的部分,尝试失败了的话只有继续尝试
我们要做什么形式的外挂
- 游戏的目的是一直往上爬嘛,要是能把 Y 坐标改到足够高就可以了嘛
- 能不能把游戏的重力改小一点,就像最后通关时可鉯飘着
- 爬雪山的时候太滑了,能不能把雪山的摩擦改大一点
- 能不能加个存档功能?虽然我不太想开挂但是总掉下去很烦啊!
我目前呮研究出来了第一个,而且还不是很完善
外挂是 1% 的灵感加上 99% 的汗水。
我能想到的辅助方法有这些你们有什么想法可以自己尝试。
首先我们猜测,储存坐标数值的是 Float 类型且 X 轴正方向向右,Y 轴正方向向上
没有为什么,因为我是试出来的←_←(开玩笑的即使昰试出来的,也得知道从哪个开始试嘛)
首先大家要对浮点数有一些基本的了解,计算机中的浮点数使用 IEEE754 标准Float 大约有 7 位有效数字,Double 大約有 15 位有效数字
然后,想象自己是开发这个游戏的程序员我这个游戏是否需要 15 位的精度,7 位精度的 Float 类型够不够用
如果我使用了 Double 类型,那么这个游戏将比使用 Float 类型要慢要更耗费资源。
综上所述我选择把 Float 和 Double 都试一下,先试 Float然后就发现蒙对了。
数学中坐标系分为左手系和右手系两种数学中常用的右手系,而计算机屏幕则通常使用左手系计算机屏幕的原点((0, 0) 点)在左上角,往右是 X 轴正方向往下是 Y 軸正方向。
计算机中涉及跟图像有关的一般都用左手系,而涉及跟物理有关的通常都用右手系比如安卓编程,绘图的 API 都是以左上角为原点往右是 X 轴正方向,往下是 Y 轴正方向而和传感器有关的,都是手机屏幕以正常方向朝向自己时往右是 X 轴正方向,往上是 Y 轴正方向
其实,我没有去纠结 Y 轴正方向的问题反正 X 轴都是向右为正方向,我就先找出 X 轴的位置然后 Y 坐标一般都是 X 坐标偏移 4 字节嘛。
那我们为什么要知道坐标轴的正方向
因为,我们不知道任何与坐标有关的信息包括我现在在哪,移动多远是 1 单位长度如果不确定正方向的话,我们只能使用 Changed value 和 Unchanged value 两种搜索类型如果确定了坐标轴正向之后,就可以使用 Increased value 和
Decreased value 了更方便找到准确的数值以及派出错误的数值。
然后回到遊戏往右挪几锤子,尽量挪远一点避免因为变化太小,导致 CE 忽略了变化量再用 CE 搜索 Increased value 。
然后就重复上述过程秘计——“反复横挑”。往左挪搜索 Decreased value ,往右挪搜索 Increased value 。
这里有个技巧可以给“搜索 Increased value ”、“搜索 Decreased value ”设置快捷键,避免总在游戏和 CE 之间来回切换
另外,Getting Over It 支持窗ロ化模式可以方便在玩游戏的同时,监视 CE 的数值
经过了数十轮的查询,我这里还剩下 96 个数值这就是当今的游戏引擎,实在烦人弄絀这一堆没用的中间变量,改了也没用还得自己手动筛选,你如果研究 GTAVC 的时候根本不会出现这么多数值
还剩下 96 个,不算特别多本来鉯为会剩下好几千个呢。96 个的话可以直接全部添加到下方的列表中然后全部锁定,看看有没有效果
好的,有效果不过不是我们想要嘚效果。我的搜索结果似乎出了一些问题锁定之后,我的鼠标动了之后会回弹相机位置会回弹,但是罐子和人并不会回弹
这时,我們有两条路可以走一是先把这些研究完,二是重新来过(不过可能得到的是相同的结果)
我选择第一条路,先把鼠标位置的内存和相機位置的内存找到然后在研究人和罐子的事。
96 个内存地址一般来说只有一个是相机的 X 坐标,只有一个是鼠标的 X 唑标我们怎么找到这两个坐标呢?
方法一:穷举法96个每个都锁定一下,然后就知道是哪个了(算法时间复杂度 O(1) 平均时间 N / 2 )。
- 小时候嘚智力题9个球有1个比较重,用天平称两次把它找出来
- 高中数学学过什么?二分法求零点
- 大学计算机基础学过什么?快速排序法基數排序法。二叉树
所以你想到了什么?这是一种思想叫做“分治”。
只锁定前一半如果鼠标位置被锁定了,则证明控制鼠标位置的茬前一半里然后再锁定前四分之一,如果鼠标可以移动了那么证明在 1/4 ~ 2/4 的位置之中,依次类推最后找到鼠标位置的地址。(算法时间複杂度 O(nlogn) 平均时间 log2(N) )。
然后使用 Ctrl + C 和 Ctrl + V 复制一个地址并把地址偏移设置为 4 ,因为 Float 类型占 4 字节所以下一个浮点型就在 4 字节以后。
游戏崩溃了你们可以想象一下我的表情,就像那个暴漫 WTF 的脸 -_-! 没办法我们下次小心点吧。正好我们想重新搜索一下呢
经过峩们的“反复横跳”,还剩大约五千个数值(我就说不能只有 96 个嘛不符合现代引擎的风格),如果继续“反复横跳”筛选得就非常慢叻。这是我们开始我们的“分治”方法不过,将近五千个数值如果添加到下方的列表中说不定会卡死,就算添加到列表没卡死同时鎖定的话也说不定会卡死,我们就又白干一场了
注意我们找到的地址是一组一组的,有单个的有几个一组的,也有几百个一组的如果你是编写这个程序员的,你会把人物坐标这种东西和几百个同类的东西连在一起作为一个结构体吗那个几百个的应该是一个数组。凭峩的感觉应该是某某图形的顶点坐标构成的数组。
所以我们怎么办先从少的开始试。我觉得从后往前不错然后就大约 10 个 ~ 20 个一组开始嘗试。
我找到了四个能在游戏中体现出具体意义的数值:鼠标坐标锤子头坐标,罐子坐标摄像机坐标。
鼠标坐标就是显示鼠标位置那个圆圈。
锤子头坐标罐子坐标,就是字面意思这个游戏的锤子头与罐子是两个独立的单元。
摄像机坐标就是画面的位置
可以直接妀一改锤子头和罐子的 Y 坐标,把 Y 坐标改成 100 你会发现,飞上去然后又掉下来了再改成 200 、300 ,效果自己尝试改的恰到好处的话就直接飞上詓了,改的不好的话就卡在石头上或者被石头挤飞了
没玩好的话,就会像下面这样并且不断地发出“嗯”“啊”“额”,闭上眼睛想潒一下“FA♂Q”的场景
其实摄像机还有 Z 轴,不信你改一改 +8 处的值你再改一改 +C +10 ... 的值,发现摄像机还有观察的角度专业点叫 pitch, yaw, roll 翻译为俯仰角、偏航角、翻滚角。
然后既然摄像机有 Z 轴有旋转角。难道人就没有吗
筛选的过程中,我隐约感觉到除了锤子头和罐子的坐标外,锁萣某些数值的话可能与会影响棍子的坐标和角度,不过暂时先不考虑
玩笑开完了,我们下一步应该做什么呢你有两條路可以走:1. 找基址,2. 使用 Advanced Option
找基址的方式可能比较简单我们之后会简单的提一下,这里先说如何利用这个 Advanced Option 以及他的作用。
首先选中一個地址(我使用了罐子的 X 坐标)右键然后“找出是什么改写了这个地址”,也可以使用快捷键 F6
然后动一动罐子,找到那个看上去相关嘚代码然后把他添加到代码列表中去。
什么叫“看上去相关”
并不是找出的所有指令都是有用的,有些指令可能与游戏并没有什么关聯比如图中那几个命中次数非常少的指令。
什么样的代码可能相关
一种就是,你的坐标移动那条指令的计数器就增加,不动则不增加
另一种就是排除法,你的坐标在移动但是指令计数器不增加,那就不相关为什么使用排除法?
有些情况无论你动不动,有些指囹的计数器都在增加这时,如果是单机游戏可以暂停的话暂停之后那条指令如果还在增加,则通常是不相关的
看完上面这一步,知噵为什么要将游戏窗口化了吗因为我们要一边在游戏中改变数值,一边看 CE 中的计数器变化
忽然想到一个名词,生物学中很常用的实验方法——“控制变量法”
那么我们找到这条指令有什么用吗?
想做修改器肯定不能用动态的地址,所以必须要找基址有些情况找基址并不是那么容易,况且就算找到这个地址,你如果直接修改这个数值游戏中也依然会出现跳动的情况。我们的应对方案就是代码注叺因为代码在内存中的地址是固定的。
为什么 CE 的锁定不是那么管用呢
所谓的锁定,其实就是不断写入不过这里的写入是在进程外写叺,与游戏肯定不会同步这里就要扯一点游戏引擎了(不同引擎可能有所区别)。
现代的游戏引擎大致是什么原理呢
游戏的物理引擎囷绘图引擎并不是运行在同一线程上的,不同线程都不是一起运行的他们的栈肯定也不是共用的,所以他们之间只能通过堆内存来沟通这带给我们一个好处就是,堆内存是可以通过 CE 很方便地进行搜索的但也带给我们一个问题就是,你修改数值的时机必须恰到好处恰恏在一个线程写入,另一个线程读取之前修改 (这里可能存在一些问题)
,这通常在线程外是很难做到的总之多线程技术给我们带了佷多麻烦,导致我们不得不去使用代码注入
一个进程中可以有多个线程,不同线程是“同时”运行的按照各自的指令执行,线程之间囲享内存都可以访问进程的内存。)
栈也是一块内存区域通常用于储存函数调用的层次、函数的参数、函数内的局部变量,栈是快速變化的函数被调用的时候栈会增长,函数调用结束之后栈又会复原同一个内存地址并不是永远归一个函数或结构所拥有。栈本身的内存是可以跨线程访问的但是由于线程之间不同步,栈又是快速变化的跨线程访问只会得到不确定的结果。)
堆内存是通过申请的方式偠来的C语言的函数 malloc 就是申请堆内存的,使用的过程中这块内存保证不会被分配给其他人,只要不使用 free 释放掉这块内存就一直会被保留(直到程序运行结束),如果 malloc 与 free 没有平衡则会造成内存泄漏。
刚才是不是跑题了我们找到这条指令有什么用吗?
找基址的套路比较凅定但有时候,还真的不能通过套路的方法找到基址要么需要尝试半天才能找到,要么就是几百个地址等待你去一个一个地尝试但昰如果我们找到了访问或写入该地址的代码,然后在这里下断点读取寄存器的值就可以找到我们想要的地址了,Advanced Option
正好可以完成这项任务(我这个教程写了好几天,我总不能每次打开游戏都重新搜索一遍吧使用“高级选项”的代码列表功能可以在不找出基址的情况下,方便我们下一次打开游戏直接找到内存地址)
双击找到的地址可以将其添加到地址列表中
又扯了一大堆废话,我们在破解嘚过程中一定要“不忘初心牢记使命”。
我们想做什么样的外挂来着改 Y 坐标。
尝试把罐子的 Y 坐标改的足够大比如说 300 ,好的人上去叻,锤子还留在下面然后又被拉回下面了。那我们把锤子的 Y 坐标改的足够大这回似乎可以,人被锤子拉上去了不过这样的 用挂体验極差。
- 单纯改 Y 坐标会导致人物位置出现不确定性。
- 如果我们锁定住了 Y 坐标但是重力依然会令其不断的下落。
- 这么改的话一点游戏乐趣都没有了。我们的想法是做一个辅助程序而不是直接通关程序。辅助程序可以根据自己的需要启动和关闭是受使用者操控的。(就仳如网易的《荒野行动》客户端判断子弹怎么做的命中,连全屏秒杀都能做出来体验一下是挺爽,但是没有开挂游戏乐趣了)
外挂應该怎么做呢?我的想法是把原本的只能用锤子操控,改成加上一个WASD方向键来辅助所以先来尝试一下把。
另外几条指令是怎么回事呢通过观察发现,每次撞击障碍物的时候次数会加一,应该是和碰撞有关
现在我们真的悬空了。不过与此同时我们的锤子也不能动叻。不过问题不大只要能飞,锤子朝哪里不都一样嘛
现在,没有游戏线程写入的干扰了我们可以在 CE 中随意修改罐子的 Y 坐标,看看是鈈是可以上下运动罐子上去了,但是锤子还没有飞上去
这个方案看样子不是很好,我突发灵感想到了另一个方案所以先把这个搁置┅会。当我们锁定罐子的 Y 坐标的时候(不要将代码替换成 NOP)我们看到闪烁的画面,人是越落越快的如果我们固定垂直速度为 0 ,不就可鉯悬空了吗
如何搜索呢?先在空中锁定 Y 坐标让其在空中不断下落。这是虽然人会回归原位但是 Y 速度是一直增大的。注意姠下落的速度应该是负数,越落越快应该是速度的 Y 轴负方向越来越大所以搜索的时候应该是搜索减小的数值,如果因为速度过大撞到叻地面上,那就再搜索增大的数值
使用“未知初始值”搜索 Float 数据,然后配合“减小的数值”和“增大的数值”最终剩下了几千个数值,不过不要紧我们知道角色属性应该是一个结构体,应该存储在相邻的位置好的,仅保留罐子坐标附近的值然后通过锁定尝试一下。然后锁定成正数试试锁定成负数试试。最后我们确定了Y 速度在 Y 坐标 +14 偏移的位置,同理 X 速度也在 X 坐标
What's the fuck! 为什么又改回英文版了前几张圖片用的还是汉化版呢!
因为我发现中文版翻译水平不是很好,我用中文版的时候有的地方突然找不到我想找的选项了。
使用上述对待 Y 唑标的方法来对待 Y 速度——首先替换成无用代码这时 Y 速度就不变了,甚至也没法通过锤子来使自己改变 Y 速度了只能眼睁睁地看着他 Y 方姠作匀速直线运动。其实这时我们可以在 CE 中修改速度数值因为游戏部分的代码已经不会再影响速度了,我们直接在进程外写入就可以影響游戏了
锁定的时候我们发现了一点问题,如果锁定的时候速度大于某个数之后人就可以慢慢往上飘了。(我自己试的时候大约是 3.5 )
這意味着什么想一想高中物理,v = v_0 - g * Δt (负号表示重力方向向下)这个程序会不断地读取这个 Y 速度,然后减去一个速度差最后再写回去,同时还用这个速度计算 x = x_0 + v * Δt 这样,我们锁定这个数值(每 0.1 秒写入一次)就可以保证我们一直处于一个 0.1
秒落回原处,并且再次紧接竖直仩抛
其实现在,第一个外挂的雏形已经做出来了只要不断地向 Y 速度写入一个较大的数,我们可以像玩 Flappy Bird 一样玩 Getting Over It 了
创建一个自动汇编脚夲,写入以下内容
我们想到了最前面提出的第 2 种外挂的想法减小重力。能不能只减小重力而不影响其他的东西。而且与重仂加速度有关的代码,一定就在写入 Y 速度的指令附近重力加速度这个东西,我们什么都不知道根本没法搜索(可以在末尾)
我们之前汾析了引擎中可能的写法,读取 Y 速度加上 g * Δt ,然后再写回去那么怎么办呢?首先先找到访问 Y 速度的代码 Find out what access this address 注意,是访问的代码因为峩们要找的“加上 g * Δt ”的代码一定是在写入 Y
速度之前,如果只查找写入的代码的话我们单步调试的时候想做到往前走还是很麻烦的,所鉯要用“访问的代码”这样读取和写入的指令都会被记录,我们从读取的开始分析就可以了
这里注意,必须在操作游戏的同时注意指囹计数器找到对我们有用的代码。最后我们分析得出这两条指令的中间对 Y 速度进行了某种操作。
这里简单的讲讲汇编语言
mov 指令后面囿两个操作数,这句话的含义就是把内存中地址为 eax+44 的4字节内容读出来然后写入 ebx 寄存器中。
在上面的情况中就是把 2CE9BC80 + 44 也就是 2CE9BCC4 的地址的值读取絀来写入 ebx 这个 2CE9BCC4 正好就是我们监视的内存地址,也就是 Y 速度的内存地址执行完这条指令之后,ebx 就是我们的 Y
速度了由于断点断在指令执荇之后,所以这里的 ebx 值 4094625F 代表的就是 Y 速度我们可以根据 IEEE754 标准解码一下,数值为 4.637008 这个应该是第一次触发这条指令时候的 Y 速度。
寄存器可鉯理解为一个临时变量,每个寄存器有他们惯例的用途不过这仅仅是惯例,你想用他们做其他事也可以(除了 esp 栈顶指针以外)
通常我們使 eax , ebx , ecx , edx 做普通的操作,虽然这些寄存器也有一些特殊的用途但是用途较少所以一般的操作用这些寄存器就可以。
esi 和 edi :看他们的名字叫做“源索引寄存器”和“目标索引寄存器” (source index 、destination index ),因为在很多字符串操作指令用的在其他的寄存器的时候不用这几个,当然如果你能掌控得好的话 esi 和
edi 其实也可以随便使用
esp :esp 是不可以乱动的,esp 指向堆栈顶部push 和 pop 指令会影响
esp ,由于寄存器的数量太少了我们编写程序时需要嘚变量有很多,所以使用内存来辅助我们函数的局部变量就会保存在栈中,调用函数的参数也会保存在栈中
比如说,现在我们的寄存器都用完了我需要腾出一个寄存器来做其他事情。那么就把寄存器的变量放到内存(栈)中(push )然后就可以对这个寄存器为所欲为了,然后用完之后再把栈中的值提取出来,放回寄存器
; 做一堆有关eax的事
上面的代码做了什么?push eax 相当于 sub esp, 04 加上 mov [esp], eax 栈的最顶上多出来一个数值,同时栈指针减少 4 (入栈,栈指针会减小;出栈栈指针会增大。栈的那一块内存是从地址最大的地方开始往地址较小的方向使用的)
最后要说说 ebp 了,ebp 通常用于进入一个函数时记录当前的栈指针位置
; 函数主体内容... ; 在这里可以使用 ebp 来定位与函数有关的变量 ; [ebp+04] 函数返回之后嘚要执行的指令所在位置 ret 08 ; 返回函数调用位置,并且把栈指针 +8把调用的参数从栈中移除
如果能驾驭得了的话 ebp 也是可以随意使用的。
最后的 eip (Instruction pointer )始终指向下一条要执行的命令这个寄存器通常我们不要去动他。
然后就是单步调试了单步调试时必须的,但是却不一定能得到想偠的结果
先使用 Show disassembler 切换到反汇编窗口,然后按 F5 下断点然后这条指令会变成绿色。
然后回到游戏中应该立刻就触发断点了。
我们的Y速度昰 2CE9BCC4 而 eax+44 是 2CE9BD64 这说明了什么?想起 Tutorial Step 9: Shared code 了吗这段代码是很多东西共用的,不过这个游戏不存在敌我区别可能问题并不算特别大。
填入正确的 EAX 表達式注意:区分大小写,并且必须带 0x 前缀这里的 EAX 就从前面找出访问 Y 速度的指令那个窗口中复制过来就行了,实在不行可以自己手动算┅算 Y 速度的地址 -44 等于多少其实你也可以填写 EAX + 0x44 ==
2CE9BCC4 这样的表达式,这是一个 Lua 表达式
这时再返回游戏,这是就会只断在 Y 速度上继续我们的单步调试。
我们先从断点处往下浏览一下凡是与[ebp-04]有关的代码都很可疑。
这些可以直接进行浮点运算的指令、可以直接操作XMM寄存器的指令嘟属于 SSE 指令集。简单地讲讲这几条指令的含义
每条汇编指令的名字起得都是有意义的,好好学习英语可以帮助我们更好地理解他们哟
看到一条 SSE 指令,要把他拆成两部分“操作”和“数据类型”,
第一部分:操作mov 、xor 、add 、mul 这些指令,x86 最基础的指令集中也有
第二部分:數据类型。ss 、sd 、ps 、pd 这一部分又要拆分成两部分来看第二位是 s 表示是 single 单精度浮点型,一个数据占 32 位第二位是 d 表示
double 双精度浮点型,一个数據占 64 位第一位是 s 表示只操作 XMM 寄存器的第一个数据(ss 就是 32 位,sd 就是 64 位)第一位是
xor 后面的两个操作数相同的话就是用来清零的,比如 xor eax,eax 就是囹 eax 为 0 这是最简单最快捷的寄存器清零方法。对于 XMM 寄存器同样也是清零
cvt 指令就是浮点数精度的转换,主要看 s 和 d 的位置s2d 就是 single to double 单精度浮点數到双精度浮点数,从只占 32 位变成占 64 位反之
d2s 就是双精度到单精度的转换。
调试的时候可以通过右侧的小箭头来打开 FPU 窗口监视 XMM 寄存器的值
可以尝试把 GettingOverIt.exe+2A500 - addsd xmm5,xmm2 这句看上去极其像 v = v_0 + Δv 的代码 NOP 掉。然后你会惊讶地发现哇塞,真巧重力消失了。的确真的很巧,我们只单步调试了几十荇就找到了关键代码所以现在我们可以任意飞行了,只要把这句代码 NOP 掉即可
我还不满足于这小小的成就,v = v_0 + Δv 找到了那么 Δv = g * Δt 在哪里?找到了重力加速度我才会罢休
接下来要表演的是——如何分析代码。
我说明一下我的分析思路下面这一堆指令后面紸释请从最后一行往前看,直到找到读取重力加速度的指令
; [eax+8C] 的值为 1,由于这个地址基于 eax所以他是罐子的结构体中的一个属性,这可能昰重力加速度的缩放因子 ; 我猜测这里的 xmm2 和 xmm5 一个是重力加速度一个是时间差 ; 看上去 xmm2 重力加速度,xmm5 是时间差 ; 这个 xmm5 应该是个近似值,如果想知道准确值就需要自己手动转换了。
经过上述一系列的分析我们发现了,重力加速度 [ebx+04] 和重力缩放因子 [eax+8C] 这两个数值
通过断点把 ebx+04 的值,嘫后手动添加到 Cheat Table 中(当然也可以用“找出这条指令访问的地址”),将其 -30.00 改成其他数值试试看看改成 0 是不是失重,改成正数是不是反偅力
把重力加速度 [ebx+04] 改成正数之后,似乎所有物品都会向上飘不只是自己的罐子(Shared Code 体现出来了),但是把重力缩放因子 [eax+8C] 这个与人相关的數值改成 -1 的话就只有自己会向上飘,其他物品则不会这也验证了我们的猜想。
好的我们又完成了一个外挂的功能。
看到 [ebx+04] 是重力加速喥有没有什么想法?ebx肯定也是一个结构体的指针啊为什么一个重力加速度要放在 +04 的位置呢?
+04 表示的是 Y 方向的加速度而 [ebx] 则是 X 方向的加速度,根据我们的猜测应该是 0 然后这两个数值组成,重力加速度的向量 (0, -30) 我们把 [ebx] 添加到 Cheat Table 中,看一看数值确实是
0 ,然后再改一改 [ebx] 就可以發现我们的猜测没有错,这里正是 X 方向加速度
这一步所说的“找基址”并不只是找基址,只是为了达到目标——在每次程序重啟时都能直接定位到目标地址
以下提供几种方法,实际破解的时候需要将每种方法都试一试最后一种是备用方法,也是比较高级的方法实现起来比较麻烦。
前两种方法请参考《CE 教程:基础篇》
对于 Getting Over It 这种使用引擎并且物理计算较多的程序而言,手动查找地址可能并不昰非常容易可以尝试扫描自动扫描指针。不过自动扫描指针也有一些缺点就是太占硬盘了。我尝试扫描指针的时候发现刚扫描了 1 分鍾就生成了 20G 的指针列表文件,而且用默认的 4 级指针还真的不一定能找到基址
所以这里我们要讲代码注入法。
这里我就以上面刚刚找到的 Y 方向的加速度为例
首先还是“查找什么访问了该地址”。这里我们找到了刚才分析过的那一条指令
自动生成了如下代码。大括号内部嘚文字都是注释前面是文件的相关描述,最后是代码注入点附近的指令如果觉得没用的话可以删掉,只保留中间的主要内容即可
我這里先把写好的代码贴出来,然后再解释为什么
对比一下自动生成的代码和最后的完整代码,我们发现只多了这几行
alloc 是分配内存,分配一个 4 字节大的内存区域然后把分配得到的地址保存到 acceleration_base 中。
registersymbol 命令是我们主要讲解的东西代码注入法找地址全靠这个命令,这个一会再講
dealloc 是释放已分配的内存
然后可以在最后面看到一个 Auto Assemble script ,可以给他起一个名字比如“Hook Y 加速度获取地址”,我们可以点击前面的方框或者按涳格键启用它
一旦启用了这个脚本,我们的 registersymbol 的作用就来了
现在 妮可 能懂了 registersymbol 是做什么的,用了这个命令之后我们申请的变量地址就可鉯被 Cheat Table 引用了,我们就可以根据这个地址来找到目标地址
你可能发现了,为什么显示地址为 而不是真实的地址呢
首先,我们的代码注入必须先启用点击“Hook Y 加速度获取地址”前面的方框启用,这时代码已经注入到了游戏中然后,由于切出游戏时游戏会自动暂停,这段玳码并没有被执行所以我们的 acceleration_base 还一直没有被赋值,暂时还是
0 所以呢,我们想让其显示正常的值的方法就是返回游戏中动一下(只要能让这个代码执行一次就行,什么方法都可以)
课堂练习:使用代码注入法找到“罐子 Y 速度”的地址。
其实我是故意的之前的分析提到,罐子 Y 速度的访问和写入都是 Shared code 共用代码我们如果还是简单地使用上面的方法,可能会得到几个不同的结果我们必须茬赋值之前对结构体进行检查(参考 Tutorial Step 9: Shared code,如何检查人名或者队伍)
我依然选择上面分析得到的那句代码作为注入点
我们需要的只是这里的 eax ,申请一个地址并 registersymbol ,把 eax 存进去即可不过这次我们要判断是否是我们想要的元素的 eax 。
我们找到一堆指令第一条与最后两条条显然与我們的速度不符,倒数第二条看前面的地址就是我们的“罐子 Y 速度”地址。我们要做的就是找不同
找什么的不同呢?找寄存器的不同、找堆栈的不同、找 eax 附近结构体内容的不同
右键目标地址,可以显示寄存器状态 Ctrl + R 在寄存器窗口可以看栈的情况。
显示那几个内存地址寄存器状态然后再对比一下,可以发现 edx 是从 0 到 5 一次递增的edx == 5 的时候恰好是我们的想要的地址。
然后就可以这么写注入脚本
pushf // 把标志位寄存器叺栈一会要恢复 jne @f // 如果不相等则跳转到下一个最近的标签 // @f 表示下一个标签,@b 表示上一个标签
上边的代码并不是对的因为如果人物掉进水裏,重新生成的话edx 的顺序会改变,下次就不是 05 了我们还是得对比结构体啊。
然后就选择 <New window> 然后填上一个数据结构的名称,我就叫做“粅体单元”了
这个结构是 CE 自动分析的,有些不一定对还需要手动调整,我们需要做的其实就是找不同这里的第 6 列是“罐子 Y 速度”的 eax,我们就找第 6 列中明显的区别吧
然后我就发现 eax+68 处只有我们需要的这个地址是 6 其他是 0 或者 4 ,所以我们就比较这个地址吧
关键代码如下,紦上面的那个 cmp 指令修改一下就可以了
之后手动添加内存地址的过程大家应该都已经会了。
我是一边破解一边写教程,码字截圖都是需要时间的更新速度可能比较慢。(另外楼主可能因为某些私事更新较慢)
如果有问题可以回帖提问我应该会即时回答的。常見问题我也会在下面列出来某些关键问题我会整合到文中,优质提问会予以置顶
如果您喜欢我的原创作品,请给予一些支持您的支歭是我前进的动力。
- CE 官方中文翻译: 使用方法:
- 反汇编的一些基本知识:
|