背景
近几天,我成功解包了游戏《ご注文はうさぎですか?? Wonderful Party!》(PSV),在KUN的建议下,我决定记录下这次解包的经历,(顺带本文参考了在遇到自己完全不会的技术栈时应该如何做?的结构编写)
必要性
实际上,我们解包大多数依赖于别人写的工具(当然如果没有的话有可能你得自己写一个,这很麻烦…),但是大部分情况通过网络上的工具就可以搞定,所以如何快速寻找这些工具就显得很重要了
方法论
以《ご注文はうさぎですか?? Wonderful Party!》(PSV)为例,首先我们发现,这是一个单文件,文件名为PCSG00786_FULLGAME_01.00_C9_V2.0.vpk
,这是一个未知扩展名的文件,所以我们首先应当用16进制编辑器查看
对于这种情况我们应该先确认文件头(此处为50 4B 03 04
),然后用Google查找这个文件头,看看这个格式是什么格式 (其实有个更取巧的办法,就是访问List of file signatures,然后直接Ctrl-F来进行查找)
zip file format and formats based on it, such as EPUB, JAR, ODF, OOXML
显然,我们的文件很有可能是用zip直接压缩而来,尝试使用7-zip打开
成功了,现在我们就完成了第一步
把这些东西全部解压出来观察我们解压后的文件结构
可以发现我们的主要要分析的文件应该是eboot.bin
,xxx_info.psb.m
和xxx_body.bin
,这是因为movie
文件夹内的文件已经是我们希望的.mp4
这种常见格式,我们不需要去动他,而另外两个文件夹内的文件过小(因为Galgame存在图片和音频等各种媒体资源,所以一般情况下存放资源文件的档案不可能很小),我们应该避免先分析这些文件。
再根据文件大小 (image_body.bin
占 636MB
而 image_info.psb.m
仅仅只有 120KB
)我们可以推断出 xxx_body.bin
为资源文件的主体部分,xxx_info.psb.m
应该为主体部分的配置文件或者索引之类的东西。
看到 .bin
这种东西,我们先用GARbro
这种通用工具尝试(实际上GARbro
无法解包),如果不行再尝试我们一开始说过的查找文件头的办法
可以看到文件头为6D 64 66 00
,查找可知
这是一个M2 Archive File
,知道了这些必要信息后,我们可以Google搜索关键词来查找工具,注意,第一次搜索关键词越多越好,找不到再删除一些不确定的关键词来搜索
此处我们使用*_body.bin mdf m2 archive
来搜索
可以看到,第二个搜索结果中与我们的关键词十分匹配,点开查看可以知道
The engine the Switch version runs on is “Kaleido ADV Workshop” by M2. There are tools to extract the *_body.bin and *_info.psb.m files, but you need an encryption key from the executable.
也就是说,这确实是一种叫做M2 Engine
的引擎,解包他确实有特定的工具,但是我们需要知道这个密钥(贴子中没有指明具体的工具,所以我们重新查找m2 engine .bin 解包
,这次因为我们已经知道了引擎名称,所以直接搜索)
出现了一个GitHub
链接,点开查看这个issue,发现这个issue主要是在讨论解包file_info.psb.m
遇到的问题,顺带我们得知这个项目可以解包我们的M2 Archive File
(这是一个叫做FreeMote的项目)。
既然找到工具了,那么这个时候我们应该返回项目主页查看具体的Readme.md也就是项目的介绍,通常此处会写明怎么使用这个项目(如果没有就翻翻Wiki之类的东西,再没有就去issue区慢慢研究怎么用…都没有的话,就只能请你自主阅读项目源码了),
FreeMote is a set of tool/libs for
M2 Packaged Struct Binary
file format. The file header usually starts withPSB
/PSZ
/mdf
, and the file extensions usually are.psb|.psz|.mdf|.pimg|.scn|.mmo|.emtbytes|.mtn|.dpak|.psb.m
.
显然,这个项目就是我们要找的工具,接着往下翻Readme可以看到
Read wiki for detailed usages.
接着查阅wiki可以得知
我们应该使用以下命令来解包我们的文件
|
|
那么我们的问题就变成了如何找到这个key
查阅wiki的PSB-Shells,-Types,-Platforms
可以得知
Key: usually hex string (length = 13 for most cases, can be different for M2 games, such as 9, and there could be any string rather than just hex), e.g. 523aad2de7132, 38757621acf82, ae3bb93923bf8, Rj9Pegoh4 Seed: key + file name, e.g. 523aad2de7132font_info.psb.m, 38757621acf82voice_info.psb.m
但是我们并没有找到查找key
的办法,这种情况我们应该查找issue,看看有没有人问过类似的问题
在issue #93下我们得知
你要去二进制文件(即包含程序逻辑的文件,比如PC游戏就是dll或者exe)里找key,解密的逻辑显然位于这种文件中。
也就是说,我们应该去eboot.bin
下找(因为一番搜索得知eboot.bin
是psv下的二进制文件)
虽然我们知道key
的结构,可以暴力枚举出所有可能的key
(即eboot.bin
下所有长度为13的字符串)来进行尝试,但这也太麻烦了,所以我们继续查找相关issue
虽然在issue #95中我们已经得知了key
的值为a23e898ef1032
,但是我们想知道是找到key
的方法
继续翻阅相关issue,在issue #30可以得知
密匙藏在同目录的eboot.bin的script/.script_info.psb.m前面,用十六进制软件直接搜索就行了
我们直接尝试搜索
果然找到了密钥,证实了我们key
的值确实为a23e898ef1032
。
尝试运行
|
|
解包成功。
总结
多问,多思考
顺带附带一个立绘合成的DLC
DLC
合成立绘的关键是正确解读配置文件,找到正确的拼接方法(大多为查找(x,y)坐标然后直接覆盖即可)
此处以我们刚刚解包好的《ご注文はうさぎですか?? Wonderful Party!》(PSV)为例
显然,配置文件为.json
,我们随便提取一个立绘组来进行研究
此处以tino_1cc1bc3c49e93177acc67700604fda8d
为例
tino_1cc1bc3c49e93177acc67700604fda8d
的配置文件有两个,一个为tino_1c876bf3986382099796dd6ea88266cc.psb.m.json
另一个为tino_1c876bf3986382099796dd6ea88266cc.psb.m.resx.json
tino_1c876bf3986382099796dd6ea88266cc.psb.m.json
:
|
|
tino_1c876bf3986382099796dd6ea88266cc.psb.m.resx.json
:
|
|
通过观察可以知道我们应该具体研究tino_1c876bf3986382099796dd6ea88266cc.psb.m.json
。因为tino_1c876bf3986382099796dd6ea88266cc.psb.m.resx.json
显然没有我们需要的数据。
接着我们看看图片
观察可知,所有的差分嵌在一张图片上,那么我们就需要把这些差分裁剪下来,然后再把基底裁剪出来进行覆盖
假如我们知道我们需要裁剪图片的左上角的坐标(x,y),以及他的长宽,我们就可以把这张图片裁剪出来
也就是说我们需要构造函数 cutimg(cv::Mat img, int x, int y, int w, int h) -> cv::Mat
然后通过读取配置文件我们可以很容易的获得这些参数,从而裁剪出所有差分和基底
接着我们只需要把差分覆盖在基底上,把文件输出即可,这个过程我们只需要知道这两张图片的相对坐标即可
也就是说我们还需要构造这么一个函数 coverimg(cv::Mat baseimg, cv::Mat faceimg, int x, int y) -> cv::Mat
这两个参数也可以通过读取配置文件然后进行一些简单的运算得出(通常为二者坐标之差取绝对值)
最后附上我的屎山()
|
|