冒险解谜游戏中文网 ChinaAVG

标题: 【汉化资料】浅谈网络游戏《天XXX》的文件加密格式 [打印本页]

作者: shane007    时间: 2008-10-30 20:49
标题: 【汉化资料】浅谈网络游戏《天XXX》的文件加密格式
学习一下人家的破解过程,这个游戏是开源游戏引擎OGRE进行开发的喔。
  S2 s5 `3 }5 V- o& |! t5 G% O3 E" A, {  N7 G' W. x0 [
$ \2 x0 w( Q- C6 w* [$ x

+ A% V4 S& B+ q2 q" m发信站: 饮水思源 (2007年06月22日02:36:37 星期五) ( A; s) O+ ~( Z4 e

9 m: R" b/ P. w; T2 W作者:[email protected]
3 I0 `% f6 M* ~
+ [. _& @% Z' @3 `+ h3 N三月份时玩了某狐公司的网络游戏《天XXX》,感觉还是蛮有意思的,遂研究了一下。 / y% w" F/ T: M6 k# ]' d
这个游戏是利用开源游戏引擎OGRE进行开发的,看了一下目录里面的文件结构,主要的数
$ p- C0 ]7 Z; v1 O/ r据都放在Data目录下面。不过文件基本都是.AXP后缀的,每一个动辄几十兆,料想肯定是 4 J; G& t4 }. d) v
把游戏文件打包到一起并加密过的,GOOGLE未遂。开始用UE打开看了一下这个AXP文件,发
  S% ^3 v3 d4 c: j& @现里面居然大部分都是明文的,开始以为只是把文件罗列在一起,不过仔细看了一下,发
