Skip to main content

xcelerate_core/stealth/
patcher.rs

1use std::path::Path;
2use std::fs;
3use regex::bytes::Regex;
4use crate::error::{XcelerateResult, XcelerateError};
5
6pub struct BinaryPatcher;
7
8impl BinaryPatcher {
9    /// Patches the binary at the given path to remove/replace automation detection strings.
10    pub fn patch_binary(path: &Path) -> XcelerateResult<()> {
11        if !path.exists() {
12            return Err(XcelerateError::NotFound(format!("Binary not found for patching: {:?}", path)));
13        }
14
15        let mut content = fs::read(path).map_err(|e| XcelerateError::NotFound(format!("Failed to read binary: {}", e)))?;
16        
17        // 1. Search for the CDC pattern: {window.cdc...;}
18        // This is a common pattern used by anti-bot scripts to detect chromedriver.
19        // We use a regex to find the block and replace it with a neutral payload of the same length.
20        let re = Regex::new(r"\{window\.cdc.*?;\}").map_err(|_| XcelerateError::InternalError)?;
21        
22        let mut patched = false;
23        
24        // We iterate and replace. Using find_iter to handle multiple occurrences if any.
25        // However, for the first pass, we can do a simple range replacement.
26        // Note: We MUST NOT change the file size, so we ljust with spaces or similar.
27        
28        if let Some(m) = re.find(&content) {
29            let start = m.start();
30            let end = m.end();
31            let len = end - start;
32            
33            // Replacement payload (equivalent to console.log but same length)
34            let mut payload = b"{console.log(\"xcelerate stealth active!\")}".to_vec();
35            if payload.len() > len {
36                // Truncate if somehow the payload is longer (unlikely for typical CDC blocks)
37                payload.truncate(len);
38            } else {
39                // Pad with spaces to match length exactly
40                payload.extend(std::iter::repeat(b' ').take(len - payload.len()));
41            }
42            
43            content[start..end].copy_from_slice(&payload);
44            patched = true;
45        }
46
47        if patched {
48            fs::write(path, content).map_err(|_e| XcelerateError::InternalError)?;
49            eprintln!("[PATCHER] Successfully patched binary: {:?}", path);
50        } else {
51            eprintln!("[PATCHER] No detection patterns found or already patched: {:?}", path);
52        }
53
54        Ok(())
55    }
56}