sfczz 发表于 2019-5-11 09:47

经典游戏《XX劫——XXXXX传》图像素材逆向分析

本帖最后由 云在天 于 2019-6-7 13:19 编辑

0.乱七八糟的碎碎念
接触神魔素材逆向其实源于一个群中的闲聊,一个兄弟的一番话让我想尝试重制神魔至尊传并添加一些新元素。但我深知这玩意吧,是个深坑,所以想找人合作。机缘巧合,找到了另外一个做神魔MOD的兄弟。找到他的时候,已经做完了一个MOD,身心俱疲。但一直纠结于图像素材无法修改。一番交流之后,我也打算从图像素材分析入手,毕竟将来重制也要跟这些打交道,就当铺路了。然后就上了这个做MOD的贼船。。。{:1_900:}


1.SAF文件结构介绍
由于做MOD的哥们已经靠脑补+人眼分析,大概猜测出来了SAF的文件基本结构,所以我就直接拿他的成果来分析了。


先上一个例子(FACE01.SAF)
00000000h: 53 41 46 05 02 74 00 1E 00 18 00 00 0C 00 74 00
00000010h: 00 00 2A 01 00 00 0A 00 9E 01 00 00 12 02 00 00
00000020h: C4 00 B0 03 00 00 25 A3 01 00 00 00 D5 A6 01 00
00000030h: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00000040h: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00000050h: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00000060h: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
00000070h: 00 00 00 00 A4 00 00 00 BB 00 00 00 D2 00 00 00
00000080h: E9 00 00 00 00 01 00 00 17 01 00 00 21 01 00 00
00000090h: 38 01 00 00 4F 01 00 00 66 01 00 00 7D 01 00 00
000000a0h: 94 01 00 00 FF FF 14 00 00 00 00 00 01 00 07 00
000000b0h: 03 00 01 00 00 00 00 00 00 00 00 FF FF 01 00 00
000000c0h: 00 00 00 01 00 01 00 03 00 01 00 00 00 00 00 00
000000d0h: 00 00 FF FF 01 00 00 00 00 00 01 00 04 00 00 00


PS:字节序:SAF中所涉及的数字,均为小端模式。
从已知的文件结构,可以将SAF分为几部分:
1).文件头
    从头起共12字节,所有SAF文件都是同一个文件头,基本没什么解读意义。
2).块信息区
    从文件第0x0C偏移起,到第一个子块信息区首地址(基本都是0x74)
    基本结构为AA AA BB BB BB BB CC CC CC CC,AA为当前块信息包含的子块信息个数,BB为块信息区起始地址,CC为块信息区长度。
    比如例子中的0x0C偏移起数据0C 00 74 00 00 00 2A 01 00 00,表示这个块有12个子块,块起始于0x74地址,长度为0x012A
    SAF文件中可以有多个块,现已知最少3个,最多5个,每个块都有不同意义。
    最后一个个数为0的块信息,为终止块,后续为全0x00无意义。
    可以看到,例子中一共有3个块
3).子块信息区
    这一部分保存的是各子块数据的起始地址。为全文件的绝对偏移地址。根据块信息的个数,即可得出各子块数据的长度。最后一个子块的长度可以根据下一个块的起始算出来。
4).子块数据区
    保存实际数据。那个好基友主要就是卡在了数据编解码上,无法还原出图片素材,当然也就没法修改并重新编码回去。


首先给出至今为止的结论:
在块信息区的描述里面提到了一个SAF文件可以有多个块,每个块有不同意义,这里列一下:
块1:帧绘制参数,主要用来指定由几张图片来组合成为一帧,包含每张图按哪个坐标起始绘制,每张图透明度如何处理。起始坐标算法有区别,有绝对坐标有相对坐标,没有详细分析。
块2:图片结构:以SAF的最小图像单元30×24为单位,描述一张图片有M*N个图像单元构成,以及各图像单元的索引
块3:图像单元数据。每个图像单元均为30×24,编解码方式后面描述。
块4:音效数据,WAVE格式,用于配合动画来播放。具体WAVE文件头的参数我给忘记了……就只记得好象是22K采样频率
块5:未知。