3 X9 {2 E+ z$ ^/ }- Q现每个文件都有一段间隔,前面还有一个数据头,而且文件与名字也无法对应。于是打开
1 r. U5 V0 a7 ^8 vOD手动分析一下,主要过程其实比较简单,CreateFile函数下断,找到文件Buffer位置, * A. w+ L6 G8 \8 {( f6 I8 V' c
再下内存访问断点即可来到关键代码区域。略过具体跟踪细节及文件校验部分不讲,文件 ( C" i8 C0 T! {2 l- H
格式主要分析如下: + D% z& `: w: h* ^3 ]

; F' A% L* N4 e" V, Q. z整个AXP文件可以分成四个部分:1.文件头 2.文件名索引 3.文件索引 4.文件数据 2 a3 N  ^" h- n0 M' {9 U8 A, B: E

5 I) F/ }( ?/ T, S
  a8 M% P0 j! M; w# G$ U1.文件头:
9 t- }/ B& ~7 i  整个文件头固定为0x28字节,其中第20个字节开始的一个整数乘以12代表了第三部分
* K& A8 P) ?1 K2 N6 @, ^+ |' p即文件索引部分的长度(因为每个索引有三个整数构成)
. Q- D5 e  s8 g% \3 B2.文件名索引: 6 s% D' E: ^1 o& Y
  整个文件名索引固定为0x60000字节,其中包含了每个压缩文件对应的文件索引位置
7 W: m5 x) Y( a, O* j& K# w1 ]1 I7 f- [7 }0 H% j, m" ?
3.文件索引:
3 A# R$ _  b3 Z  本部分长度由文件头相关数据决定,其中包含了每个压缩文件在.axp中的实际偏移位   u0 D, ~2 C3 X" Q& t% {2 j
置及文件大小
, _+ T+ V; x' B: e* m+ T& i( @4.文件数据: % t% s" V9 n+ P& @9 j* w
  本部分包含所有压缩文件的具体数据,每个文件之间用若干零填充。 - r# k2 D( H2 |7 R( x
5 u1 s- ~7 v$ @9 s3 ?9 J
首先说说解压总体过程:比如我们要从A.axp中解压出一个叫file.txt的文件,那么先根据 - W$ q' S! S( p0 |  q5 g! X4 C
文件名file.txt到文件名索引中去找到对应的文件索引,然后再根据文件索引找到这个文
- A) s: x1 N7 k: {( {9 s0 d件在axp文件中的位置和大小,最后把其解压出来。 & D3 z( {. h) Z$ |" O% Y7 `
+ j' I$ G0 Z* e+ u
解压具体过程如下: % K- x. `: W5 G/ T/ u8 y- F
  将待解压的文件名转为小写(如果为英文字母),利用GetDisp(char* s,int v)函数 1 F0 O# S" |% z9 f3 |/ ?' }
计算相关数据,其中s代表文件名,v代表计算参数,分别计算GetDisp(fname,1),GetDisp ( F8 ~9 O. J5 K8 I; u9 J6 s, t$ z* a
(fname,2),
: \. ~7 }2 L; X1 N' g+ [0 _GetDisp(fname,3),得到三个值a1,a2,a3。其中a3低位与在文件名索引中的位置有关,a3最 . w& ?$ O" `! C/ ^& |- C
高位及a1,a2用来进行校验,如果三个值不能同时满足要求,则将偏移位置顺移继续验证, ; M' ]! O/ b* J- t: M1 s0 B
具体细节懒得写了。
9 o/ b4 l9 R1 ?以下为GetDisp函数具体内容,我直接将跟踪代码里面的汇编改造了一下拿出来用,其中s
: v$ K9 R" ^# q' O: N( Q. mucks为一个随机数数组,这里不列出来了。 7 G* `6 W: p( v8 m
unsigned int TLBBUnpacker::GetDisp(char* s,int v)
: k! j# H3 [1 l% X. q% Q{
% }7 ^- N$ ]( C# M( j* G__asm
. L' S  Q4 u* |1 E0 w{
: y, L/ S9 W' [8 _9 R% spush esi + ]6 o0 B6 U# g0 l. }1 r9 W
mov esi,s
2 o$ P, Z4 r, [0 S0 K' Jmov cl,byte ptr ds:[esi] ( Q. }' @, g) G- u: ?
test cl,cl
2 Q. K4 P, n, D* R) Y9 L- T( zmov eax,0x7FED7FED
- i2 s7 K5 v" C7 h5 X4 @- xmov edx,0xEEEEEEEE # e) Q8 K+ O6 @  @# Z& W* ~
je end
$ a9 l: x- S. g0 a5 k+ Rpush ebx
. H8 h; t" C* B1 V* M; r7 Apush ebp
! B' Y4 E3 ?5 Z( _' B' \push edi
: p, N# U! X. A5 v+ umov edi,v
1 R9 n. \, S, wshl edi,0x8
  A& \) Z' L- n5 A( Giter: . n- b: E7 X( G* k
add eax,edx 0 |0 i$ q" X9 C4 o
imul edx,edx,0x21
; ]( x# ~2 t# L. [, y) \8 kmovsx ecx,cl . M8 o" _( O8 U* n. m# Q
lea ebx,dword ptr ds:[edi+ecx] , R$ v3 F! P3 a' z1 k9 [( j
mov ebp,dword ptr ds:[ebx*4+sucks] ! l) }: ]+ E: A$ ~/ v/ M4 q: T9 O
inc esi
& n$ X6 o- J  D$ S' nadd edx,ecx 0 e4 n& P5 A+ E! V# ^' N# l$ V
mov cl,byte ptr ds:[esi] ! C' P3 ^) S1 F- L7 w4 K, {) ^
xor eax,ebp
, P: G: F. n  T5 a. {( y' c# Htest cl,cl * ]: L; v0 [+ ^2 A/ L- G- y- u
lea edx,dword ptr ds:[edx+eax+3] 8 {+ g7 V7 {, G8 ]- ]' v- f1 d. Y
jnz iter
; |( k3 I1 w  A5 ^8 {7 W8 R, t# bpop edi # T4 [+ T4 f! m; t
pop ebp
: H+ g& p2 X. p: `pop ebx 2 F  ?( H/ K* K6 q! ^! ^- O1 n
end:
/ c! Z2 h/ p; B! b8 R( }3 C/ S' epop esi 0 K' a- I0 T7 c% U; Z$ L9 }
} : L1 y$ R6 x2 ?7 n+ i
} 6 Z8 n0 K' u7 R
这个为解压单个文件的函数GenerateFile,用到了QT作GUI,大家就当伪代码看吧。
* p/ C- X8 W* t1 qbool TLBBUnpacker::GenerateFile(QString name)
" e0 N& n$ i1 `{ 5 X. d  I% b4 ^! U  q
name=name.toLower();
% r3 P1 F4 V( w" l; f' {unsigned int a=GetDisp(name.toLocal8Bit().data(),3),a2=GetDisp(name.toLocal8B
0 r2 k* T: b: r# X$ q4 nit().data(),2),a1=GetDisp(name.toLocal8Bit().data(),1),b,disp,length; 4 `& v9 i; I) t, \7 k/ b, i0 _
a&=0x7FFF;
; n3 w# S8 }) f' Dwhile(!((b=((int*)buffer2)[a*3+2])&0x80000000)||a1!=((int*)buffer2)[a*3]||a2!
( Q! R7 B5 a' \& {0 r=((int*)buffer2)[a*3+1])
( v5 s. z) n& q+ V* u{ 7 ]" M- M: y% @+ w8 I! X
a++;
' ]9 V& ^5 ^( c; b- z3 z* w9 La&=0x7FFF;   d# x% B1 L9 L' _+ X
}
5 |8 S' Z7 X4 f% U& [- s1 |) \b&=0x3FFFFFFF; ' N( e  f. w0 W8 x6 w
disp=((int*)buffer3)[b*3]; 3 _7 ~! v2 }# c1 i1 `' O
length=((int*)buffer3)[b*3+1];
0 _7 ~6 N& L) K  I- v; E8 A8 ?
+ j$ J! i- f/ c. @0 IQFile pdata(this->package_name);
+ Y, J8 J+ c7 g4 nif (pdata.open(QFile::ReadOnly)&&pdata.seek(disp)) { . F" m4 Q$ j7 H9 a8 V$ P+ M! b
- `+ T% x: }/ F$ n5 Q9 ]4 F
QString wdir=QDir::currentPath()+QDir::separator()+QFileInfo(pdata).fileName
0 _& M0 T$ m3 x+ r()+QDir::separator();   i& c6 g" U  G1 {- S, q
QDir dir; ! ~, l% d; @' F* [* B
QDataStream pfin(&pdata); / v( C- }+ S: A
QFile file(wdir+name);
9 B5 a: h& ]5 P5 c2 J, i2 Y! GQFileInfo info(file); 5 t  e+ ?4 W- U6 }
dir.mkpath(info.absolutePath());   U' e8 {# y- ~- p, S4 n
if(file.open(QFile::WriteOnly))
* z) U( }# m; y9 A* _$ g3 K{ 5 a9 V# P# J' |$ k  l, Y$ w
char* pBuffer=new char[length];; & h3 n  L. h) y# {* V, _, X
QDataStream fout(&file); ; V9 r. G  A- D' e
pfin.readRawData(pBuffer,length); " o& }0 Y" [- x# }
fout.writeRawData(pBuffer,length); - k, _9 }( r6 l3 u. j4 @9 y
delete []pBuffer;
+ e0 L* d/ J+ v2 b4 F+ @return true; 4 [- v* y( d) v7 J! b' Z8 J8 D7 A) {
}
6 C7 V8 ?7 t6 _+ q+ K}
2 s( N( @- }( ~, X" Ereturn false;
) _) i$ I  [/ T7 j}
) V# F8 }# L0 q- b  U6 u得到待解压文件在文件索引中的位置後就可以找出该文件在axp文件中的具体偏移量和文件 6 h/ ?  z1 j! t! B
大小了,然后直接fseek一下然后在弄出来就OK了。
7 [3 h( F* m6 M: S' r8 y最后说一下,这个AXP压缩包本身就含有一个文件列表文件叫做(list),所以每次只要先解 : i: ~+ b' J4 Y9 o- d7 q
压缩这个文件,然后按照里面的文件列表来一一解压缩就OK了。 + a8 t7 V) q  f& u
" ~$ _( [4 ]7 G- W$ R
8 A8 ?  L8 z! s! u& e+ F# ~
以上就是文件大致格式,感觉还是比较简单的,也可以考虑在自己的项目中使用类似方法 8 J/ ?, c* m2 z1 d- g
进行文件压缩。 $ [4 n# M9 N/ v" N4 f

: U+ Y* V! G9 {2 yPS:本文仅供学习,本人不负任何责任。。。。




欢迎光临 冒险解谜游戏中文网 ChinaAVG (https://chinaavg.com/) Powered by Discuz! X3.2