msg_tool\scripts\cat_system\archive/
int_password.rs

1//! Get Password from CatSystem2 Executable
2use crate::types::*;
3use crate::utils::blowfish::{Blowfish, BlowfishLE};
4use crate::utils::encoding::*;
5use anyhow::Result;
6use pelite::FileMap;
7use pelite::pe32::*;
8use std::path::Path;
9
10/// Retrieves the int archive's password from a CatSystem2 executable file.
11pub fn get_password_from_exe<S: AsRef<Path> + ?Sized>(exe_path: &S) -> Result<String> {
12    let path = exe_path.as_ref();
13    let file_map = FileMap::open(path)?;
14    let file = PeFile::from_bytes(&file_map)?;
15    let resources = file.resources()?;
16    let mut code = resources
17        .find_resource(&["V_CODE2".into(), "DATA".into()])?
18        .to_vec();
19    if code.len() < 8 {
20        return Err(anyhow::anyhow!("Invalid V_CODE2 resource length"));
21    }
22    let key = resources
23        .find_resource(&["KEY_CODE".into(), "KEY".into()])
24        .map(|s| {
25            let mut s = s.to_vec();
26            for i in s.iter_mut() {
27                *i ^= 0xCD;
28            }
29            s
30        })
31        .unwrap_or_else(|_| b"windmill".to_vec());
32    let blowfish: BlowfishLE = Blowfish::new(&key)?;
33    blowfish.decrypt_block(&mut code);
34    let len = code.iter().position(|&x| x == 0).unwrap_or(code.len());
35    let result = decode_to_string(Encoding::Cp932, &code[..len], true)?;
36    eprintln!("Used password from CatSystem2 executable: {}", result);
37    Ok(result)
38}