这篇是网络上找到的QuickBMS实战例子。9 |$ R+ @. u. I1 K( p6 Z
. v$ h: x( Q7 }0 z. ]- U" |6 q: [! t- [! I" A4 l
这几天的发现太惊人了。。。XeNTax才是mghack的最终目标。。一个坚持了20年的组织。
; U U x5 T& F5 g: m- M+ g& v不多说了。。以AR为例子,讲解一下这个强大的通用解包器吧。。 % K: r5 G& r1 l6 `, Y5 i! z
$ y2 {3 ]& }! o4 _
准备工具: 4 ~, {: H, Q' c& O1 Q' G- E, ?
1.UE(或者其他hex编辑器)
' c H/ G/ c& _5 G3 n) b2.QuickBms(这才是主角)
" v* y1 w0 L8 q9 x* i" @3.AstroRanger这个游戏的hsp资源文件(我们这里以附件中的BoneObject.hsp为例) ! `' r0 i, b+ `( t
# W9 J) ] r( T5 m教程开始: # v6 F# H1 A6 j7 T
1.首先在c:盘创建一个TEST目录,把QuickBMS和BoneObject.hsp放进游戏目录,准备研究解包。 ( P# H! @+ c' C
2.创建一个新文本文档,命名为Astro_hspfile.bms,保存到同样目录下。
! _! [- G; M1 p5 _; m0 C7 o: |0 {
& h( K2 C$ Q" a: G: E2 A3.用十六进制编辑器打开BoneObject.hsp,我们将对这个文件进行分析。 ! o2 I, o$ c% L& a. U. p- m; e, \
5 M, Z/ N" [# j6 j
2 d6 z6 D% q& K, A5 Q H
我们在编辑器的右边看到一些类似文件名的文本。这说明AR对文件名并没有进行加密。 - H! G: j7 J* r. m# H' L4 f+ V6 q
好了,别急着高兴,冷静分析出这个文件的打包方式才是我们的主题。 + n& Y, R# P- D
首先看到前4个字节20 50 53 48 或者 “ PSH”,倒转过来就是HSP加一个空格,
' \; D) h" f: e1 p3 I6 U一般windows的文件都会在文件前N个字节做上“ID记号”,这个“ PSH”就是hsp文件的"ID记号". : T+ H. Q( E+ h" W
用记事本打开Astro_hspfile.bms,我们写上脚本的第一行代码^_^. 8 ^: _0 p/ b" X# l& M8 u
: b8 g( l; n# V% \, G
引用
5 u8 W9 Y# o8 ^; d4 oidstring " PSH"
3 y( y8 z( l% C! g9 n% Z4 M4 X; y; x: _3 R4 P- d
这行代码的意思是“如果访问的文件的最开始不是' PSH'的话,那么就不会尝试去访问它了”
' N' y+ j/ Q ?& Y7 j3 {7 m5 H( k; L+ O* W" r5 b2 h2 p h7 ?3 r
好了,接下来我们找一些自己能看懂的东西,例如那些像是文件名的地方。 : B* a$ Q. T/ D
类似Datas\Texture\BoneObject\npc_nagoya_octopus01_body.dds这样的文件名一共有4个。 5 ?9 Z3 u+ I( D! e/ t/ K- H- x1 _
( C; c5 B7 B& s' n% T
喂,别老盯着那些文件名看了。就算一直看着他们,他们也不会自己蹦出来的。
4 Q) ~7 }: {, _+ @6 H% s8 @我们回到文件头那里继续,之后的4个字节01 00 00 00,经过倒转字节后就是00 00 00 01,也就是1。
' y- L: J& p* s) v$ z到这里我们好像没有什么和1有关的信息,暂时把它定义为“未知字节(unknow)”吧。 9 L- Y$ \2 O) b. c6 D W+ D
于是我们应该在bms文件里写上这么一句代码: 8 t; a( e0 O) D* c& m
$ U; s) k T" i" S: e
引用 ) |2 Z1 ?8 y2 ]
get UNK1 long
5 ~- R! P% q; x% b, t# V$ d
: S' ]8 X. F' ^ B8 d3 U这句的意思,就是从文件中获取4字节保存到变量“UNK1”中。 $ f! P2 m0 ?3 F! z
9 R4 |1 ^9 i, T. k
继续。。后4个字节是04 00 00 00,倒转后是00 00 00 04也就是4。
" i2 D/ e# b6 y* q/ O很眼熟吧,没错,刚才我们看到4个文件名,那么基本可以确定这个4就是“文件数量”了。
2 N0 s" Q8 P, `. }% o- x所以我们得把这个好消息同样告诉"BMS". 0 L3 s) W. f: h" m% f# T! O) v
" ~. ^! w. A5 l. A e y. v
引用 7 ~7 c! l/ [) K
get FILES long
8 a+ O( A+ ^5 c6 N e0 }8 p5 ?$ K
0 y, {( |" I6 N1 r. W! f$ J+ y4 i/ }4 R6 o9 q( m. z! Q
之后是4个00 00 00 00,这里得到的值是0, * r+ ^- T1 I9 O# _0 W ^
我们也不知道是做什么的,暂时设为NULL(空)吧 9 J$ _4 f2 x& o9 J8 i
7 e4 y# U7 g( s8 |引用 . S1 {$ N0 J, W' y; ^# U) {
get NULL1 long
7 q( T2 U. t5 j# `+ ]( G" ~" f7 U4 C& a& P
# b6 A/ r/ o, u/ z$ i- A
看到这里,接下来总算可以看文件名了。 , L) o% E/ L* T- c2 f
经过对比,每个文件名的文本加上其后的00一共是0x80也就是128字节.
$ F+ |$ B9 r; L$ U所以我会写上这样一行代码: 2 I+ [# v! e+ b+ g5 C3 ~
4 O ]$ B |# V: l/ i引用 2 ~% `" j3 ~% h a9 `
getdstring NAME 0x80 ' [: `" M9 _( \9 l: l- ]
% }5 a3 y5 x0 o5 k3 R* B) j( F意思是获取0x80字节保存到 文本型变量 NAME 中.
7 ~0 c, m9 e, k8 A文本型变量在遇到00的时候会自动判断为文本结尾,所以文件名后的00都会在保存时候被自动删除^_^
p2 ?( \6 I8 r- u) c' W; b) O; C! c' [3 K5 T
奇怪,在第一个文件名和第二个文件名之间还有3个LONG长度的字节, ! b+ a3 h0 x. d! C, [2 x$ r
以之前解PAK的经验来看,这里一般都是文件开始位置、文件长度、文件加密key之类的东西, 1 H, `1 ]8 L9 b3 D
但是我们现在还不清楚具体哪个是哪个,就暂时定义为“未知数据”吧。
( |) |1 [: r+ f7 x6 {+ d, N; {
5 d6 r5 _3 x, `+ g9 j7 b5 x) I9 E引用 6 _6 t, R8 W+ D0 ?9 Z7 S
get UNK2 long
4 z4 Q7 |2 f+ ~9 D5 W1 sget UNK3 long ) J5 d: p. `! {
get UNK4 long 8 l# q/ Z$ b7 w
# `* k5 k2 t$ |! r& g4 w1 u
- l- U5 f `0 U% T) t到此为止我们已经初步了解了文件列表部分的循环结构了
0 `# s4 L1 |2 E6 R* v/ X1 h$ B我们目前手头写的脚本代码如下:
+ Z- m( Q- @! D4 n: X& _) A9 ^/ c3 G9 u& h; i
引用
1 a4 A$ d i+ o3 \! w9 L7 p X# u+ eidstring " PSH"
" n, a$ g' V, X4 Y# o2 {0 ]get UNK1 long
3 ?( v7 u. O( L/ z1 J: rget FILES long
' A- @; w, ]/ E* s6 I/ [# Aget NULL1 long $ o0 ]. o0 ?1 ]8 ^: J0 p
getdstring NAME 0x80 6 t+ L/ M# B' g
get UNK2 long ; M9 ?/ F) c+ F" p5 C4 P- i: ^, _
get UNK3 long
6 u' G1 x) L( k: U# j4 E! Hget UNK4 long
4 L$ ^" s0 k* H) w. P( u0 c( c ?, I
) _: |/ k+ N/ g B: P光是上面的代码仅仅也就只能取到第一个文件名而已。
, [8 P q1 e J; }% `+ j8 h我们需要给他们加上一个循环脚本,让他们能读到所有文件名,代码如下: 6 _' @8 q! ?! C2 }7 w" U& Z
0 E9 A3 i. u; @% d! F
引用
4 [6 ]4 [" N8 R; a- U, \/ y9 }$ Didstring " PSH" 5 y) Y5 r: q: U* C7 B
get UNK1 long
; J* V' q( ^! H! W$ M- Gget FILES long - `/ W$ ?2 K# F6 W% i+ N L
get NULL1 long * @$ r! L& Q' ?/ ^
for i = 0 < FILES 8 Z6 R( o" ?) N) L M
getdstring NAME 0x80 % [2 e R7 p3 u, m& P' L3 r
get UNK2 long
; o7 [" _3 ?+ k' t- `3 C9 y+ }3 J" Zget UNK3 long 7 u5 b4 H8 W4 b: _. H; i m
get UNK4 long ) U' Q* u8 k V. g' k
next i
, R. A. y0 F2 T% V) j! {: F
) I) d; g& y! d# x# h6 s% \, `4 i; _6 H' D6 H8 y
即使加了循环,我们还是没有能保存出文件,因为还没有加入log保存命令。 8 y9 R2 Z! p- w8 u* C) i: @+ V
hoho,天亮了,暂时分析到这里。 # u8 ~& x1 F1 V0 Z
最终代码如下。已经可以解包所有hsp文件喽: / x/ S' w/ _+ y! ~
1 ]- i3 \6 z8 r A9 A5 b* j引用 " G; Z: c) b# r1 X4 _" B) i) o
idstring " PSH" . }* o, C$ Q1 F# t6 D% D' h- J% P) _
get UNK1 long / C9 ?- e& n; B) B q+ j! T' ^+ q
get FILES long
0 B: c# g! l3 d0 x/ uget NULL1 long
9 I9 z7 f$ {( V3 p6 v& c7 v# G- Tfor i = 0 < FILES % q! D# o) G) ]
getdstring NAME 0x80 * Y, M# L8 B/ ]2 Q: T: `' c2 ^0 U
get ZSIZE long
0 P. ?/ }$ O7 z+ X1 W1 ?# H# Eget SIZE long
8 u% J% U/ G8 tget OFFSET long
1 J0 }9 F. R, [* S8 ?clog NAME OFFSET ZSIZE SIZE
( N. x0 A, p& @next i
* u; }, D- Z! ~5 O
# ~) P3 G# \' j8 p }4 R把上面的脚本保存后 z, L. N, U2 z- ?5 j
新建一个txt内容如下:
( J0 \ h. P) }0 p2 ^quickbms astro_hspfile.bms BoneObject.hsp .
. v' T! m- s+ x. \* Y7 m7 |1 }注意保存最后的"."然后把内容保存为hsp_extractor.bat - G, p4 |8 X1 Q' A) ]
之后运行hsp_extractor.bat就能看到解包后的结果啦。。 $ L4 o' O }1 n5 I8 ^& z
睡觉睡觉。。。 |