这篇是网络上找到的QuickBMS实战例子。
' t8 v5 x g: V6 G* p
: H% v ]( l8 w) S$ P6 N
7 Z3 u2 o' U8 T0 w这几天的发现太惊人了。。。XeNTax才是mghack的最终目标。。一个坚持了20年的组织。
* R5 u+ ^' T0 D7 f不多说了。。以AR为例子,讲解一下这个强大的通用解包器吧。。
# g/ F/ v1 i7 u% o
& n+ C$ i: f( m7 J; t- x+ j准备工具:
" X9 }2 B1 r ]1 E! k. j4 a0 W3 I: K1.UE(或者其他hex编辑器)
8 _3 V" X& m5 F. q. M) m3 b7 i2.QuickBms(这才是主角) ! }: @$ X$ Y: ^" Q: }
3.AstroRanger这个游戏的hsp资源文件(我们这里以附件中的BoneObject.hsp为例)
" z; k/ Q; w/ \
$ `8 E+ y$ T$ [5 {教程开始: 9 @, S! P G6 R; w. B
1.首先在c:盘创建一个TEST目录,把QuickBMS和BoneObject.hsp放进游戏目录,准备研究解包。
2 p9 v& P) L2 M* O/ C6 g( L9 P2.创建一个新文本文档,命名为Astro_hspfile.bms,保存到同样目录下。 / Z# Z2 v% A7 C; J
b" ~/ u/ x: X' t& E$ f, g/ ~, N0 R* o' T7 y! e/ f! {
3.用十六进制编辑器打开BoneObject.hsp,我们将对这个文件进行分析。 # p' C9 V7 Q' b7 b$ |( ^4 V: M" Y9 i
$ K2 u( j3 C, {1 M# v
# B$ I& J6 e: ]7 a, ^我们在编辑器的右边看到一些类似文件名的文本。这说明AR对文件名并没有进行加密。
6 h7 W7 V' H. e4 y9 i* [) l好了,别急着高兴,冷静分析出这个文件的打包方式才是我们的主题。 " F' P# j" z2 p$ O$ H" X6 @
首先看到前4个字节20 50 53 48 或者 “ PSH”,倒转过来就是HSP加一个空格,
; `. o3 w9 s1 ~+ z' T一般windows的文件都会在文件前N个字节做上“ID记号”,这个“ PSH”就是hsp文件的"ID记号". 1 N2 P4 _3 J/ D" ^) K2 e$ A
用记事本打开Astro_hspfile.bms,我们写上脚本的第一行代码^_^.
' d* N/ m- J$ m6 H" l, H- ^
0 w5 B; z7 M5 I引用 + o! [0 y' U0 f4 ?/ R# Y' G/ ^
idstring " PSH" 0 i9 K* D: k/ Z
8 ~9 _) Q! |$ H2 C
这行代码的意思是“如果访问的文件的最开始不是' PSH'的话,那么就不会尝试去访问它了” 8 y" a6 C) V/ y4 u! v3 ^" g
& K; f) A+ B' _$ S
好了,接下来我们找一些自己能看懂的东西,例如那些像是文件名的地方。
( R1 _& _) W e类似Datas\Texture\BoneObject\npc_nagoya_octopus01_body.dds这样的文件名一共有4个。 ) A; m. w4 k: L5 K! ^" ~
, @2 t) M# a0 q* n8 F2 m5 p喂,别老盯着那些文件名看了。就算一直看着他们,他们也不会自己蹦出来的。
7 c/ r. q6 y* S5 b2 M我们回到文件头那里继续,之后的4个字节01 00 00 00,经过倒转字节后就是00 00 00 01,也就是1。 @5 r6 i) s2 O% a
到这里我们好像没有什么和1有关的信息,暂时把它定义为“未知字节(unknow)”吧。
y4 B% D, }4 o3 n1 X于是我们应该在bms文件里写上这么一句代码:
# ^5 \) v+ s, D2 t, o5 c+ G) |
$ r) r5 {, {4 x3 G: Q" g M引用
# U% A5 q, V1 k+ Tget UNK1 long / ~9 Z y$ ]; u6 s) X
! G$ L) z$ q. g. |* n2 b2 b4 _这句的意思,就是从文件中获取4字节保存到变量“UNK1”中。
" ], y; o T4 e! V' H' Z
* T8 ?8 w9 ?" y, V: k继续。。后4个字节是04 00 00 00,倒转后是00 00 00 04也就是4。 8 }1 j9 n( C; g/ s" p# c+ q, k
很眼熟吧,没错,刚才我们看到4个文件名,那么基本可以确定这个4就是“文件数量”了。 / D# B1 W2 Q W5 z) z3 q1 \
所以我们得把这个好消息同样告诉"BMS".
, B2 \7 n3 o% [6 g8 W- g3 K8 k
$ Q0 r) D4 M% F% q C引用 . j* M- u* Y) W7 J
get FILES long
' B. o. B1 \8 p# g0 d& r. R; [. H2 n; d* u0 m- N9 R. V9 n- q/ w4 A
: h: H6 ?9 y7 M
之后是4个00 00 00 00,这里得到的值是0,
- L! ]/ x2 F( V我们也不知道是做什么的,暂时设为NULL(空)吧 ( L- R' f* t! A# @& g
7 ~. t4 ^+ u- O' G$ v- m4 R" m
引用
$ G7 _! g/ D5 ^. yget NULL1 long
9 \! P9 F# I1 Q6 Q
+ j; `/ ~# K3 f7 y$ \
5 O: l. S! |; Y. d0 O看到这里,接下来总算可以看文件名了。
7 G$ E( E- M1 F# `% {经过对比,每个文件名的文本加上其后的00一共是0x80也就是128字节. ! X8 K$ t+ Y4 c B% t8 I
所以我会写上这样一行代码: & t4 U+ S7 w& c; b5 A; Z
# ]8 I. U+ U8 f8 h) V5 \ C% i引用
) R7 @* w5 S4 j1 s xgetdstring NAME 0x80 + { O, w. T2 f* [' v* g% |* i
6 l5 @8 X, k9 o3 A; |5 c意思是获取0x80字节保存到 文本型变量 NAME 中. 7 t. O6 [, [6 ^# o1 x$ y/ q
文本型变量在遇到00的时候会自动判断为文本结尾,所以文件名后的00都会在保存时候被自动删除^_^
/ i- `* s/ A& N6 T8 Q: P7 j+ d9 [/ W) c) |" q1 c" g5 h* F
奇怪,在第一个文件名和第二个文件名之间还有3个LONG长度的字节, 1 u/ |- ~+ e# _9 S& T* X) u
以之前解PAK的经验来看,这里一般都是文件开始位置、文件长度、文件加密key之类的东西, ; x# ?( A9 G: b5 w
但是我们现在还不清楚具体哪个是哪个,就暂时定义为“未知数据”吧。
3 j. D' j8 ]1 w: }: L% z& H% U2 _
引用
: p# E9 a: h, ~- eget UNK2 long
; [8 Q: ~: e, y9 g1 m, U- o3 cget UNK3 long
( p3 ^" u3 o+ dget UNK4 long
8 D+ A% C# A/ A- t& ^% o2 Z" T: Q3 _' ^6 s% a: {. h
6 h9 ^; G2 }' T$ n! z" e到此为止我们已经初步了解了文件列表部分的循环结构了
7 o! i6 _% P% s我们目前手头写的脚本代码如下: * _/ u5 E) ?. p: s9 l( `5 D
9 s k0 C5 W" h% I5 d& I6 N, J7 z引用
1 B+ F4 [4 p5 k8 i! P9 F1 Aidstring " PSH"
8 \1 v# W- n6 yget UNK1 long 1 ^0 m v1 f5 v5 ?7 P( l
get FILES long 8 O9 K/ s; U) ?+ y! U9 y$ p7 z
get NULL1 long
$ C" z- h* r4 n _& ?getdstring NAME 0x80
- S' e5 b: `: [7 |1 C4 a* X9 rget UNK2 long 1 w0 c6 p6 z5 T& `
get UNK3 long 1 b7 d, _8 k3 O7 u5 R
get UNK4 long
q0 J% B* M$ H. ], q/ |0 C4 j4 n7 f" E/ B/ H& i) K$ O) N
& F2 i' y W" f# @+ q
光是上面的代码仅仅也就只能取到第一个文件名而已。
$ L) _# R. U. g7 Y我们需要给他们加上一个循环脚本,让他们能读到所有文件名,代码如下: - x* \( a C) o8 b2 F- F' [& O
1 a W# S" A2 s0 L+ z \引用
$ i1 w& m6 w' f$ Oidstring " PSH"
; R G K' `- I: `* P+ _* Wget UNK1 long
2 x' t! ]0 y5 cget FILES long
- g; T8 ^( ]" E( Wget NULL1 long
/ C* O" L5 N9 t5 |2 ifor i = 0 < FILES
- S& f- B! H2 jgetdstring NAME 0x80 7 F! j, W) D0 A
get UNK2 long 1 a0 E$ q# b* S4 }+ b. O, F
get UNK3 long
3 P4 W( o1 r% W: }8 r8 l+ |- Yget UNK4 long
6 q5 j" \( j* @, f) ?. Y% {next i , _$ q# ^6 M! U! y; |
5 T* C, P# T. S1 n* S
' T; e! A( N* {8 Q
即使加了循环,我们还是没有能保存出文件,因为还没有加入log保存命令。 7 c6 U' Q$ u5 r B
hoho,天亮了,暂时分析到这里。
% q( i" @) F( M. s% R最终代码如下。已经可以解包所有hsp文件喽:
; B, H0 x+ x# G3 }! u$ n
2 j6 ^" T9 U, D. W1 z$ o, | n+ I引用
* y1 ^6 M+ X' |idstring " PSH"
: h3 ~: s; W( o2 e/ n n4 Aget UNK1 long ) W& L( Q) Z: @) S3 t, q5 u4 T
get FILES long " L" ~& F0 M, [4 p$ l( x
get NULL1 long
: A ?' V: X9 M( h% `5 J3 a1 g& g6 H: ufor i = 0 < FILES ; Q1 ?$ W' y2 h- h2 a; | t
getdstring NAME 0x80
3 f4 a/ E5 r8 |; ?8 C* Cget ZSIZE long
; Y2 k j5 f/ M2 |get SIZE long
* r. i, e: I) L9 L4 Gget OFFSET long
* I" Y7 g V+ l! j; Uclog NAME OFFSET ZSIZE SIZE ) ^7 ^& P- s( `. ~& D2 Q6 m
next i
- [2 |4 w* a% N2 K; R6 O: {% B" W R( K1 v; Y
把上面的脚本保存后
% z$ {& ?$ D0 k3 R! j新建一个txt内容如下:
" N) E2 }3 v1 P M& wquickbms astro_hspfile.bms BoneObject.hsp . , C, \# s9 _& q/ g
注意保存最后的"."然后把内容保存为hsp_extractor.bat 5 g" {% h; V' I. }; m$ J
之后运行hsp_extractor.bat就能看到解包后的结果啦。。 / o: x( Y7 H& T- Q# C8 w X
睡觉睡觉。。。 |