本帖最后由 shane007 于 2023-8-27 10:49 编辑
# |4 r$ G' v$ A+ R' a K! m
8 ~9 o/ k) ]) j这个游戏是opengl引擎的,对opengl的初始化主要是在vision71.dll里做的。经过grep文字检索之后,确定这个游戏没有调用 glGenLists和glCallList这2个函数来用于字幕显示。
, s+ V/ c, y- z9 Y$ j. B3 M. f$ j8 j& V& q, K n
dxwnd窗口化之后,用cheatengine 检索内存字符串(注意,有的字符串在内存有2份,对后1份下断点才有用),
3 G) w) ]% c: o: z* {! k+ p/ m随后下断点。在以下地方断下。! O, X: O5 Q9 u
; ?. w2 \6 C# t7 s' f* C
- Operation Wintersonne.exe+CE883 - F3 A5 - repe movsd
0 J. ~9 @- J$ s) ^- [* f - 004CE883
复制代码
9 a6 O- L8 Z! W: H' w1 H* o, e% j( W6 a+ W1 M
用ida pro查看之后,发现是个底层方法。
2 K) x. @+ Q; [. t7 q真的显示函数应该是调用它的上层方法。$ B) o$ G7 ^$ D& x' D7 v
- void *__cdecl memcpy_0(void *a1, const void *a2, size_t a3)
/ o; x2 f- g# H) K
复制代码 9 ?! U$ x4 A9 I
0 |3 ^2 S+ P6 b7 U2 m4 ^这个方法看着蛮像的,也许就是它,待日后修改代码测试
8 r I/ `) n& `) }! |% _( q D; d8 }
- : s3 B2 C' A) D# E; C
- int __thiscall ATL::CSimpleStringT<char,0>::SetString(_DWORD *this, void *a2, size_t a3)
( a. i3 n& t" G ~, n$ R - {1 J. J+ x' O, {' }) Y
- unsigned int v4; // edi
+ ~# P: W$ j* o# C7 I - char *v5; // esi& N1 m1 e+ i5 r' g" `& X9 R$ J6 b8 a1 G
- void *v6; // eax
0 d% {6 e, ]+ S+ @2 i - 7 a- y! h; M( j% e7 ~
- if ( !a3 )2 e4 l8 \( y: F, l8 C& x! n; L/ ]
- return ATL::CSimpleStringT<char,0>::Empty();
7 t# G3 I8 d' A" h4 n- p5 h' [# h7 y$ v - if ( !a2 )
3 Y( D$ L% D+ Y$ h' P3 N/ k - unknown_libname_180(-2147024809);( L8 b/ `3 k9 m% s1 z( R) l1 y
- v4 = *(_DWORD *)(*this - 12);' T( U( `. k( T3 m, c) w
- v5 = (char *)a2 - *this;$ s; k2 L- E5 n5 {; w V1 _$ \; W, }
- v6 = (void *)ATL::CSimpleStringT<char,0>::PrepareWrite(a3);- s( h- k/ `* A5 Q" n2 }
- if ( (unsigned int)v5 > v4 ), q1 U- M, K1 I+ z. K" h7 |
- memcpy_0(v6, a2, a3);3 i: e0 T$ J/ ~# h _
- else
& Y: V% B# S) `9 D" {; X" y8 l M - memcpy(v6, &v5[(_DWORD)v6], a3);
* l9 M( `8 |' A. L - return ATL::CSimpleStringT<char,0>::SetLength(a3);$ g4 t& i8 i: Q! a$ V1 f3 {
- }
. j" G- c7 U0 |7 B
复制代码
/ a C: ^7 T1 a2 T% F8 m) ?8 m6 G4 X. {% w
( @8 `1 d3 K% e0 K+ O1 G! J |