本帖最后由 shane007 于 2023-8-27 10:49 编辑
' y7 _0 Z" P+ }9 j$ m5 T7 Z1 ^: \ }* ^$ z* J
这个游戏是opengl引擎的,对opengl的初始化主要是在vision71.dll里做的。经过grep文字检索之后,确定这个游戏没有调用 glGenLists和glCallList这2个函数来用于字幕显示。7 C. a1 b6 ]5 j
4 i y0 }/ x' O# ^+ M! T+ r3 m
dxwnd窗口化之后,用cheatengine 检索内存字符串(注意,有的字符串在内存有2份,对后1份下断点才有用),
6 l9 a7 a6 E0 T+ z- ^* B随后下断点。在以下地方断下。1 K) u9 d5 \6 _% A& A/ q" L/ L
* U" O. M; ~* t- Operation Wintersonne.exe+CE883 - F3 A5 - repe movsd + D. @% m- P; F( V( j. W! \5 n3 w
- 004CE883
复制代码
) F, b5 `5 j+ `' P0 R/ R' d( m% c- ]8 @6 i1 A, Z( C( `$ O# h
用ida pro查看之后,发现是个底层方法。
- \: p* x% i, T5 T5 i" ^# h3 R0 ?/ n2 K真的显示函数应该是调用它的上层方法。
$ e6 l9 N3 N+ |% Y- void *__cdecl memcpy_0(void *a1, const void *a2, size_t a3)
& Q" M+ _# T% t3 n" K" Q3 d l0 P
复制代码 + K! ^2 k/ \8 X" A: c v3 ]
# S; O1 E8 |0 L
这个方法看着蛮像的,也许就是它,待日后修改代码测试: D2 k& j% P' n8 c
% F/ ~1 z: k/ ]* }! N2 i8 p* m
3 M2 G. J! B B. ~2 ?/ K- int __thiscall ATL::CSimpleStringT<char,0>::SetString(_DWORD *this, void *a2, size_t a3)
9 b" c) j* H0 o: Z9 z" o. Q - {
5 `# T2 \" v' |9 g$ y. P) G3 q - unsigned int v4; // edi
3 M# j1 Q7 l4 J5 l - char *v5; // esi
e, q. h2 Z2 R. x, Z L - void *v6; // eax# b9 m q1 V! w3 D3 G% e, `) {. }
' m- z* g/ C" g. r4 P1 b- if ( !a3 )! i7 W5 ~$ V& Q: e
- return ATL::CSimpleStringT<char,0>::Empty();3 R1 V7 ]" A+ @/ n$ ], B/ }7 K0 `, V
- if ( !a2 )1 X: F) n. b) }* S
- unknown_libname_180(-2147024809);
$ g) @, s) B$ a, [5 h - v4 = *(_DWORD *)(*this - 12);
& | @4 p8 @: m) N5 r" v - v5 = (char *)a2 - *this;2 R2 o f9 v# ?, y r! ]0 K$ W5 @, x
- v6 = (void *)ATL::CSimpleStringT<char,0>::PrepareWrite(a3);- {1 r4 K# G7 {: d/ w7 q1 U! f
- if ( (unsigned int)v5 > v4 )! h3 ^* I2 w, L- n% @6 r
- memcpy_0(v6, a2, a3);
- {2 V7 L: D4 ~2 C! t - else
2 K# L' I# w j5 j - memcpy(v6, &v5[(_DWORD)v6], a3);, B5 N* z7 ?# `' d" B: V' s2 D
- return ATL::CSimpleStringT<char,0>::SetLength(a3);
; u7 ^' ^+ e, j. X - }
% Q$ m# \/ Y; j/ W4 y3 a
复制代码 4 c# ]# l0 G5 L; m q; M
' s$ d# C. |) U- Y; I8 D5 s6 M0 U; {. r0 N r( t
|