2.开始分析
因为当前目的是做素材替换,所以最低要求是搞定块2(图片结构)和块3(图像单元数据)的数据编码解码。
当然,在刚开始分析的时候,压根不知道块1和块2是啥,但是看一眼就知道那俩玩意绝对不可能有图像数据,因为太短了。
还是以FACE01.SAF为例,下面就是块2中的一条数据,胡乱猜也知道这么规律的数据不会是图像数据。
000001C5H: 00 05 00 05 00 00 00 01 00 02 00 03 00 03 00 04
000001D5H: 00 05 00 06 00 07 00 03 00 08 00 09 00 0A 00 0B
000001E5H: 00 03 00 0C 00 0D 00 0E 00 0F 00 10 00 11 00 12
000001F5H: 00 13 00 14 00 15


那么精力就放在块3的分析上。
我手上的神魔EXE是加了压缩壳的,只有151K,所以还需要进行脱壳,脱壳后大小大概1.9M,当然实际代码没有这么大,脱壳DUMP出来一些多余数据。(还有个事情需要请教高手,我自己脱壳后,仅能在不重启电脑的情况下使用,重启电脑就不能用了,是哪里没弄对么。。。实际我最后是在贴吧找了另一位高手脱壳后的EXE进行分析的)
先捋一下思路:
因为要分析数据,那么可以采用内存断点的形式进行代码的定位;设置内存断点的前提就是需要知道代码解析时数据放在哪里;那如何知道放在哪里?在WINDOWS平台,除非开发者脑子抽筋直接访问存储器,否则肯定要打开文件,然后读取数据到内存。那么下一步干什么就知道了。


用ollydbg打开EXE,将模块切换到Kernel32,在CreateFileA起始地址下断点。

然后开始跑程序,会发现在断点处停下后,栈视图中有关于函数参数的地址,可以直接在内存视图查看FileName的值。

然后我们就一直不停的跑,等到FileName是一个SAF文件的时候再进行分析。记得每次断点停下以后,看一下FileName参数值。

此时可以看到,Title.saf被传入CreateFileA。手动单步执行,直到退出Kernal32,返回游戏EXE。

然后单步步入,仔细观察。会发现代码一步步走过GetFileType、SetFilePointer、ReadFile等等文件操作类API。熟悉WIN32API的人其实就可以得出结论:直接在ReadFile下断点。(其实刚开始就可以尝试在ReadFile下断点,详细说明下跟踪过程,也许可以让不太熟悉的朋友慢慢进入状态)

这个时候就可以取消掉CreateFileA的断点,直接看ReadFile。(题外话,这里仅限于神魔,别的EXE可能并不是CreateFile之后紧接着ReadFile,所以需要在看到希望分析的文件被打开后,记录下它的Handle,然后在ReadFile断点停下的时候,看传入的Handle是否就是之前记下的)
也许是我的ollydbg有问题,ReadFile并没有做参数解析,但这不是啥大问题,直接根据ReadFile的原型(普及常识,栈顶ESP是子过程结束后PC返回的地址),可以得出ESP+4是Handle,ESP+8是lpBuffer既保存读取数据的内存地址。

有lpBuffer的地址就好办了,单步执行离开ReadFile,从内存视图看一下lpBuffer的地址是不是读出来了Title.saf的数据。没错,读的就是它的内容。

然后找到Title.saf的块3数据中第一个子块起始(根据文件结构部分即可计算出,加上lpBuffer地址就可以到到子块数据起始地址),下内存断点。关掉其余断点,跑程序。

当程序访问到设定内存断点的地址后,将会停下

