请知悉:本文最近一次更新为 2年 前,文中内容可能已经过时。

以下内容完整转载自:Eiffel2018 原创发布:【金手指教程2】使用 GDB 找出 敌我判断 的特徵

继续上次 未完的教程

之前调试发现, 把 main+D2058 改成 NOP, 会令到敌我皆变成 HP不减, 需要进行 敌我判断


基本概念

何谓 敌我判断 ?

游戏开发者在同一个函式, 同时处理我方及敌人的属性。

我们要找出特征, 来分辨 处理中的对象 是我方 还是敌人。

我试用过的解决方法有很多种, 记得的有

1) 用 pointer 指针 可以很轻易的解决, 但每个金手指只能针对单一角色处理, 如果角色多了,有时会变成一个很大的文件。

2) 分析 我方和敌方角色的内存附近范围内容, 做对比, 试验, 找出 程序内建的判别方法 Flag

使用 GDB 找出 敌我判断 的特征1

3) 查看扣减HP的共用函式的寄存器 [X0] 最初的地址, 通常这个就是角色对象的类 Object Class, 敌我所用的Class很多时是不同的, 而且偏移0的 [X0] 是 object地址的最末三个数字 会是固定的。

4) 以上皆不可行时,便要用GDB追踪程序的运行,看看有没有判断敌我的程序 (经常可以看到HP0之后死亡的处理,敌我肯定不一样的)

5) 利用开发引擎的特性进行破解, 例如 Unity的il2cpp 或是 Unreal Engine以函式地址找寻函式的本来名称, 都可以对找出敌我判断大有帮助。

6) 如果你真的找不到, 或许看看 外网 fearless 上 Cheat Engine 的高手 破解PC版本的相同游戏 是怎样分辨敌我的, 虽然平台不同,处理器也不同, 但代码往往是大同小异的!

游戏需要敌我判断, 真的太多了, 真不记得某个游戏用哪一种手法.不用问了


回归正题, 上一次女勇者变成了无敌之后, 竟然打不倒敌人,

先查看一下两边的内存。

女勇者的内存位址,我是知道的,

就是刚才下断点的 heap:00000024B02F1490 附近

