上次在这翻资料的时候正好看到某人写的虚拟村庄3的汉化教程 手头上正好也有这游戏 所以决定小试下汉化
2 W2 D) O# N @
" \0 U6 d# n) V在汉化前我们需要分析下游戏是如何显示字符串的 是贴图还是点阵
: i4 Y( J6 [! ~0 ?这里是用bitblt贴上去的 / [1 O* ]- A3 P& A4 O% [
知道是贴图就要寻找相应的字库和字符串 , A. a6 l7 j" ?& h
字库在image文件夹就能找到
; L+ Y J9 N+ {4 U) D: M# ^# F2 r4 q字符串被压在了EXE里(脱壳后exe增大了3MB) 2 P0 f6 }8 p5 D8 p" r9 L/ N3 e: g
3 U- ?, {1 L" _7 ^" F. ]5 i9 k9 M! F下面就是分析游戏是如何显示字符串的 + G, X' L* u( m8 k/ V! H- E
用OD载入脱壳后的EXE文件 找到某个字符串下硬件访问 我这里断的是Quit+ d' f! f7 [6 L2 f- }" w! z- A
1 {. `' W5 ^# U, A; V按F9启动游戏
7 m. a7 q# G/ S6 D然后断在4F24D2处" W; B( G( x# u {* M9 P0 J. r
这里是读取字符串用的9 Z7 E b( L% X- m& j6 c$ E
/ `& \) v% u1 G; L$ u4 @分析下
7 z+ [( r2 ~2 [- {. J4 Y# V1 E004F24D0 |> 8B01 /MOV EAX,DWORD PTR DS:[ECX] 这里是读取4字节 quit
/ R$ C6 w: z/ v( w1 G, Y004F24D2 |. |BA FFFEFE7E |MOV EDX,7EFEFEFF 这里一块主要分析字符串是否已经到\04 ]) e; M% P6 n( r6 e9 S+ m9 f3 l# q" J7 ^
004F24D7 |. |03D0 |ADD EDX,EAX
; N* T1 e- M9 n3 \' o004F24D9 |. |83F0 FF |XOR EAX,FFFFFFFF
! U) p1 T- k& q H+ Y004F24DC |. |33C2 |XOR EAX,EDX
3 H! T1 y5 a1 y) t, P# ?1 }004F24DE |. |83C1 04 |ADD ECX,4 读取后面4个字节
m, F* j1 u/ L0 |+ W004F24E1 |. |A9 00010181 |TEST EAX,81010100 + P& K u l1 q+ K* [
004F24E6 |.^ 74 E8 |JE SHORT Unpacked.004F24D0 如果是4个00(也就是81010100)就跳出+ u$ U- t: D r7 t
; x, T+ F5 M1 G- B# C+ J8 B& D
这里要注意一下$ g1 t8 j3 }3 u8 \
因为是4字节一取 \0处一定要是00 00 00 005 z0 N& X* B4 m! T% r& j
如果要把Quit$ h9 D/ x1 v1 {# N" f @+ p) j
51 75 69 74 00 00 00 00 Quit....Quit....5 w+ g2 s* B1 y- @; R9 c4 b7 s" a
翻译成"退出吧" 就需要在加4字节
% j2 M/ W+ o3 e$ j0 s地方不够用咋办 幸好ecx是个指针 MOV EAX,DWORD PTR DS:[ECX]
7 s; @8 `- ^' v$ u. U/ L只要把ecx里的地址改成你的就OK了) m S0 [' w |4 J2 S
/ O) U3 W& r% Q
继续找处理图片的地方8 e) e v/ P; {7 ^) K- f
一路跟下来到了3 R' V3 n) Q/ R; B! P
I) W. I+ `# x7 B; A004F398C |. 83E6 F0 AND ESI,FFFFFFF0% Y/ X$ U" k! o" I2 c8 U3 r
004F398F |> 56 PUSH ESI ; /HeapSize = 56 C% |1 y9 Y7 A( C% i
004F3990 |. 6A 00 PUSH 0 ; |Flags = 0
9 @/ l. C) r: `8 y- W004F3992 |. FF35 3C7B7B00 PUSH DWORD PTR DS:[7B7B3C] ; |hHeap = 00D600001 k* Q4 W) ^% j! ^! y! }
004F3998 |. FF15 14815100 CALL DWORD PTR DS:[<&kernel32.HeapAlloc>>; \HeapAlloc8 C6 E$ Q; ^& z$ c! j. I" S: z, l' ^
004F399E |> 5E POP ESI7 H! h O/ h8 g$ I& O$ ?
( @/ f% }1 h) I$ \发现HeapAlloc 这个是用来分配内存的% T: l2 v1 P2 b: }0 `' n1 Y3 ?. k
F8步过 取eax的地址 就是将写入新的quit的地方7 r0 E% o" J$ K$ \5 K
对其下硬件访问 F9运行" x! ]1 k; p* d5 _0 h
断在了403811( Q% l0 t- @: d7 A
在F9几次 断在了4091c4
( |5 M" k* A! ]/ P& x4 n在F9几次 回到了403811 t% O$ v( ^" s% C# a% G
$ @/ R/ {* h/ k" T D$ z确定就是这2处地方了# z1 Z5 r" n7 |9 S, {
这里我选择了4091c4 因为在跟踪403811后发现这里的数据没用. v2 F- k2 i% m" p8 X% r ?
4 M: I2 p$ W$ H4 E: P
004091BE |> 8B55 08 /MOV EDX,DWORD PTR SS:[EBP+8]
+ D* x/ d8 s0 r# S* n' s( W W; i004091C1 |. |0FBE02 |MOVSX EAX,BYTE PTR DS:[EDX] 取第一个字节Q6 v+ t2 e- e; O
004091C4 |. |85C0 |TEST EAX,EAX
# |6 R& c, W$ g/ ~- F; B004091C6 |. |0F84 E2000000 |JE Unpacked.004092AE 字符串到达\0就跳出+ A. [7 @0 L0 J; ^
004091CC |. |8B4D 08 |MOV ECX,DWORD PTR SS:[EBP+8]
2 ]) z. T' t/ T' u9 @" \004091CF |. |0FBE11 |MOVSX EDX,BYTE PTR DS:[ECX] 取第一个字节Q4 J1 ]* y( Z1 i' M! [
004091D2 |. |83FA 0A |CMP EDX,0A 判断是否是空格
! h" {' q3 ^0 w2 b$ l& K9 l004091D5 |. |75 21 |JNZ SHORT Unpacked.004091F8
/ v- P& ~6 x3 o$ H004091D7 |. |8B45 E8 |MOV EAX,DWORD PTR SS:[EBP-18]
7 P" v7 ]+ h. ^3 z8 i9 Z004091DA |. |8945 0C |MOV DWORD PTR SS:[EBP+C],EAX& w$ n3 m1 d9 e; j; E, L
004091DD |. |6A 00 |PUSH 0 ; /Arg1 = 00000000" a1 p' s: Y& w3 p) Z
004091DF |. |8B4D F8 |MOV ECX,DWORD PTR SS:[EBP-8] ; |3 S5 Y2 v! n) f" K" @
004091E2 |. |E8 C9A7FFFF |CALL Unpacked.004039B0 ; \Unpacked.004039B0
8 G: X1 ?! `/ p( B, b0 A004091E7 |. |0345 10 |ADD EAX,DWORD PTR SS:[EBP+10]
% v& _/ n1 ]3 j- s& g8 F A004091EA |. |8945 10 |MOV DWORD PTR SS:[EBP+10],EAX
! X- R0 E: G1 L5 ?5 B; [! D004091ED |. |8B4D 08 |MOV ECX,DWORD PTR SS:[EBP+8]
# S P+ S h7 ?: e$ t3 p004091F0 |. |83C1 01 |ADD ECX,1: q$ E! ?. U) t5 d
004091F3 |. |894D 08 |MOV DWORD PTR SS:[EBP+8],ECX/ }) Y0 b+ o' @& r
004091F6 |.^ EB C6 |JMP SHORT Unpacked.004091BE
/ M7 J& E# Y) O* K. _004091F8 |> |8B55 08 |MOV EDX,DWORD PTR SS:[EBP+8] 不是的空格跳到这里2 s6 `+ K, ?; m; g4 p1 }' \
004091FB |. |0FBE02 |MOVSX EAX,BYTE PTR DS:[EDX] 把Q给EAX (实现双字节 就要让他取WORD 这里需要改造)
" f X5 \. H! `: Q( e q. f004091FE |. |8945 C0 |MOV DWORD PTR SS:[EBP-40],EAX 把Q 放到参数中去
* P- S+ y; i7 P6 F' O1 }00409201 |. |8D4D D8 |LEA ECX,DWORD PTR SS:[EBP-28]
! N7 M/ V: k8 l7 a00409204 |. |51 |PUSH ECX ; /Arg2 \% {1 p7 h: G3 T4 K8 G
00409205 |. |8B55 C0 |MOV EDX,DWORD PTR SS:[EBP-40] ; |
8 l* a+ @6 A9 L# y7 _00409208 |. |52 |PUSH EDX ; |Arg1 压入Q( s5 ~9 e- S. m) M" T& C
00409209 |. |8B4D F8 |MOV ECX,DWORD PTR SS:[EBP-8] ; |
: I# p5 `, p$ r! f7 O+ O0040920C |. |E8 0FB4FFFF |CALL Unpacked.00404620 ; \Unpacked.00404620 这里是关键
" o3 t1 F) ]7 x9 h- ]" p8 ?0 y00409211 |. |8B45 08 |MOV EAX,DWORD PTR SS:[EBP+8]+ R B/ @; Z6 A- {
00409214 |. |83C0 01 |ADD EAX,1 读完Q后读u
6 w0 U- ^: I( V" p) X/ n00409217 |. |8945 08 |MOV DWORD PTR SS:[EBP+8],EAX
8 n6 X, Y) o: R' r0 ~1 }0040921A |. |8D4D D8 |LEA ECX,DWORD PTR SS:[EBP-28]5 A$ p% b8 _ p0 k9 s+ f( L1 H, y/ [
0040921D |. |E8 5E8BFFFF |CALL Unpacked.00401D80 这里存入了画Q需要的长度4 }# U; o0 Y2 s5 ?9 a: ?% R0 Y
00409222 |. |8945 D4 |MOV DWORD PTR SS:[EBP-2C],EAX* I7 f3 d7 n2 z! D, U8 S' I
00409225 |. |837D D4 00 |CMP DWORD PTR SS:[EBP-2C],0) R2 H2 X! x: }8 E, W8 |6 x+ P
00409229 |. |74 7E |JE SHORT Unpacked.004092A99 G9 J4 ?# }* m/ o9 D( z) L
& }: A: f; h& V, V5 S% @! B' c
# o0 O, s2 ?5 R( F0 z8 f* o% y& m [- }3 B( X, Y
" `' n7 {- N K' Q2 a4 u0 {9 ~9 O @; A; N4 `
! T' I: Q v/ M4 C+ |00404620 /$ 55 PUSH EBP
% E. n% \, }0 {! r' O00404621 |. 8BEC MOV EBP,ESP
# k. \& D" ]# w7 l- ^3 V00404623 |. 83EC 0C SUB ESP,0C
& }3 Y8 @. p& a7 G" h00404626 |. 894D F4 MOV DWORD PTR SS:[EBP-C],ECX ! _5 b+ }% a, L' ~/ s) }
00404629 |. 8B45 F4 MOV EAX,DWORD PTR SS:[EBP-C]; D; c. T* [, w9 o. `( s5 }
0040462C |. 8B48 14 MOV ECX,DWORD PTR DS:[EAX+14]
1 O) R. f* K8 L0 ?/ N; H0040462F |. 894D FC MOV DWORD PTR SS:[EBP-4],ECX8 }2 Z& T; Y( ^" S; j' v+ d0 I
00404632 |. 837D 08 00 CMP DWORD PTR SS:[EBP+8],0 这里就是边界检查! X7 b7 }' t7 h- f4 c3 `9 F# D' y
00404636 |. 7D 0D JGE SHORT Unpacked.004046452 [' ?) {4 R. X
00404638 |. 8A55 08 MOV DL,BYTE PTR SS:[EBP+8]
3 W2 K6 r1 h* [- l5 L' U, R0040463B |. 8855 FB MOV BYTE PTR SS:[EBP-5],DL
1 k* U* h* z0 {- `* Y8 S& j( z; b0040463E |. 0FB645 FB MOVZX EAX,BYTE PTR SS:[EBP-5]
E: g$ d( b5 v9 M7 R# R, \00404642 |. 8945 08 MOV DWORD PTR SS:[EBP+8],EAX8 D) {# k8 X) Q
00404645 |> 817D 08 00010>CMP DWORD PTR SS:[EBP+8],100 边界检查
y( Y- Y, ` Q1 b! V0040464C |. 7D 18 JGE SHORT Unpacked.00404666: A: P1 K& p0 E
0040464E |. 8B4D 08 MOV ECX,DWORD PTR SS:[EBP+8]
$ J' K' S: {5 ^6 L `$ u% }' ?00404651 |. 8B55 F4 MOV EDX,DWORD PTR SS:[EBP-C]. p1 n4 o0 [& U7 Q! m0 U
00404654 |. 8B448A 18 MOV EAX,DWORD PTR DS:[EDX+ECX*4+18]) C) R! _3 u! b, S1 E% X+ g8 A( N
00404658 |. 6BC0 14 IMUL EAX,EAX,14& V7 ?0 }, n; J7 ~& t0 e
0040465B |. 8B4D F4 MOV ECX,DWORD PTR SS:[EBP-C]& p6 W9 V9 O, _9 d0 e% H' g
0040465E |. 0341 14 ADD EAX,DWORD PTR DS:[ECX+14]2 D4 ^2 V* x* o2 N
00404661 |. 8945 FC MOV DWORD PTR SS:[EBP-4],EAX
4 K) u( j7 J" j5 r8 u$ Q0 x00404664 |. EB 15 JMP SHORT Unpacked.0040467B
8 Q# q) C5 t. y% h6 ?1 Z+ v* s2 U1 c00404666 |> 8B55 08 MOV EDX,DWORD PTR SS:[EBP+8] 这里一块是算Q的码表
5 |) l$ R j \8 a% [9 k2 ^" V% M- `) U0 X) M. W% u# R# ]6 Z% p8 f
4 B& d/ F; w- w' F& U, O
& ?1 \% P; W+ n& N% D8 N9 K0054AA48 51 00 00 00 2D 02 00 00 00 00 00 00 3C 02 00 00 Q...-......<..5 y1 p _3 J4 C$ e3 H3 ~
0054AA58 1B 00 00 00 ...
4 ]* Q2 s M% l _
, A5 G3 K- `9 b51就是字符Q
2 c! k6 E6 s. Q9 p0 U2 u2D 02 00 00
* r- W3 S: C/ s/ m( s2 A7 f# j00 00 00 00
' z* q; B9 W" C! N3 {5 r8 ~3C 02 00 00/ H1 }9 ~) z: Z' X8 W$ c% a: l2 U
1B 00 00 002 W R8 M# ^* f1 X8 H/ S2 ^
$ F I' K k% E) n1 ]/ `$ Z A━━┓ 0 d" k' i) k0 V/ v8 a# K' t$ Q& ~! v* ?
┃ Q ┃
7 _. `" D: T8 Z4 b. @ ┗━━B2 O9 J9 i$ V! ]6 z& R: h, P
/ Q5 `+ E" u# k* jA的坐标 (22D,0)2 K- A4 K$ G1 \% f O$ n1 r' |8 ^
B的坐标 (23C,1B)
# e" W* b' I) q8 Q! r8 J1 h$ w5 I/ c. ^1 n0 a; Q# W9 ?1 C
3 `0 k* y: V( a O( g( B; g0 J: o" v, b) `) s) |, S2 \8 ]2 h
00404669 |. 81E2 FF7F0000 AND EDX,7FFF
9 ] U3 V' u1 J9 _+ h( q3 Q0040466F |. 6BD2 14 IMUL EDX,EDX,144 T" ~% d9 a$ a. J' X& R' {" i
00404672 |. 8B45 F4 MOV EAX,DWORD PTR SS:[EBP-C]+ l- {, a {! G. t: [# P& z& o
00404675 |. 0350 14 ADD EDX,DWORD PTR DS:[EAX+14]
! m$ }- S1 @0 ]00404678 |. 8955 FC MOV DWORD PTR SS:[EBP-4],EDX4 o8 Q* _! A U( a
0040467B |> 8B4D 0C MOV ECX,DWORD PTR SS:[EBP+C]
* l4 V5 c! d8 p4 J4 }0 b' j, i0040467E |. 8B55 FC MOV EDX,DWORD PTR SS:[EBP-4]* A" D6 ]% n% U% ?
00404681 |. 8B42 04 MOV EAX,DWORD PTR DS:[EDX+4]5 c1 K, f- d1 v% J
00404684 |. 8901 MOV DWORD PTR DS:[ECX],EAX 存入22D
5 n0 n! V( ~+ ]; U00404686 |. 8B4D 0C MOV ECX,DWORD PTR SS:[EBP+C]5 V/ t) @- E, j' P( V4 A t5 j) _& i
00404689 |. 8B55 FC MOV EDX,DWORD PTR SS:[EBP-4]
- l/ f# ?, }" v9 G9 p& G9 m" A7 P0040468C |. 8B42 0C MOV EAX,DWORD PTR DS:[EDX+C]/ S: c$ p+ Q1 T
0040468F |. 8941 08 MOV DWORD PTR DS:[ECX+8],EAX 存入23C
$ R" Q- U2 O0 p4 q- @# e2 W00404692 |. 8B4D 0C MOV ECX,DWORD PTR SS:[EBP+C]
: Z- J& H! H% W, Z# M00404695 |. 8B55 FC MOV EDX,DWORD PTR SS:[EBP-4]
2 J! z# {; r3 O00404698 |. 8B42 08 MOV EAX,DWORD PTR DS:[EDX+8]
. h/ d6 a: B# L9 e0 _3 h- p- i0040469B |. 8941 04 MOV DWORD PTR DS:[ECX+4],EAX 存入00 O7 c4 R$ T# ?3 k9 V' V# \
0040469E |. 8B4D 0C MOV ECX,DWORD PTR SS:[EBP+C]* A& E2 E+ w9 ?
004046A1 |. 8B55 FC MOV EDX,DWORD PTR SS:[EBP-4]1 w; g/ X9 Z: j/ J. R8 y7 f7 u
004046A4 |. 8B42 10 MOV EAX,DWORD PTR DS:[EDX+10]
5 u1 B1 N1 t6 m4 y& ?! T004046A7 |. 8941 0C MOV DWORD PTR DS:[ECX+C],EAX 存入1B
: [9 t. n& x" v" v1 e004046AA |. 8BE5 MOV ESP,EBP9 ?- k2 \) J1 G3 m! ?( z2 Z2 y
004046AC |. 5D POP EBP& l( [# J! w( F! f% x
004046AD \. C2 0800 RETN 8+ M, v- o8 Q) e9 v
, S9 x h4 E* A2 ?" U. q- z6 W6 d- y
. @7 T0 }1 Q+ C# a. K+ ~1 w. j& n
" Z3 F. T; c* i5 O* J4 R
S( L9 P0 d v. h3 v% j# ]7 T) d7 D! n/ P
知道这些后 就可以改造了
0 e4 p( q! L& w, U% c7 D2 v先改字库$ c8 G- a, `, w9 n( g! v
1 R8 p9 T9 U% L( V4 h7 c2 {7 W
# ^: b1 R$ W) F然后改成支持汉字的7 r* ^. `: w$ w2 |
把4091d2 的 CMP EDX,0A 改成jmp
4 ~+ s, j, q e# W6 ?跳到我的代码上去
( [3 I6 F+ C5 \% }& n) s- a/ o. f/ T, v4 s7 L, h
AND EDX,0FF 去除高位的FF
1 n- F6 V+ [ w7 J9 J$ bCMP EDX,0B0 比较是否汉字 跟比较80一样 因为我的字库是从 啊(B0 A1) 开始的
( a# A# x" f3 A' r% U2 j3 T7 uJL Unpacked.004091F8 小于 B0的就跳回去0 y. Z3 U8 K8 B% c6 j- C9 ^, i% _
MOV EDX,DWORD PTR SS:[EBP+8]
. I; I2 }1 b4 p; NMOVSX EAX,WORD PTR DS:[EDX] 取2个字节 (支持汉字)! C+ b8 q ?. e& {3 y ?: G
AND EAX,0FFFF 去除汉字高位的FF
; a1 R: ]& B5 S. e& o( QMOV DWORD PTR SS:[EBP-40],EAX 存入形参
5 `' v# p" B( S. l! v/ RLEA ECX,DWORD PTR SS:[EBP-28]
# {" x: @/ E9 @: x( ^* U* H2 o% L3 S- H7 oPUSH ECX ; /Arg2
: T; V1 O6 Q! f) u# c( KMOV EDX,DWORD PTR SS:[EBP-40] ; |
$ W' y1 M; u* L: `* c& BPUSH EDX ; |Arg1
$ l3 C& _9 x/ e7 b7 y* UMOV ECX,DWORD PTR SS:[EBP-8] ; |2 a' j* ]6 Y( L3 J' y0 c+ `
CALL Unpacked.007CFF3C 这里是读取并存入 字符串X Y坐标
% v2 _9 v# j' B, H! G2 B! A0 y; nMOV EAX,DWORD PTR SS:[EBP+8]( \- A: F2 o* ~/ n; `! V
ADD EAX,2 call出来后加2个字节
) k. i1 T) o0 g! c1 a6 AJMP Unpacked.00409217
% v7 w- E4 g) h( _; w: l
$ |8 M9 h$ T5 P0 d. R2 T2 [% ^* Q' f4 }, ^
& s; F- l! s( T" [2 ~, g
1 W# s- _- i3 W0 w8 _6 }0 I" QPUSH EBP
' ^# u% @' O' S& S& m9 YMOV EBP,ESP
7 Y- w( |! a( G4 F2 CSUB ESP,0C
1 o) N+ c( J4 i5 X9 N5 S* G3 b" zMOV DWORD PTR SS:[EBP-C],ECX" |9 {9 F0 a/ i# ~' l
MOV EAX,DWORD PTR SS:[EBP-C]
& L" K8 N4 I1 e% W. oMOV ECX,DWORD PTR DS:[EAX+14]( c9 `. G4 B' n, D
MOV DWORD PTR SS:[EBP-4],ECX2 M8 r; X2 ^* V) ?/ a) y8 {2 J
CMP DWORD PTR SS:[EBP+8],0F9D7 边界检查 我这里最后个文字是 座(D7 F9)
) T* u6 n# ]# A- q/ nJG SHORT Unpacked.007CFF8E 超出就绘制一个空白图片
" ]; f8 c: s0 _! Q9 U( r6 k' n5 kMOV ECX,DWORD PTR SS:[EBP+8] 从形参读取汉字 把汉字 放入ecx (我这里代码写的乱)3 w% Y8 y( @" _5 y# f9 U6 ^
XOR EAX,EAX4 `* |0 n# Z9 {
MOV AL,CL 把汉字第一个字节 放入eax1 M, Q6 a& p, C' o3 l
SHR CX,8 右移8位取第二个字节
. n3 H$ _4 g4 j! {/ yXOR EDX,EDX! m+ {- \6 s2 k$ b
MOV DL,CL 把第2个字节放到edx去+ r8 _* p3 `. ~ F2 P
SUB AL,0B0 这里是我自己写的算法 不用再读取码表了4 @$ o: _$ q( h" ^
SUB DL,0A1
) g5 h8 f3 t3 OIMUL EAX,EAX,10 我用的 宋体16 一个汉字是16X16) Z% t6 U2 W& V; U6 J" h1 G* }$ Z
IMUL EDX,EDX,10# S6 D* B' _* A+ @2 J' x2 E
ADD EAX,20 加上我图片原来的高度: ?' t* ~; O) Z0 n; e% \4 z
MOV ECX,DWORD PTR SS:[EBP+C]
; B) e( Q2 e: v6 yMOV DWORD PTR DS:[ECX],EDX* s: s' V& I" A P' y |. t% u
MOV DWORD PTR DS:[ECX+4],EAX
- G7 T' e; Q. u: {* vADD EAX,10( p: j! ~$ Y2 q4 z# n
ADD EDX,10
2 x$ D' L7 A6 p, p: t% }: C; yMOV DWORD PTR DS:[ECX+8],EDX* X" |+ g5 R6 n
MOV DWORD PTR DS:[ECX+C],EAX1 g% G8 n1 H @7 i* U' K- R
MOV ESP,EBP
o9 j% s& R2 b& W+ b4 D( kPOP EBP0 }6 I) S7 T: {) H
RETN 8# c# C" {! o8 w# V
4 f6 p4 b* T' l/ u' P
# }# T) d9 v( t' w9 G* `$ ]
|