断定造成伤害的函数是共用的,需要换一个方向使角色无敌,或者注入代码来只让我方不受伤害(也就是 CE 教程 step9 的内容)
CE step9 的部分原文与翻译
Often when you've found health of a unit or your own player, you will find that if you remove the code, it affects enemies as well.
你经常会找到我方单位或者你自己的血量,然后发现如果你把伤害输出的代码删了,对面也不受伤害了
In these cases you must find out how to distinguish between your and the enemies objects.
Sometimes this is as easy as checking the first 4 bytes (Function pointer table) which often point to a unique location for the player, and sometimes it's a team number, or a pointer to a pointer to a pointer to a pointer to a pointer to a playername. It all depends on the complexity of the game, and your luck
这些情况下,你必须去找出如何分辨敌我双方对象的方式,有时候这事情就很简单,比如找出指向玩家多个属性所在地址的前四个字节(也就是函数指针表的地址),又有些时候,所属方是一个团队代码,或者一个指向玩家名的多级指针,这取决于游戏的复杂度,也有运气的成分在里面
The easiest method is finding what addresses the code you found writes to and then use the dissect data feature to compare against two structures. (Your unit(s)/player and the enemies) And then see if you can find out a way to distinguish between them.
最简单的方式就是去找出哪里的代码写入了你找出来的地址,然后用解析出来的数据特征将我方和敌方所属的两个结构体进行比较,然后看看你能不能找出什么方式来辨识双方
When you have found out how to distinguish between you and the computer you can inject an assembler script that checks for the condition and then either do not execute the code or do something else. (One hit kills for example)
如果你已经找到了能够辨识你和电脑玩家的方式,你可以植入一个汇编脚本并看看情况,或者不修改这部分代码,而是做点别的(比如说让我方一击必杀)
Alternatively, you can also use this to build a so called "Array of byte" string which you can use to search which will result in a list of all your or the enemies players
同样地,你也可以用这个方式来构建一个叫做“字节数组”的字符串,一个用来列出所有敌方或者我方的列表,供伤害函数搜索所属方
去年用 CE 稍微搞过的游戏,现在拿 IDA 继续熟悉
寻找函数的位置,并对齐内存
IDA 部分
以一个不知名的函数为例
因为程序 (game.exe) 没有加壳,所以直接拿 IDA 开拆
首先要找出代码段的位置
CE 给的是这样的信息:00004098-game.exe
前面这个值是 PID,每次启动游戏都会刷新;后者即程序名,绝大多数情况不变
又用 CE 发现 game.exe 起始于 00F70000(也可以用 x64dbg 在符号页中发现),这个值每次启动都会改变,虽然一般情况应当起始于 00400000,但这里暂时用不到
在IDA中我需要的函数的第一条汇编是
.text:005E0950 push ebx
,其地址也就是 .text 后面的东西:005E0950翻到最顶部,又知道了其起始地址为 00401000
根据如下方式计算:
函数基址 = 动态链接库/游戏程序本体(dll / exe)的起始地址 + 偏移量(offset),代入得到
其在文件中的偏移地址为:005E0950 = 00401000 + offset
打开计算器,算得 offset = 001DF950
x64dbg 部分
打开程序,并附加到 game.exe ,打开“符号页”得到 game.exe 的基址为 00F70000
双击打开,发现其内部的起始地址为 00F71000,取这个值计算
00F71000 + 001DF950 = address
计算得 01150950
与 IDA 不同,x64dbg 用
ctrl + g
来跳转地址跳转
game.1150950
,如果发现 IDA 的操作码和寄存器与 x64dbg 中的一致,说明已对齐这一部分对上了,现在又怎么和 CE 对上呢
CE 部分
以血量为例,与前面两个小节使用的例子不同!
CE 里面说得很清楚:
game.exe + 8B8F3
前面又提到过,程序的标准启动地址为 400000
这里不管实际启动地址是什么,想要在 IDA 中找到这段代码,一律使用如下方式计算:
400000 + 8B8F3 = address
address = 48B8F3
在 IDA 中
g
键召出跳转,输入 48B8F3除了比较的操作码有一点点不同之外,对上了
CE 搜索的结果
之前游玩的时候就已经得出来的东西,虽然不是基址,但至少是固定的
血量追踪
前面的部分,交代了我所发现的地址,现在看看是什么函数导致了血量 (hp) 的下降
CE 选择 "find out what writes to this address"
几番操作,我操作角色碰上了对手,并受到了伤害
CE 显示这几个操作对角色的血量有影响
看操作码就知道第四个最有可能是扣血的操作
用 CE 将操作码删除后,发现如果继续被打,伤害示数存在但是血量不会下降
但是,此时我方再怎么输出也同样不会对对方造成伤害
断定造成伤害的函数是共用的,需要换一个方向使角色无敌,或者注入代码来只让我方不受伤害(也就是 CE 教程 step9 的内容)
又通过一些正常的游玩,发现第一个操作码是初始化血量;第二个则是与血量的恢复,包括自然恢复和使用道具的恢复有关;第三个,似乎与使用道具和休息的恢复有关
判断完了操作血量的函数的大意,转到 IDA ,先看看伤害函数
大致的逻辑就是先判断这个对象的某个属性码(
this[7]
)是不是什么东西(可能是属于中立方的商人),不是就造成伤害并输出。虽然最后的条件判断没看懂几番操作(
瞎想),伤害函数大概长这个样:这么看,有四种方式无敌:
游戏中,中立方在敌方踏入她所属的房间时,会直接消失。所以首先排除第一种
一击必杀不是我想要的效果,pass
buff 与 debuff
因为它的状态栏是一个条,而且没有数值,只能找敌方上/下 buff,用 CE 不停地扫。花了一点点功夫(怪真是赏脸啊),也确实给我找着了我需要的地址和进行操作的代码
movss 是单精度赋值,与之类似的还有 movsd 用于双精度赋值,由此确定这个状态条的数据类型是一个 float
类推可得类似的状态条都是单精度浮点数,之后扫地址能用得上。
又走了几十步,buff 消失了,追踪的值变成了 0 ,新的代码也出现了
我首先尝试了一下在 CE 中直接修改状态的值,但是 buff 并没有出现,预估可能需要与buff 等级同时有效才会出现,但是我已经没有回头的机会了
IDA 跳转过去,看到的其所对应的代码也验证了我的想法
又花了一个小时边玩边找,我终于发现了 buff 的初始化函数(长代码警告!)
我回忆了一下,会显示 buff 且能够在右上角显示的有大概 10 种,而且有一种来自地形,一种不会随时间下降,因此判断此处的 8 种 buff 均为随时间下降的 buff ,有了这个,获取 buff 相对就没那么抓瞎了,除了变量令人疑惑的 6 个 float ,2 个 int
下一回
因为我暂时没有掌握如何修改,这些东西可能下一次再讲,也可能......没有下次
参考依据
IDA pro与 x64dbg 地址对齐