myph-v2.git


myph-v2

~ rust shellcode loader with evasive capabilities
git clone https://github.com/djnnvx/myph-v2.git
log | files | refs | archive | README

mod.rs (10981B)

      1 //! Encryption module providing multiple cipher implementations.
      2 //!
      3 //! This module implements a generic encryption interface with support for:
      4 //! - AES-128 (CBC mode with random IV)
      5 //! - AES-256 (CBC mode with random IV)
      6 //! - ChaCha20 (stream cipher with random nonce)
      7 //! - XOR cipher (simple XOR operation)
      8 //! - Blowfish (CBC mode with random IV)
      9 //! - Twofish (CBC mode with random IV)
     10 //! - Camellia-256 (CBC mode with random IV)
     11 //!
     12 //! # Production-Ready Features
     13 //!
     14 //! All implementations use:
     15 //! - SHA-256 for proper key derivation from passwords (except XOR)
     16 //! - Random IV/nonce generation for each encryption operation
     17 //! - IV/nonce prepended to ciphertext for automatic extraction during decryption
     18 //! - Logging of generated IV/nonce values for debugging
     19 //! - Key length warnings for Blowfish
     20 
     21 mod aes256_cipher;
     22 mod aes_cipher;
     23 mod blowfish_cipher;
     24 mod camellia_cipher;
     25 mod chacha20_cipher;
     26 mod twofish_cipher;
     27 mod xor_cipher;
     28 
     29 use sha2::{Digest, Sha256};
     30 
     31 use crate::cli::EncryptionKind;
     32 
     33 pub use aes256_cipher::Aes256Encryptor;
     34 pub use aes_cipher::AesEncryptor;
     35 pub use blowfish_cipher::BlowfishEncryptor;
     36 pub use camellia_cipher::CamelliaEncryptor;
     37 pub use chacha20_cipher::ChaCha20Encryptor;
     38 pub use twofish_cipher::TwofishEncryptor;
     39 pub use xor_cipher::XorEncryptor;
     40 
     41 /// Generic encryption/decryption interface
     42 pub trait Encryptor {
     43     /// Encrypts the given data using the configured key
     44     fn encrypt(&self, data: &[u8]) -> Result<Vec<u8>, String>;
     45 
     46     /// Decrypts the given data using the configured key
     47     #[allow(dead_code)]
     48     fn decrypt(&self, data: &[u8]) -> Result<Vec<u8>, String>;
     49 
     50     /// Returns the key size used by this encryptor
     51     #[allow(dead_code)]
     52     fn key_size(&self) -> usize;
     53 
     54     /// Returns the encryption algorithm name
     55     #[allow(dead_code)]
     56     fn algorithm_name(&self) -> &'static str;
     57 
     58     /// Returns the encryption type string used for code generation (e.g., "xor", "aes")
     59     fn encryption_type(&self) -> &'static str {
     60         match self.algorithm_name() {
     61             "XOR" => "xor",
     62             "AES-128-CBC" => "aes",
     63             "AES-256-CBC" => "aes256",
     64             "ChaCha20" => "chacha20",
     65             "Blowfish-CBC" => "blowfish",
     66             "Twofish-CBC" => "twofish",
     67             "Camellia-256-CBC" => "camellia",
     68             _ => "unknown",
     69         }
     70     }
     71 
     72     /// Returns whether this encryption method uses an IV/nonce
     73     #[allow(dead_code)]
     74     fn uses_iv(&self) -> bool {
     75         true // Most modern ciphers use IV/nonce
     76     }
     77 
     78     /// Generates the decryption function code for embedding in the target binary
     79     fn generate_decrypt_code(&self) -> &'static str;
     80 
     81     /// Generates the decryption template code (the actual call to decrypt)
     82     fn generate_decrypt_template(&self) -> String {
     83         let encryption_type = self.encryption_type();
     84         match encryption_type {
     85             "xor" => r#"
     86     let decrypted = internals::decrypt_xor(ENCRYPTED_SHELLCODE, &DECRYPTION_KEY);
     87 "#
     88             .to_string(),
     89             _ => {
     90                 format!(
     91                     r#"
     92     let decrypted = internals::decrypt_{}(ENCRYPTED_SHELLCODE, &DECRYPTION_KEY)
     93         .expect("Failed to decrypt");
     94 "#,
     95                     encryption_type
     96                 )
     97             }
     98         }
     99     }
    100 
    101     /// Returns the required Cargo dependencies for this encryption algorithm
    102     #[allow(dead_code)]
    103     fn required_dependencies(&self) -> Vec<(&'static str, &'static str)> {
    104         vec![] // Default: no additional dependencies
    105     }
    106 
    107     /// Returns the key size in bytes required by this algorithm
    108     #[allow(dead_code)]
    109     fn key_size_bytes(&self) -> usize {
    110         self.key_size()
    111     }
    112 }
    113 
    114 /// Creates an encryptor based on the encryption kind and key
    115 pub fn create_encryptor(kind: EncryptionKind, key: &str) -> Box<dyn Encryptor> {
    116     match kind {
    117         EncryptionKind::AES => Box::new(AesEncryptor::new(key)),
    118         EncryptionKind::AES256 => Box::new(Aes256Encryptor::new(key)),
    119         EncryptionKind::Chacha20 => Box::new(ChaCha20Encryptor::new(key)),
    120         EncryptionKind::XOR => Box::new(XorEncryptor::new(key)),
    121         EncryptionKind::Blowfish => Box::new(BlowfishEncryptor::new(key)),
    122         EncryptionKind::Twofish => Box::new(TwofishEncryptor::new(key)),
    123         EncryptionKind::Camellia => Box::new(CamelliaEncryptor::new(key)),
    124     }
    125 }
    126 
    127 pub fn derive_key_bytes(key: &str, kind: &EncryptionKind) -> Vec<u8> {
    128     match kind {
    129         EncryptionKind::XOR => key.as_bytes().to_vec(),
    130         EncryptionKind::AES => {
    131             let mut hasher = Sha256::new();
    132             hasher.update(key.as_bytes());
    133             let hash = hasher.finalize();
    134             hash[..16].to_vec()
    135         }
    136         EncryptionKind::AES256
    137         | EncryptionKind::Chacha20
    138         | EncryptionKind::Twofish
    139         | EncryptionKind::Camellia => {
    140             let mut hasher = Sha256::new();
    141             hasher.update(key.as_bytes());
    142             let hash = hasher.finalize();
    143             hash.to_vec()
    144         }
    145         EncryptionKind::Blowfish => {
    146             let key_data = key.as_bytes();
    147             if key_data.len() < 4 {
    148                 let mut padded = key_data.to_vec();
    149                 while padded.len() < 4 {
    150                     padded.push(0);
    151                 }
    152                 padded
    153             } else if key_data.len() > 56 {
    154                 key_data[..56].to_vec()
    155             } else {
    156                 key_data.to_vec()
    157             }
    158         }
    159     }
    160 }
    161 
    162 #[cfg(test)]
    163 mod tests {
    164     use super::*;
    165 
    166     #[test]
    167     fn test_create_encryptor_aes() {
    168         let encryptor = create_encryptor(EncryptionKind::AES, "test-key-123456");
    169         let data = b"Hello, World!";
    170         let encrypted = encryptor.encrypt(data).unwrap();
    171         assert_ne!(encrypted, data);
    172         let decrypted = encryptor.decrypt(&encrypted).unwrap();
    173         assert_eq!(decrypted, data);
    174     }
    175 
    176     #[test]
    177     fn test_create_encryptor_chacha20() {
    178         let encryptor = create_encryptor(EncryptionKind::Chacha20, "test-key-123456");
    179         let data = b"Hello, World!";
    180         let encrypted = encryptor.encrypt(data).unwrap();
    181         assert_ne!(encrypted, data);
    182         let decrypted = encryptor.decrypt(&encrypted).unwrap();
    183         assert_eq!(decrypted, data);
    184     }
    185 
    186     #[test]
    187     fn test_create_encryptor_xor() {
    188         let encryptor = create_encryptor(EncryptionKind::XOR, "test-key-123456");
    189         let data = b"Hello, World!";
    190         let encrypted = encryptor.encrypt(data).unwrap();
    191         assert_ne!(encrypted, data);
    192         let decrypted = encryptor.decrypt(&encrypted).unwrap();
    193         assert_eq!(decrypted, data);
    194     }
    195 
    196     #[test]
    197     fn test_create_encryptor_blowfish() {
    198         let encryptor = create_encryptor(EncryptionKind::Blowfish, "test-key-123456");
    199         let data = b"Hello, World!";
    200         let encrypted = encryptor.encrypt(data).unwrap();
    201         assert_ne!(encrypted, data);
    202         let decrypted = encryptor.decrypt(&encrypted).unwrap();
    203         assert_eq!(decrypted, data);
    204     }
    205 
    206     #[test]
    207     fn test_create_encryptor_aes256() {
    208         let encryptor = create_encryptor(EncryptionKind::AES256, "test-key-123456");
    209         let data = b"Hello, World!";
    210         let encrypted = encryptor.encrypt(data).unwrap();
    211         assert_ne!(encrypted, data);
    212         let decrypted = encryptor.decrypt(&encrypted).unwrap();
    213         assert_eq!(decrypted, data);
    214     }
    215 
    216     #[test]
    217     fn test_create_encryptor_twofish() {
    218         let encryptor = create_encryptor(EncryptionKind::Twofish, "test-key-123456");
    219         let data = b"Hello, World!";
    220         let encrypted = encryptor.encrypt(data).unwrap();
    221         assert_ne!(encrypted, data);
    222         let decrypted = encryptor.decrypt(&encrypted).unwrap();
    223         assert_eq!(decrypted, data);
    224     }
    225 
    226     #[test]
    227     fn test_create_encryptor_camellia() {
    228         let encryptor = create_encryptor(EncryptionKind::Camellia, "test-key-123456");
    229         let data = b"Hello, World!";
    230         let encrypted = encryptor.encrypt(data).unwrap();
    231         assert_ne!(encrypted, data);
    232         let decrypted = encryptor.decrypt(&encrypted).unwrap();
    233         assert_eq!(decrypted, data);
    234     }
    235 
    236     #[test]
    237     fn test_generate_decrypt_code_xor() {
    238         let encryptor = create_encryptor(EncryptionKind::XOR, "test-key");
    239         let code = encryptor.generate_decrypt_code();
    240         assert!(code.contains("decrypt_xor"));
    241         assert!(code.contains("xor_bytes"));
    242     }
    243 
    244     #[test]
    245     fn test_generate_decrypt_code_aes() {
    246         let encryptor = create_encryptor(EncryptionKind::AES, "test-key");
    247         let code = encryptor.generate_decrypt_code();
    248         assert!(code.contains("decrypt_aes"));
    249         assert!(code.contains("AES-128"));
    250     }
    251 
    252     #[test]
    253     fn test_generate_decrypt_code_chacha20() {
    254         let encryptor = create_encryptor(EncryptionKind::Chacha20, "test-key");
    255         let code = encryptor.generate_decrypt_code();
    256         assert!(code.contains("decrypt_chacha20"));
    257         assert!(code.contains("ChaCha20"));
    258     }
    259 
    260     #[test]
    261     fn test_generate_decrypt_template_xor() {
    262         let encryptor = create_encryptor(EncryptionKind::XOR, "test-key");
    263         let template = encryptor.generate_decrypt_template();
    264         assert!(template.contains("internals::decrypt_xor"));
    265         assert!(template.contains("ENCRYPTED_SHELLCODE"));
    266         assert!(template.contains("DECRYPTION_KEY"));
    267     }
    268 
    269     #[test]
    270     fn test_generate_decrypt_template_aes() {
    271         let encryptor = create_encryptor(EncryptionKind::AES, "test-key");
    272         let template = encryptor.generate_decrypt_template();
    273         assert!(template.contains("internals::decrypt_aes"));
    274         assert!(template.contains("ENCRYPTED_SHELLCODE"));
    275         assert!(template.contains("expect"));
    276     }
    277 
    278     #[test]
    279     fn test_required_dependencies_aes() {
    280         let encryptor = create_encryptor(EncryptionKind::AES, "test-key");
    281         let deps = encryptor.required_dependencies();
    282         assert!(deps.len() >= 2);
    283         assert!(deps.iter().any(|(name, _)| *name == "aes"));
    284         assert!(deps.iter().any(|(name, _)| *name == "cbc"));
    285     }
    286 
    287     #[test]
    288     fn test_required_dependencies_chacha20() {
    289         let encryptor = create_encryptor(EncryptionKind::Chacha20, "test-key");
    290         let deps = encryptor.required_dependencies();
    291         assert!(deps.iter().any(|(name, _)| *name == "chacha20"));
    292     }
    293 
    294     #[test]
    295     fn test_key_size_bytes() {
    296         let xor_encryptor = create_encryptor(EncryptionKind::XOR, "test");
    297         assert_eq!(xor_encryptor.key_size_bytes(), 4);
    298 
    299         let aes_encryptor = create_encryptor(EncryptionKind::AES, "test-key");
    300         assert_eq!(aes_encryptor.key_size_bytes(), 16);
    301 
    302         let aes256_encryptor = create_encryptor(EncryptionKind::AES256, "test-key");
    303         assert_eq!(aes256_encryptor.key_size_bytes(), 32);
    304 
    305         let chacha20_encryptor = create_encryptor(EncryptionKind::Chacha20, "test-key");
    306         assert_eq!(chacha20_encryptor.key_size_bytes(), 32);
    307     }
    308 }