Site icon 时鹏亮的Blog

Switch 金手指制作教程二:如何使用 IDA Pro 的 GDB 调试器

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

以下内容完整转载自:Eiffel2018 原创发布的:【金手指教程1】 除错器

前言

GDBstub 是新版大气层的功能之一, 主要用途是跟踪程序的运行, 布置断点(breakpoint), 方便找到相关代码。

之前初步尝鲜测试了一下GDB:最新大气层功能GDBstub开发金手指教学

现已经过了无数试验, 算是深入了解. 可以详细剖说一下 (是时候找数了)


要求工具

  1. 大气层版本1.2.4以上 (建议保持最新版本)
  2. EdizonSE (找地址用的, 也可以用其他工具找; 本教学利用到 ==* 功能, 需要版本 v3.8.34a 以上 )
  3. IDA PRO v7.5 SP3 (如果想深入分析, 还需要加装读取 NSOELF 的LOADER, 与及方便修改内容的 KEYSTONEKEYPATCH)
  4. 下载我制作的简单PY:markRegions.rar
    使IDA能够自动划分区段 (只支援python3, 所以你可能要把 idapython 2 升级到 idapython 3)

个别安装问题,不在此详细说明。


注意事项

为求运行时稳定, 尽可能减少载入 sysmodule,

那些 Tesla / sys-clk / noexes 等, 可以全部关了 (或者你遇到无法解决的问题时再关吧)

(我只留一个,如果你用DBI的usb传输,连这FTP也可关去)


简单介绍

以下将会以 TitleID 010005C015524000 邪恶国王与出色勇者 作为例子

这游戏是个很容易找到内存的简单RPG,

