11use std:: ffi:: c_void;
2+ use std:: sync:: Mutex ;
23
34use windows_sys_loader:: Win32 :: System :: Diagnostics :: Debug :: FlushInstructionCache ;
45use windows_sys_loader:: Win32 :: System :: Memory :: { VirtualProtect , PAGE_EXECUTE_READWRITE } ;
56use windows_sys_loader:: Win32 :: System :: Threading :: GetCurrentProcess ;
67
78use crate :: config:: Config ;
89use crate :: patches;
10+ use crate :: util:: api:: Api ;
911use crate :: util:: memory:: PatchMemory ;
1012
13+ enum EarlyLog {
14+ Info ( String ) ,
15+ Warn ( String ) ,
16+ }
17+
18+ static EARLY_LOGS : Mutex < Vec < EarlyLog > > = Mutex :: new ( Vec :: new ( ) ) ;
19+
1120struct DirectMemory {
1221 game_base : usize ,
1322 game_size : u32 ,
@@ -30,7 +39,20 @@ pub unsafe fn apply(game_base: usize) {
3039 game_size,
3140 } ;
3241 let config = Config :: load ( & base_dir) ;
33- patches:: apply_early ( & memory, & config) ;
42+ patches:: apply_pre_tls ( & memory, & config) ;
43+ }
44+
45+ pub fn flush_logs ( api : & Api ) {
46+ let logs = match EARLY_LOGS . lock ( ) {
47+ Ok ( mut logs) => std:: mem:: take ( & mut * logs) ,
48+ Err ( _) => return ,
49+ } ;
50+ for log in logs {
51+ match log {
52+ EarlyLog :: Info ( message) => api. log_info ( & message) ,
53+ EarlyLog :: Warn ( message) => api. log_warn ( & message) ,
54+ }
55+ }
3456}
3557
3658impl DirectMemory {
@@ -112,9 +134,17 @@ impl PatchMemory for DirectMemory {
112134 true
113135 }
114136
115- fn log_info ( & self , _message : & str ) { }
137+ fn log_info ( & self , message : & str ) {
138+ if let Ok ( mut logs) = EARLY_LOGS . lock ( ) {
139+ logs. push ( EarlyLog :: Info ( message. to_owned ( ) ) ) ;
140+ }
141+ }
116142
117- fn log_warn ( & self , _message : & str ) { }
143+ fn log_warn ( & self , message : & str ) {
144+ if let Ok ( mut logs) = EARLY_LOGS . lock ( ) {
145+ logs. push ( EarlyLog :: Warn ( message. to_owned ( ) ) ) ;
146+ }
147+ }
118148}
119149
120150fn find_pattern ( image : & [ u8 ] , pattern : & [ u8 ] , mask : & str ) -> Option < usize > {
@@ -132,88 +162,4 @@ fn find_pattern(image: &[u8], pattern: &[u8], mask: &str) -> Option<usize> {
132162}
133163
134164#[ cfg( test) ]
135- mod tests {
136- use std:: cell:: RefCell ;
137-
138- use super :: * ;
139-
140- struct FakeMemory {
141- base : usize ,
142- image : RefCell < Vec < u8 > > ,
143- }
144-
145- impl PatchMemory for FakeMemory {
146- fn game_base ( & self ) -> usize {
147- self . base
148- }
149-
150- fn game_size ( & self ) -> u32 {
151- self . image . borrow ( ) . len ( ) as u32
152- }
153-
154- fn aob_scan ( & self , start : usize , size : u32 , pattern : & [ u8 ] , mask : & str ) -> usize {
155- let offset = start - self . base ;
156- let image = self . image . borrow ( ) ;
157- find_pattern ( & image[ offset..offset + size as usize ] , pattern, mask)
158- . map_or ( 0 , |found| start + found)
159- }
160-
161- fn mem_read ( & self , addr : usize , buf : & mut [ u8 ] ) -> bool {
162- let offset = addr - self . base ;
163- buf. copy_from_slice ( & self . image . borrow ( ) [ offset..offset + buf. len ( ) ] ) ;
164- true
165- }
166-
167- fn mem_write ( & self , addr : usize , data : & [ u8 ] ) -> bool {
168- let offset = addr - self . base ;
169- self . image . borrow_mut ( ) [ offset..offset + data. len ( ) ] . copy_from_slice ( data) ;
170- true
171- }
172-
173- fn log_info ( & self , _message : & str ) { }
174-
175- fn log_warn ( & self , _message : & str ) { }
176- }
177-
178- #[ test]
179- fn early_scanner_matches_wildcards_before_tls ( ) {
180- // Given: 版本间变化的字节位于稳定指令签名中。
181- let image = [ 0x85 , 0xC0 , 0x75 , 0x07 , 0xBE , 0x00 , 0x12 , 0x80 ] ;
182- let pattern = [ 0x85 , 0xC0 , 0x75 , 0x07 , 0xBE , 0x00 , 0x00 , 0x80 ] ;
183-
184- // When: TLS 前扫描器使用与晚期 patch 相同的掩码。
185- let found = find_pattern ( & image, & pattern, "xxxxxx?x" ) ;
186-
187- // Then: 可变字节不会破坏版本无关识别。
188- assert_eq ! ( found, Some ( 0 ) ) ;
189- }
190-
191- #[ test]
192- fn enabled_checks_are_patched_by_shared_early_pipeline ( ) {
193- // Given: AppUser 与 TLS 检测仍是原字节,且配置明确启用两项绕过。
194- let mut image = vec ! [ 0x90 ; 64 ] ;
195- image[ 8 ..14 ] . copy_from_slice ( & [ 0x83 , 0x7C , 0x24 , 0x04 , 0x00 , 0x75 ] ) ;
196- image[ 24 ..40 ] . copy_from_slice ( & [
197- 0x85 , 0xC0 , 0x75 , 0x07 , 0xBE , 0x00 , 0x00 , 0x80 , 0x00 , 0xEB , 0x02 , 0x33 , 0xF6 , 0x8B ,
198- 0x5B , 0x34 ,
199- ] ) ;
200- let memory = FakeMemory {
201- base : 0x1000 ,
202- image : RefCell :: new ( image) ,
203- } ;
204- let config = Config {
205- base_dir : "." . to_owned ( ) ,
206- sections : "[BypassAppUser]\n [DisableTLS]"
207- . parse ( )
208- . expect ( "测试配置必须有效" ) ,
209- } ;
210-
211- // When: DLL_PROCESS_ATTACH 使用与晚期阶段共享的 patch 定义。
212- patches:: apply_early ( & memory, & config) ;
213-
214- // Then: 两个会在 TLS 初始化中被缓存的检测都已提前改写。
215- let image = memory. image . borrow ( ) ;
216- assert_eq ! ( image[ 13 ] , 0xEB ) ;
217- assert_eq ! ( image[ 31 ] , 0x00 ) ;
218- }
219- }
165+ mod tests;
0 commit comments