-
-
Notifications
You must be signed in to change notification settings - Fork 111
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
a02c978
commit 845d8fa
Showing
7 changed files
with
109 additions
and
92 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,85 +1,89 @@ | ||
use fmtools::format; // using obfstr to obfuscate | ||
use std::ffi::c_void; | ||
use std::mem::{size_of, zeroed}; | ||
use std::ptr::null_mut; | ||
use widestring::u16cstr; | ||
use windows_sys::Win32::Foundation::{CloseHandle, HANDLE, INVALID_HANDLE_VALUE}; | ||
use windows_sys::Win32::Storage::FileSystem::{ | ||
CreateFileW, SetFileInformationByHandle, FILE_ATTRIBUTE_NORMAL, FILE_DISPOSITION_FLAG_DELETE, | ||
FILE_DISPOSITION_INFO, FILE_RENAME_INFO, OPEN_EXISTING, | ||
// Base code adapted from RustRedOps by joaoviictorti under MIT License | ||
// https://github.com/joaoviictorti/RustRedOps/tree/main/Self_Deletion | ||
|
||
use std::{ | ||
ffi::c_void, | ||
mem::{size_of, size_of_val}, | ||
}; | ||
use windows::core::PCWSTR; | ||
use windows::Win32::{ | ||
Foundation::CloseHandle, | ||
Storage::FileSystem::{CreateFileW, SetFileInformationByHandle, FILE_RENAME_INFO}, | ||
Storage::FileSystem::{ | ||
FileDispositionInfo, FileRenameInfo, DELETE, FILE_DISPOSITION_INFO, | ||
FILE_FLAGS_AND_ATTRIBUTES, FILE_SHARE_READ, OPEN_EXISTING, SYNCHRONIZE, | ||
}, | ||
System::Memory::{GetProcessHeap, HeapAlloc, HeapFree, HEAP_ZERO_MEMORY}, | ||
}; | ||
use windows_sys::Win32::System::LibraryLoader::GetModuleFileNameW; | ||
|
||
unsafe fn open_handle(path: &[u16]) -> HANDLE { | ||
CreateFileW( | ||
path.as_ptr(), | ||
0x00010000, // DELETE | ||
0, | ||
null_mut(), | ||
OPEN_EXISTING, | ||
FILE_ATTRIBUTE_NORMAL, | ||
null_mut() as isize, | ||
) | ||
} | ||
pub(crate) fn perform() -> Result<(), Box<dyn std::error::Error>> { | ||
let stream = ":nimpln"; | ||
let stream_wide: Vec<u16> = stream.encode_utf16().chain(std::iter::once(0)).collect(); | ||
|
||
unsafe fn rename_handle(handle: HANDLE) -> bool { | ||
let stream_rename = format!(":nimpln"); | ||
let ds_stream_rename = u16cstr!(&stream_rename).unwrap().as_ptr(); | ||
let mut rename_info: FILE_RENAME_INFO = zeroed(); | ||
rename_info.FileNameLength = (size_of_val(&ds_stream_rename) - size_of::<u16>()) as u32; // Exclude null terminator | ||
rename_info.FileName.copy_from( | ||
ds_stream_rename, | ||
rename_info.FileNameLength as usize / size_of::<u16>(), | ||
); | ||
SetFileInformationByHandle( | ||
handle, | ||
10, /* FileRenameInfo */ | ||
&mut rename_info as *mut _ as *mut c_void, | ||
size_of::<FILE_RENAME_INFO>() as u32 + rename_info.FileNameLength, | ||
) != 0 | ||
} | ||
unsafe { | ||
let mut delete_file = FILE_DISPOSITION_INFO::default(); | ||
let lenght = size_of::<FILE_RENAME_INFO>() + (stream_wide.len() * size_of::<u16>()); | ||
let rename_info = | ||
HeapAlloc(GetProcessHeap()?, HEAP_ZERO_MEMORY, lenght).cast::<FILE_RENAME_INFO>(); | ||
|
||
unsafe fn mark_for_deletion(handle: HANDLE) -> bool { | ||
let mut delete_info: FILE_DISPOSITION_INFO = zeroed(); | ||
delete_info.DeleteFile = FILE_DISPOSITION_FLAG_DELETE as u32; | ||
SetFileInformationByHandle( | ||
handle, | ||
4, /* FileDispositionInfo */ | ||
&mut delete_info as *mut _ as *mut c_void, | ||
size_of::<FILE_DISPOSITION_INFO>() as u32, | ||
) != 0 | ||
} | ||
delete_file.DeleteFile = true.into(); | ||
(*rename_info).FileNameLength = (stream_wide.len() * size_of::<u16>()) as u32 - 2; | ||
|
||
pub fn perform_self_delete() -> Result<(), Box<dyn std::error::Error>> { | ||
let mut path: [u16; 261] = [0; 261]; // MAX_PATH + 1 | ||
unsafe { | ||
if GetModuleFileNameW(null_mut(), path.as_mut_ptr(), path.len() as u32) == 0 { | ||
return Err(format!("Failed to get the current module file name").into()); | ||
} | ||
} | ||
std::ptr::copy_nonoverlapping( | ||
stream_wide.as_ptr(), | ||
(*rename_info).FileName.as_mut_ptr(), | ||
stream_wide.len(), | ||
); | ||
|
||
let handle = unsafe { open_handle(&path) }; | ||
if handle == INVALID_HANDLE_VALUE { | ||
return Err(format!("Failed to acquire handle to current running process").into()); | ||
} | ||
let path = std::env::current_exe()?; | ||
let path_str = path.to_str().unwrap_or(""); | ||
let mut full_path: Vec<u16> = path_str.encode_utf16().collect(); | ||
full_path.push(0); | ||
|
||
if !unsafe { rename_handle(handle) } { | ||
unsafe { CloseHandle(handle) }; | ||
return Err(format!("Failed to rename the file").into()); | ||
} | ||
let mut h_file = CreateFileW( | ||
PCWSTR(full_path.as_ptr()), | ||
DELETE.0 | SYNCHRONIZE.0, | ||
FILE_SHARE_READ, | ||
None, | ||
OPEN_EXISTING, | ||
FILE_FLAGS_AND_ATTRIBUTES(0), | ||
None, | ||
)?; | ||
|
||
unsafe { CloseHandle(handle) }; | ||
SetFileInformationByHandle( | ||
h_file, | ||
FileRenameInfo, | ||
rename_info as *const c_void, | ||
lenght as u32, | ||
)?; | ||
|
||
let handle = unsafe { open_handle(&path) }; | ||
if handle == INVALID_HANDLE_VALUE { | ||
return Err(format!("Failed to reopen current module").into()); | ||
} | ||
CloseHandle(h_file)?; | ||
|
||
if !unsafe { mark_for_deletion(handle) } { | ||
unsafe { CloseHandle(handle) }; | ||
return Err(format!("Failed to mark the file for deletion").into()); | ||
} | ||
h_file = CreateFileW( | ||
PCWSTR(full_path.as_ptr()), | ||
DELETE.0 | SYNCHRONIZE.0, | ||
FILE_SHARE_READ, | ||
None, | ||
OPEN_EXISTING, | ||
FILE_FLAGS_AND_ATTRIBUTES(0), | ||
None, | ||
)?; | ||
|
||
unsafe { CloseHandle(handle) }; | ||
Ok(()) | ||
SetFileInformationByHandle( | ||
h_file, | ||
FileDispositionInfo, | ||
std::ptr::from_ref::<FILE_DISPOSITION_INFO>(&delete_file).cast(), | ||
size_of_val(&delete_file) as u32, | ||
)?; | ||
|
||
CloseHandle(h_file)?; | ||
|
||
HeapFree( | ||
GetProcessHeap()?, | ||
HEAP_ZERO_MEMORY, | ||
Some(rename_info as *const c_void), | ||
)?; | ||
|
||
Ok(()) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters