【转】GBA_0688_炸弹人破解过程

来源:互联网 发布:瑞丽宏泰网络公司地址 编辑:程序博客网 时间:2024/06/05 17:21
注:这个是从flyeyes大的博客里转过来的,连程序如何写字模的过程都分析了,非常值得学习。

========
编码扩容
========
--------
跟踪过程
--------
因为已知字库首地址0x1BCD90,设断点r0=081BCD90,r1=081BCD90…………r6=081BCD90。
开始游戏,在08015294处中断,发现是r1读取了字库首地址。
向下读,
08015296 add r6,r0,r1,说明r0中是对应字符的偏移
向前看,有
08015284 lsl r0,r0,18h和
08015292 lsr r0,r0,15h,即去掉r0的高24位,并乘以8。考虑到8x8 1bpp的一个字模占用8字节,因此可以确定r0中原先保存的是字符编码。
然后要确定r0中的值是怎么来的,这句话中的第四个字是ん,重新开始游戏,设中断r1=081BCD90。
中断3次后,设中断r0=38(ん的编码),会有多次中断,逐个排除。正确的前面应该有ldrb rX,[..],并且可以查看下[..]对应处的内存,看是否为文本,多次中断后(这一块要靠经验)确定为08016058 mov r0,r1那处。向上看,找到
08016050 ldrb r1,[r0,0h]
这句,因为r0的值已经改变,在此句设中断,删除原有中断,运行中断时r0=081BD824,察看后发现是文本,从此句向下读即可知道编码的调用过程,编码扩容可能。
----------
要改的语句
----------
08016050 ldrb r1,[r0,0h] //改为ldrh r1,[r0,0h]
     str r1,[r2,2Ch] //r2=03007470,储存了字符编码
     add r0,1h //改为add r0,2h
     str r0,[r2,24h]
08016058 mov r0,r1
     sub r0,E0h
     cmp r0,1Fh
0801605E bhi 0801612Ch //由这一段可知,读取的编码小于E0h或大于FFh时就跳转到0801612Ch。另外,记一下bhi是进行无符号比较,高于则跳转。
0801612E ……
………………
08016138 ldr r1,[r4,2Ch] //r4=03007470,即r1读取了字符编码
     lsl r1,r1,18h //改为0409 lsl r1,r1,10h
     lsr r1,r1,18h //改为0C09 lsr r1,r1,10h
………………
08015306 mov r0,r1
………………
0801530C lsl r0,r0,18h //改为0400 lsl r0,r0,10h
     lsr r0,r0,18h //改为0C00 lsr r0,r0,10h
………………
08015284 lsl r0,r0,18h //改为0400 lsl r0,r0,10h
………………
08015292 lsr r0,r0,15h //这句和上面那句实现了r0*8,改为0B40 lsr r0,r0,09h,实现r0*16*16*(4/8),即使用16x16的4bpp字模
以上
==========
写字模程序
==========
----
内容
----
见图片"0688-写字模.GIF"
----
修改
----
08015298 mov r2,r6
0801529A b 080152F0h
=========
写map程序
=========
----
内容
----
见图片"0688-写map1&2&3.GIF"
----
修改
----
见图片"0688-写map1&2&3.GIF"和"0688-写map2&3-修改.GIF"

============
显示程序修改(基本没用了,还可以用于移动字符所在位置)
============
目的是让两行文本挨着,以便用多tile显示大字。
寻找map,第一个文字所在tile的map address为0600F408,用内存察看打开那里,大部分填充的是0xF381,对应显存中那个空的tile,第一个字对应的是0xF386。
在下一个字对应的map处写中断([0600F40A]!),看map的值是如何给的。
中断于08015354 8010 strh r0,[r2,0h],前面有
08015340 ldr r3,[08015368] //r3=03007470h
     ldr r2,[r3,40h]
     ldr r0,[r3,74h]
     lsl r2,r2,01h
     add r2,r2,r0
     ldr r0,[r3,78h]
0801534C ldrh r1,[r0,10h]
     lsl r1,r1,Ch
     ldr r0,[r3,44h]
     orr r0,r1
08015354 strh r0,[r2,0h]
这时,r1=F000h,r3=03007470h,r2=0600F40A,要考虑r2的值是怎么变的,发现与030074B0处的值有关,在那里设中断,删除其他中断。中断于0801614C
08016148 ldr r0,[r4,40h]
     add r0,1h
0801614C str r0,[r4,40]
多次中断,看换行时那次,为
08015690 ldr r0,[080156A0] //r0=03007470h
     ldr r1,[r0,30h]
     add r1,40h //改成add r1,20h就行了
     str r1,[r0,30h]
08015698 str r1,[r0,40h]
因此,030074A0处是基础值,重新开始游戏,中断处代码
08015622 ldrh r0,[r5,6h] //r5=081E196C
     str r0,[r4,40h]
08015626 str r0,[r4,30h]
可知,0x1E1972处保存了其初始值为了把文本向上提一行,把那里的值剪掉20h即可。