剩下就是阅读汇编,并整理解码方法了。下面直接给结论:
图像单元固定为30*24像素,每一条是一个图像单元,像素为16位色,单像素占两字节,RGB565格式
图像单元结构为:标志 数据 标志 数据 标志 数据……
标志占一字节,8位
7 6 5 4 3 2 1 0
X Y |N   |


X = 1      进行绘制
      Y = 0 顺序绘制后面的(N + 1)像素
      Y = 1 绘制后面的像素(N + 1)次
X = 0      不进行绘制
      Y = 1 跳过(N + 1)像素不绘制,此时后续没有跟数据


根据上面的分析,即可将每一个图像单元绘制出来。多绘制几个就可以看出来之前提到的块2其实就是之前结构中所说的M*N个图像单元。
解码分析到此结束,因为MOD需要素材替换,所以还需要进行图片的编码,既用PS等工具进行图像编辑后,还能再把图像编码回SAF的格式,让游戏可以处理。
基本上编码就是解码的逆向操作,只有几点需要注意:
1、通过观察多个SAF文件的块2,可以发现有图像单元复用的情况。比如一块纯黑色的图像单元,可能会被用到多个图片中。因为素材编辑后可能无法再次进行图像单元的复用,所以我采用了针对块2也重新处理的方式。这样就比原来多出一些图像单元,这涉及整个SAF文件结构的改动,包括块信息区、子块信息区偏移的重新计算。
2、编码时注意也要将图片分割为30×24的大小,挨个编码,否则游戏会出错。


下面上成果:


最后上我自己做好的工具:


下期预告:如何修复神魔至尊传中未开发完成的法术“返召之咒”:lol

sfczz 发表于 2019-5-11 18:10

pwdobwq 发表于 2019-5-11 16:59
个人神魔至尊传重置那真是无比的深,和汉化最终幻想等不一样的是,修改添加剧情没有深厚的汉堂情节无法驾驭 ...

看到成品图了么,那是已经完成的高难mod,增添跟幽城有关的剧情和关卡,可以试试哟。百度一下就能找到

sfczz 发表于 2019-5-12 18:14

qichen 发表于 2019-5-12 17:54
nice,终于等到你了,哈哈,不知道有没有帧中心点这些信息

感觉没有帧中心点,已经找到各个图像单元的起始绘制坐标,但是有的是绝对坐标有的是相对坐标

青词倾慕 发表于 2019-5-11 10:10

兄弟,玩不玩2002年的天龙八部啊?

今天很高兴 发表于 2019-5-11 11:22

厉害了我的天啊

snccwt 发表于 2019-5-11 11:31

很老的游戏,勉励壮行

sfczz 发表于 2019-5-11 11:39

青词倾慕 发表于 2019-5-11 10:10
兄弟,玩不玩2002年的天龙八部啊?

没玩过啊,咋了??

silverkey 发表于 2019-5-11 11:57

感觉天下霸图2可以出MOD,分析了以后发现他最新版本很多套装,不过都是隐藏的,需要自己改出来

青词倾慕 发表于 2019-5-11 11:59

sfczz 发表于 2019-5-11 11:39
没玩过啊,咋了??

这也是很经典的游戏
玩的话,一起研究修改啊
哈哈

xgameboy 发表于 2019-5-11 12:01

特别佩服你们这些逆向冷门经典老游戏的大牛,现有资料几乎没有,完全凭自己一点一点摸索,需要的毅力精力都是无法估量的,请收下我的敬意!

sfczz 发表于 2019-5-11 12:10

青词倾慕 发表于 2019-5-11 11:59
这也是很经典的游戏
玩的话,一起研究修改啊
哈哈

我都是挤时间,而且很有可能就鸽了,神魔这个全凭热爱才坚持下来{:1_906:}

baolei1988 发表于 2019-5-11 12:48

天地劫我觉得是神一样的游戏
页: [1] 2 3 4
查看完整版本: 经典游戏《XX劫——XXXXX传》图像素材逆向分析