因为该句指令是 [x19,#8]

可以断定这内存的范围是 由 heap:00000024B02F1488 (即是X19) 开始。

使用 GDB 找出 敌我判断 的特征2


然后我顺势把这区块中, 每一个变数 跟 游戏内 女勇者的数据 对比一下。

但战斗还没完, 逃跑吧, 退一步海阔天空…. 这样才看到女勇者的数据

使用 GDB 找出 敌我判断 的特征3

LV3, HP29/29, ATK 18, DEF 12, SPD 9


在内存按n, 把知道的栏位添加名称

使用 GDB 找出 敌我判断 的特征4

剩下最前的 1001 可能是经验, 也可能不是,

后面3个浮点数,暂时也不知是什么, 先不管了


之后我们要记录这个格式结构 define structure. 方便往后使用

选择范围, 滑鼠右击, Create Struct from Selection

使用 GDB 找出 敌我判断 的特征5

按n 给个名称 actor

使用 GDB 找出 敌我判断 的特征6

回到 IDA View-PC, 看到这对象被收起了

使用 GDB 找出 敌我判断 的特征7

按 Ctrl + 便可打开, 变成这样

使用 GDB 找出 敌我判断 的特征8


好了,现在要取得敌人的地址。

在刚才触发断点的地方, main+D2058 按 F2 加一个 software breakpoint (软件断点)

这 软件断点 跟 硬件断点 不同的地方,

就是这个只能在程式码下, 如果你在资料段下的话, 是不能触发的。

另一个特点是, 硬件断点最多只可下4个, 而这软件断点没有限制,只要你的电脑够强劲,下超过100个断点也不成问题.

(我有时就是会这样的,渔翁撒网,看看那一个函式会触发)

使用 GDB 找出 敌我判断 的特征9

下好了F2, 就按F9让游戏继续跑了。


这 软件断点, 能捕捉打击敌人的刹那。

使用 GDB 找出 敌我判断 的特征10

IDA 也停了下来, 不过刚才 main:D2058 原本是好端端的 NOP, 现在变成了 FF FF FF E7

使用 GDB 找出 敌我判断 的特征11

这其实是 大气层GDBstub 的另一个小Bug. 那个地方更新时只用了8位元,而不是32位元,

但不要紧, 这不影响 SWITCH的运作,

如果你需要, 也可以关闭这断点之后, 更新内存 Refresh Memory

使用 GDB 找出 敌我判断 的特征12

这便正常

但无论如何,你必须关闭断点,之后才能进一步操作

使用 GDB 找出 敌我判断 的特征13

否则…. 这大气层会崩溃的, 小心!


刚刚我们让断点触发了.

敌人的内存在什么地方呢?

答案就是 [X19, #8]

在右边 暂存器X19 旁边的箭头点一下

使用 GDB 找出 敌我判断 的特征14

这就是其中一个敌人的内存了

使用 GDB 找出 敌我判断 的特征15


但今次我们不必人手把变数一个一个的改成十进制DoubleWord

因为我们之前定义了一个 Actor 的 物件结构 structure

用 Alt+Q 就可以了

使用 GDB 找出 敌我判断 的特征16

又收起来了, 按 CTRL+ 把它扩张

使用 GDB 找出 敌我判断 的特征17

这就看到了。

使用 GDB 找出 敌我判断 的特征18


还是看不到 敌我分别?

再来一个, 把另一个敌人的内存位置也找出来

不过,你千万不要立刻打开刚才的断点,然后按F9

你需要把浮标(即是PC)移到下一行,才可再次启动之前那个软件断点 (这大气层新功能的缺陷,没办法了)

令PC跳去下一行,方法有几个:

你可以按F8或F7几下, 第一下通常会跳到SDK的区块的,要多按两三下才跳回main;

(这是因为SWITCH进程不是单一的, 而这大气层GDB, 暂时也不能只查看单一进程)

另一个方法是把鼠标移到下一行,然后按F4

使用 GDB 找出 敌我判断 的特征19

这个方便, 我经常用的。

还有,你可以在右边 PC寄存器 上用滑鼠双击, 人手加上4 (像这样)

使用 GDB 找出 敌我判断 的特征20

(不过要留意,你下断点那句,就不会执行了; 现在是NOP没所谓)

比较高阶的方法是在 断点设立时, 在condition 的位置输入 PC=PC+4;1

这就会自动帮你在触发断点时,前进下一个指令 (同样地,你下断点那句就不会执行了; 但你可以连 Break 也取消, 配合 msg 把想知道的东西,全记录下来)

使用 GDB 找出 敌我判断 的特征21


无论如何, 你都可以找到另一个敌人的内存位置, 再 ALT+Q 套用 actor结构。

使用 GDB 找出 敌我判断 的特征22

仍是看不出敌我特征? 把他们打横排列吧!

使用 GDB 找出 敌我判断 的特征23

这很明显吧, 在第一行, 女主角是1001, 两个敌人是2031

这是什么呢? 这都是十进制数, 按道理这里并非 批次判断 的.

1001 / 2031 等, 很有可能是角色的ID 因为两个敌人都叫 苔玉蛙, 而ID相同是2031

按一般游戏规划角色或敌人ID都会分开的, 例如玩家角色是10XX , 敌人ID是由2000开始

暂时这只是推测,要进行多些游戏才知道结果。

不过我们现在已可以做一个敌我分办,

凡是角色是 1001 就是女主角小勇

先试一下吧

反正不试就卡在这里,双方HP不减, 无法继续游戏 (也要给我机会继续讲解啊)


由于刚才 触发点 只得一行 STR W9, [X19,#8]

无法进行敌我判断的, 至少要找一个位置, 让我们

1. 获取 [x19]的值

2. 检查这值是否1001

3. 如果是主角跳过下一句

4. 写入新HP

5. 反回原本地址

需要4至6行代码

一般函式和函式之间的空隙是都不足够的。

我们要找一大块空白的地方来扩充

按一下 CTRL S

使用 GDB 找出 敌我判断 的特征24

留意到 main 区段是去到 0x375000 结束

可以跳到它前面 0x374F00 看看是否空白

使用 GDB 找出 敌我判断 的特征25

这往往是有空间的, 100分之99的机会有充足空间给你用。

(我自己习惯是用E00结尾的, 因为我名字是E字开头的)

今次只是教学, 先用 374F00 写 code cave 吧

使用 GDB 找出 敌我判断 的特征26


未开始写之前, 你最好先把这位置全改成 nop

Keypatch -> Fill Range

使用 GDB 找出 敌我判断 的特征27

然后在上面按一下 C (make code)

使用 GDB 找出 敌我判断 的特征28

变成这样

使用 GDB 找出 敌我判断 的特征29

#本身Keypatch是有BUG的, 如果你见到内存是 ? ? ? ? 般,

就不能用Keypatch直接改了, IDA会崩溃的,

幸好连接GDB时,会自动变成0, 这样用Keypatch没问题


之后,在开始的地方按N,给它一个名称 HP_hack

使用 GDB 找出 敌我判断 的特征30

然后 按 ESC 返回刚才 断点的地方 main+D2058,

把原本的 NOP 改写一句 BL HP_hack

使用 GDB 找出 敌我判断 的特征31

这就做好了呼叫扩充函式的动作.

# 部分情况,原程式没有把X30放到SP (STACK)时, 不能使用BL和RET的, 要改用 B 替代


另外, 我们还要看看有什么寄存器可以使用

使用 GDB 找出 敌我判断 的特征32

主要看后面十多句,

X0 和 X1 应该可以用的, 它们都是会被立即改变的寄存器,

现在, 可以返回刚才的 HP_hack , 开始 Ctrl Alt K 写代码了


我想说明一下这种转跳的输入方法,

使用 GDB 找出 敌我判断 的特征33

PC即是现时运行的位置, 可用一点 “.” 来代替,

+4就是下一行指令, +8就跳过一行去到第三行。

所以 BEQ .+8 的意思是 如果结果相同, 会跳一行 (即是下一行不会执行)

变成这样再继续

使用 GDB 找出 敌我判断 的特征34

好了,写好了

使用 GDB 找出 敌我判断 的特征35


如果你喜欢,更可以把原本的 STR W9,[X19,#8] 改成 STR WZR,[X19,#8]

WZR内容永远是0的 (至少,在大多数情况下是这样), 改成这样就可以秒杀敌人!

秒杀, 我可加快游戏进程, Why not? 就改 WZR吧。

使用 GDB 找出 敌我判断 的特征36

可以再 F9 了


又玩了一会, 没问题

(其实继续玩下去,会有伙伴,到时敌我判断就得稍微改一下, 例如 1001 改成 2000, BEQ 改成 BLE或BCC等)

不过我写稿写了一晚,还没写完, 要先停一下. 以后玩到再改吧。

接下来最后的事, 是教大家如何把CODE CAVE程序变成金手指

其实也很方便, 在Hex View的窗口按一下4, 而且改成 column 1

使用 GDB 找出 敌我判断 的特征37

像这样, 之后选取代码 (留意地址要8个位就够了)

使用 GDB 找出 敌我判断 的特征38

贴到 notepad++, 把中间的两个空白改成一个,再在每行前面加 04000000便可以了

[HP hack]
04000000 00374F00 B9400260
04000000 00374F04 710FA41F
04000000 00374F08 54000040
04000000 00374F0C B9000A7F
04000000 00374F10 D65F03C0
04000000 00374F14 D503201F

之前那句 BL 呼叫 HP_hack 也 照板煮碗 的做一次

使用 GDB 找出 敌我判断 的特征39

加到最末尾

04000000 000D2058 940A8BAA

完成!

恭喜你升级了


特别鸣谢

Eiffel2018 原创发布:【金手指教程2】使用 GDB 找出 敌我判断 的特徵


如您从本文得到了有价值的信息或帮助,请考虑扫描文末二维码捐赠和鼓励。

尊重他人劳动成果。转载请务必附上原文链接,我将感激不尽。


与《Switch 金手指制作教程三:如何使用 GDB 找出 敌我判断 的特征》相关的博文:


留言

avatar
😀
😀😁😂😅😭🤭😋😘🤔😰😱🤪💪👍👎🤝🌹👌