Pokemon Center | 口袋中心 以口袋妖怪为主题并带有其他动漫游戏的讨论

 找回密码
 加入口袋中心
搜索
查看: 1929|回复: 0

【学习手记/转】debug实例2

[复制链接]

3344

回帖

612

现金

484

勋章券

超级版主

Rank: 26Rank: 26Rank: 26Rank: 26Rank: 26Rank: 26

积分
21859
QQ

时光印记Lv.3挥金如土勋章水中王者勋章Lv3Omega红宝石发售确认纪念章Alpha蓝宝石发售确认纪念章金银好CP-Ho-oh/LUGIA【里】金银好CP-Ho-oh/LUGIA【真·正常向】异化型LUGIA【M超梦版】

发表于 2015-3-25 19:49:47 | 显示全部楼层 |阅读模式
本帖最后由 jiangzhengwenjz 于 2015-3-25 22:27 编辑

原作者FBI agent,这次debug的难度个人觉得显著小,但作者认为其难度高于上一篇。

拒绝转载,这篇不是教程是手记,仅作记录和分享之用,若要转载请转原帖。

这一篇的内容是扩充道具名称字母数量。

第一部分:目的介绍

目的:扩充道具名称字母数量

基本想法:读取道具名称的地址时,设置新程序,若第一个字节为FF转而读取道具名称的指针,以突破原表格的限制。

第二部分:认识数据表格

由于bulbapedia上有现成的道具数据结构的资料,所以可以查资料。或是通过搜索道具名称的ASCII码来找到表格。

顺便,给出道具表格的数据结构:(来自bulbapedia)

Offset        Field        Size
0        Name        14 bytes
14        Index number        2 bytes
16        Price        2 bytes
18        Hold effect        1 byte
19        Parameter        1 byte
20        Description pointer        4 bytes
24        Mystery value        2 bytes
26        Pocket        1 byte
27        Type        1 byte
28        Pointer to field usage code        4 bytes
32        Battle usage        4 bytes
36        Pointer to battle usage code        4 bytes
40        Extra parameter        4 bytes

这样,限制一清二楚。

第三部分:debug

以下以burn heal作为例子(火红U)

首先如何下断这个太容易了,在burn heal的地址那里添加bpr即可(no$gba应该是"?")

打开背包转到burn heal的那一页,会被断到。

那么接下来自然是反汇编,利用vba的反汇编功能或vba-sdl-h的dt指令即可。

游戏在0x8D90被断,而在0x8D84注意到push {lr}指令。

那么自然是先分析下这个程序:

  1. MAIN:                                 
  2. ROM:08008D84                 PUSH    {LR}
  3. ROM:08008D86                 MOV    R3, R0
  4. ROM:08008D88                 B       SECTION

  5. SECTION2:
  6. ROM:08008D8A                 STRB    R2, [R3]
  7. ROM:08008D8C                 ADDS    R3, #1
  8. ROM:08008D8E                 ADDS    R1, #1

  9. SECTION:
  10. ROM:08008D90                 LDRB    R2, [R1]
  11. ROM:08008D92                 MOV    R0, R2
  12. ROM:08008D94                 CMP     R0, #0xFF
  13. ROM:08008D96                 BNE     SECTION2
  14. ROM:08008D98                 MOV    R0, #0xFF
  15. ROM:08008D9A                 STRB    R0, [R3]
  16. ROM:08008D9C                 MOV    R0, R3
  17. ROM:08008D9E                 POP     {R1}
  18. ROM:08008DA0                 BX      R1
复制代码


这是一个典型的读取-存入-循环-判断的例子,做的事情也很清楚:

从ROM读取名称数据→写入内存(如果注意下内存地址的话是0x020041F1,对应于r0,而r1对应于文本的指针,相当于拿这两个寄存器的值作参数)

分析完毕,那么接下来不妨在0x08008D8A下断,看看这段程序如何被调用(注意r1来确保在合适的地方断了)

发现前面是bl指令,在8db4的位置。(注意bl占用4字节的特性)

而这里又是对应了一段程序:

  1. ROM:08008DA4                 PUSH    {LR}
  2. ROM:08008DA6                 MOV    R2, R0
  3. ROM:08008DA8                 B      08008DAC
  4. ROM:08008DAA                 ADDS    R2, #1
  5. ROM:08008DAC                 LDRB    R0, [R2]
  6. ROM:08008DAE                 CMP     R0, #0xFF
  7. ROM:08008DB0                 BNE     08008DAA
  8. ROM:08008DB2                 MOV    R0, R2
  9. ROM:08008DB4                 BL      08008D84
  10. ROM:08008DB8                 POP     {R1}
复制代码


显然,此处的作用是找到FF的位置,然后把它存在R0。而这个程序的参数也是R0。可能是用于在内存中完成单词的拼合。

那么在8DA4下断,依然通过r1来确保在合适地方断掉。

发现是在0x108596通过bl指令被调用,查看这个指令属于哪个程序。(反汇编)