现在是利用 GDB 的功能找出 ASM代码 来修改。

  1. 查找HP

    这很简单,就是在 EdizonSE 按两下 – 减号, [u64][==*][RAM] (不限形态,自动查找), 再输入现时的HP 27, 开始第一次搜寻



  2. 改变HP再找

    回到游戏, 使主角的HP减少, 然后退到 EdizonSE 再在搜寻的位置按一下ZL, 那个 27 便即时减少为 26, 再搜一次



  3. 试验

    你可以继续重覆步骤2, 直至只剩一个侯选值(candidates),

    而我的习惯,在这剩下几个侯选值(candidates)的情况时, 会在每个侯选值按一下R3(即右磨菇), 了解内存内容.

    在你认为这个就是HP值的地方,改动一下数值, 再回去游戏看看是否被修改。



    修改后, 可确认这个侯选值是正确的,

    我们需要把它抄下来 heap+7CF1490 备用。

  4. 连接 IDA PRO

    现在准备退出 EdizonSE 接驳 IDA 的 GDB debugger,

    要注意的是, 在EdizonSE 按B或+退出前, 必须确保是 Detach 状态 (右上角写明 dmnt not attached)

    否则, 就要按一下 ZL+B , 这样才能接驳 IDA 的。

    开启 IDA, 只需要一个空白的新实例, 一开始按 Go 即可

    然后, Debugger ->Attach ->Remote GDB debugger

    之后, 我们需要先把 处理器 改成 ARM64 (AArch64):

    Debug Options ->Set specific options -> Configuration: ARM64 (AArch64)


    再把 Hostname 改成你家中的 switch 地址, PORT位预设 22225, 连接。

    选择 游戏进程的ID, 通常是最大,最后的一个

    成功后,会看到IDA PRO底色变成浅蓝色, SWITCH的游戏画面也会马上冻结(暂停运行)

  5. 划分区段

    现在我们要做的是定义区段 (define segments) 方便探究之后程序及内存

    按 ALT+F7 执行 PY 文件, 由于这是 64 位元游戏, 所以要用我附件中的 markRegions64.py (只有少数很旧的游戏,使用那32位元的ARM)


    打开执行之后,便会自动定义好各个区段,

    但遗憾的是,我只是个py新手,零经验 (附件这PY是我的第一个PY程式),

    执行时, 所定义的区段未能做到自动排序, 要人手处理一下

    在任意一个区段上,滑鼠右击再编辑edit, 之后按一下ok即可.



    排好再按OK。

    说了这么多, 总算完成第一阶段了。

    这里 4-5 我用了很大篇幅瞄述, 因这有点复杂,容易出错,

    实际操作不用10秒已能做好。

    事实上,实际操作也要经常 在IDA 退出 Detach from process, 回去edizonSE找地址,

    经常来来回回, 此步骤必须要熟练,要快。

    (只是当 detach 退出进程, 在第二次进入 IDA 时, 若游戏没有重启, 便不用再设定 processor 及 segments 了)

  6. 跳到内存位置

    按下 G , 然后直接贴上

    刚才我们记下的内存地址 heap+7CF1490

    看到了, 这个 0x1D, 就是刚才的内存地址

    为了清楚好看, 我会再按几下D (或者如图右点,改成Double Word)

    之后还要按 H 把它改回十进制。

    改变地址的变数形态, 分析附近内存是甚么,

    这个也是很有意思的, 要多多练习一下

    题外话: 如果你想修改这 29 HP, 或后面 估计是最大HP 的 29, 可以在这里编辑啊,不过你要输入16进制的数字

    (但如果你打算做大量修改, 也可以跳到 Hex View 窗口, 改成 所有资料以 32位元形态 十进制数 显示, 然后按 F2 直接编辑)

  7. 下断点 (breakpoint)

    快捷键就是 F2, 在刚才 29HP 的位置上按一下 F2

    这画面有很多细节地方要学习的. 有兴趣的朋友应该要根据官方文件逐一测试。

    暂时初学, 可以直接取消 Read, 只使用 [Enable][Hardware][Write][Break] 便可以

    成功后, 可看见刚才的 29HP 变了红色(正常是深红色,我私下在IDA选项内改了粉红色)

    而且,下面 Breakpoint 列表视窗 可看到一个新的断点

    这断点的意思就是让程序继续运行直至程序在这内存位置[写入]新的内容

    (另有 Read断点 与及 CODE区段中的软断点, 也很常用, 日后也应该要学习的)

    现在按 F9, 游戏可继续跑了

  8. 触发断点

    继续玩游戏,尝试使角色扣血

    就在准备要扣血时, 游戏突然停止了!

    我们再看看IDA, 弹出了讯息, 原来是刚才的断点触发了

    之后, IDA View-PC 窗口自动跳到了 触发断点的程序.

    所谓 PC, 是32个64位元寄存器(registers)的其中一个。

    现在这 IDA View-PC 窗口是会自动追随PC的值跳动的。

    PC所记的地址 main+D2058 , 就是现在运行停顿的地方(蓝色底色一句)

    如果现时要看其他位置,要按 G 跳去;想退回去看之前断点的地方, 可按ESC

    不应该人手改变PC寄存器的值, 这会影响往后运行的结果!

    这句 main:00000000000D2058 69 0A 00 B9 STR W9, [X19,#8]

    69 0A 00 B9 是机器码 machine code, 平常我们写金手指 B9000A69, 是反转来用的

    STR W9[X19,#8] 是反组译出来的 ARM64v8 指令

    意思是 STORE (写入) W9 (寄存器X9 的 32位元 DoubleWord 形态: W9) 到这个位址 [X19, #8] (64位元寄存器X19,加上偏移值(offset)8的位置)

    先看看右边 X19是甚么, 它记下了 0x00000024B02F1488 , 在旁的注释看到是属于 heap 区段

    所以 [X19, #8] 应该就是 0x00000024B02F1488 + 0x8 = 0x00000024B02F1490 了

    正是刚才下的 breakpoint 位置

    把 鼠标 移到 [X19, #8] 上面, 可看到 现时这位置的值是 29

    把 鼠标 移到 W9 上面, 可看到 准备要写到这位置的值 0x1B, 心算一下, 就是 27

    现在, 我们先 关闭了刚才的断点, 因为这个断点如果一直开着, 程序不能够继续跑的。

    这是现时 大气层GDBstub 的一个小小问题,

    不能在这时按F7/F8跳去下一行,

    也不能狂按F9强迫它运行,

    这只会令程序崩溃, 希望日后在这种 Single Step Debug 方面可改善

    关闭断点方法, 在下面列表, 右点便看到。

  9. 修改程序

    你可以想像一下, 假如这句指令不执行, 那么不就是 [HP不减] 了吗?

    这修改能否成功需要尝试才知道. 这也有可能令到HP增加也变成无效的.

    不过一试无妨. 简单把这句改成 NOP 便可以了。

    假如你安装好 keystone + keypatch 便可以像我一样按 CTRL+ALT+K 跳出这画面

    把原本的 STR W9, [X19,#8] 人手输入 改为 NOP, 再按一下Patch便可以

    (之后它会跳到下一个指令,你便要cancel)

    成功的话, 看到 main+D2058 的指令被改成了 1F 20 03 D5 NOP

    聪明的小伙伴应该知道, 这就是对应金手指的

    04000000 000D2058 D503201F

    不过, 我们这样用GDB修改了内存或指令后,

    暂时是无需要编写金手指代码才可测试的,

    直接再按一下F9 运行, 便可继续调试了.

    (按F9前,再检查一下你刚才的断点是否已取消或删除,小心,不要一直开着!)

  10. 进行调试

    回到游戏,再玩一下,

    即时看到效果, 刚才 HP29 本应变成 27 的, 但现在没有改变.

    主角一直保持HP 29 (算是初步成功了)

    可惜不妙的是,现在连敌人的HP也不减了!

    这确是很多新手会不知所措的问题。


虽然这个HP不减的金手指还未完成, 但已完整说明以GDB找出ASM代码的方法。

希望小伙伴能够触类旁通, 轻易找到其他想要修改的金手指
(例如HP29后面的4,应该是MP吧,你可以同样去用断点改,敌我通用应该也没所谓吧;再后面攻防能力等,因为很少写入,或许可以用Read作为断点,达到修改目的)

后续教程将讲解 敌我判断。


特别鸣谢

Eiffel2018 原创发布:【金手指教程1】 除错器


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

本站资源,请 注册城通账户 后,使用客户端下载,参考教程:城通网盘如何使用客户端下载文件


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


与《Switch 金手指制作教程二:如何使用 IDA Pro 的 GDB 调试器》相关的博文:

Exit mobile version