程序稍显复杂:

  1. ROM:08108560                 PUSH    {R4,R5,LR}
  2. ROM:08108562                 MOV    R4, R0
  3. ROM:08108564                 LSL    R1, R1, #0x10
  4. ROM:08108566                 LSR    R5, R1, #0x10
  5. ROM:08108568                 LDR     R0, =0xFE940000
  6. ROM:0810856A                 ADDS    R1, R1, R0
  7. ROM:0810856C                 LSR    R1, R1, #0x10
  8. ROM:0810856E                 CMP     R1, #1
  9. ROM:08108570                 BHI     SECTION

  10. ROM:08108572                 LDR     R1, =a489
  11. ROM:08108574                 MOV    R0, R4
  12. ROM:08108576                 BL      08008D84
  13. ROM:0810857A                 B       0810858C

  14. -----------------------                 一些指针

  15. SECTION:
  16. ROM:08108584                 LDR     R1, =a423
  17. ROM:08108586                 MOV    R0, R4  
  18. ROM:08108588                 BL      08008D84
  19. ROM:0810858C                 MOV    R0, R5
  20. ROM:0810858E                 BL      0809A8BC
  21. ROM:08108592                 MOV    R1, R0
  22. ROM:08108594                 MOV    R0, R4
  23. ROM:08108596                 BL      08008DA4
  24. ROM:0810859A                 POP     {R4,R5}
  25. ROM:0810859C                 POP     {R0}
  26. ROM:0810859E                 BX      R0
复制代码


其中跳转的两个地方都已经分析过是干什么的了,注意到在10858E有未知程序。

根据ROM中程序的一般规律,结合mov r1, r0可以推测这个程序把内存中文本的指针写入r0。

当然我们还是反汇编来看看:

  1. push {lr}
  2.         lsl r0, r0, #0x10
  3.         lsr r0, r0, #0x10
  4.         bl 0x809A8A4
  5.         lsl r0, r0, #0x10
  6.         lsr r0, r0, #0x10
  7.         mov r1, #0x2C
  8.         mul r0, r0, r1
  9.         ldr r1, =(0x83DB028)
  10.         add r0, r0, r1
  11.         pop {r1}
  12.         bx r1
复制代码


注意到其中又有bl跳转,那不妨在跳转的地址下断(0809A8A4)

依然忽略掉不符合条件的break,注意到此时r0的值极为特殊恰好是0xF,对应burn heal的道具ID!(如何确定不是巧合?多次测试即可)

在09A8A4反汇编,得到程序代码(标签版)

  1. main:
  2.         push {lr}
  3.         lsl r0, r0, #0x10
  4.         lsr r1, r0, #0x10
  5.         mov r0, #0xBB
  6.         lsl 0, r0, #0x1
  7.         cmp r1, r0
  8.         bhi return_zero
  9.         add r0, r1, #0x0
  10.         b end

  11. return_zero:
  12.         mov r0, #0x0
  13. end:
  14.         pop {r1}
  15.         bx r1
复制代码


而其中
  1. lsl r0, r0, #0x10
  2. lsr r1, r0, #0x10
复制代码
不过是清空寄存器中数据的两个高位并存入r0罢了。不难看出这程序不过是个防止ID超出范围的辅助程序。

那么,原程序的意义就清楚了,撇开不重要的就是得到道具名称的地址。

第四部分:强设跳转

这部分比较容易,注意到pop{r1}后bx r1,相当于pop{r15},所以不妨干脆就在这里设跳转

然后程序必须从结尾为0,4,8,C的地方开始。(否则那个word会misaligned,不过个人认为这个问题编译器能解决,只不过地方稍稍浪费)

(从mul r0, r0, r1的地方开始写)

.thumb
ldr rX, label
bx rX

.align 2
label: .word 0xXXXXXXXX
注:此处跳转个人认为最好能push和pop rX,否则可能造成问题,但作者没这么做而是直接用了r2。当我没说,一时脑子没转过来

第五部分:编写程序

极为容易,不多啰嗦了

  1. .text
  2. .align 2
  3. .thumb

  4. main:
  5.         mul r0, r0, r1
  6.         ldr r1, label
  7.         add r0, r0, r1
  8.         ldrb r1, [r0]
  9.         cmp r1, #0xFF
  10.         bne end

  11. readPointer:
  12.         ldr r0, [r0, #0x4]
  13.        
  14. end:
  15.         pop {r1}
  16.         bx r1

  17. .align 2
  18. label: .word 0x83DB028
复制代码


注意新增指针的位置前是FF000000以使其word-aligned

注:这种方法依然有严重缺陷, 那就是道具在背包中无法正常显示!问题应该是出在向内存中存道具名称的过程,具体是什么问题大家可以测试。但是,脚本中bufferitem命令可用。

如有错误,望指正
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 加入口袋中心

本版积分规则

手机版|Archiver|Pokemon Center

GMT+8, 2024-4-26 12:18 , Processed in 0.111894 second(s), 39 queries .

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表