Skip to content

Commit cc97a6f

Browse files
committed
Fixed Self Deletion Using Alternate data stream
1 parent 83c0f26 commit cc97a6f

File tree

1 file changed

+85
-69
lines changed

1 file changed

+85
-69
lines changed

Malware_Tips/self_delete.rs

Lines changed: 85 additions & 69 deletions
Original file line numberDiff line numberDiff line change
@@ -8,118 +8,134 @@
88
99
*/
1010

11-
use std::env::current_exe;
12-
use std::mem::{size_of, size_of_val};
11+
/*
12+
Explanation:~
13+
* 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.
14+
* 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.
15+
* 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.
16+
17+
*/
18+
use std::ffi::OsString;
19+
use std::os::windows::ffi::OsStrExt;
1320
use std::ptr::null_mut;
1421
use winapi::ctypes::c_void;
15-
use winapi::um::errhandlingapi::GetLastError;
1622
use winapi::um::fileapi::{CreateFileW, SetFileInformationByHandle, FILE_RENAME_INFO};
1723
use winapi::um::handleapi::CloseHandle;
1824
use winapi::um::heapapi::HeapFree;
1925
use winapi::um::minwinbase::{FileDispositionInfo, FileRenameInfo};
20-
use winapi::um::winnt::HEAP_ZERO_MEMORY;
26+
use winapi::um::winbase::FILE_FLAG_DELETE_ON_CLOSE;
27+
use winapi::um::winnt::{FILE_ATTRIBUTE_NORMAL, HEAP_ZERO_MEMORY};
2128
use winapi::um::{fileapi::FILE_DISPOSITION_INFO, heapapi::{GetProcessHeap, HeapAlloc}};
22-
use winapi::um::handleapi::INVALID_HANDLE_VALUE;
23-
24-
macro_rules! okey {
25-
($msg:expr, $($arg:expr), *) => {
26-
println!("[+] {}",format!($msg, $($arg), *));
27-
}
28-
}
2929

30-
macro_rules! error {
31-
($msg:expr, $($arg:expr), *) => {
32-
println!("[!] {}",format!($msg, $($arg), *));
33-
println!("Exiting ...");
34-
std::process::exit(1);
35-
};
36-
}
30+
// macro_rules! okey {
31+
// ($msg:expr, $($arg:expr), *) => {
32+
// println!("[+] {}",format!($msg, $($arg), *));
33+
// }
34+
// }
3735

38-
pub const NULL: *mut c_void = 0 as *mut c_void;
36+
// macro_rules! error {
37+
// ($msg:expr, $($arg:expr), *) => {
38+
// println!("[!] {}",format!($msg, $($arg), *));
39+
// println!("Exiting ...");
40+
// std::process::exit(1);
41+
// };
42+
// }
3943

4044
fn main(){
41-
let stream = "let del this nerdy !";
42-
let stream_wide: Vec<u16> = stream.encode_utf16().chain(std::iter::once(0)).collect();
45+
// This stream name is for alternate stream.
46+
let stream = ":test_stream";
47+
let stream_wide: Vec<u16> = OsString::from(stream).encode_wide().chain(std::iter::once(0)).collect();
4348

4449
unsafe{
45-
let mut delete_file: FILE_DISPOSITION_INFO = std::mem::zeroed();
46-
delete_file.DeleteFile = true.into();
50+
let mut delete_file = FILE_DISPOSITION_INFO{
51+
DeleteFile: 1 // default value is 1
52+
};
4753

48-
let length = size_of::<FILE_RENAME_INFO>();
54+
let rename_info_size = std::mem::size_of::<FILE_RENAME_INFO>() + (stream_wide.len() * std::mem::size_of::<u16>());
55+
56+
// allocate memory for FILE_RENAME_INFO
57+
let rename_info = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, rename_info_size) as *mut FILE_RENAME_INFO;
4958

50-
let rename_info = HeapAlloc(
51-
GetProcessHeap(),
52-
HEAP_ZERO_MEMORY,
53-
length as usize
54-
) as *mut FILE_RENAME_INFO;
59+
if rename_info.is_null() {
60+
panic!("Memory allocation failed");
61+
}
5562

56-
(*rename_info).FileNameLength = (stream_wide.len() * size_of::<u16>()) as u32 - 2;
63+
delete_file.DeleteFile = 1;
64+
(*rename_info).FileNameLength = (stream_wide.len() * std::mem::size_of::<u16>()) as u32 - 2;
5765

5866
std::ptr::copy_nonoverlapping(
5967
stream_wide.as_ptr(),
60-
(*rename_info).FileName.as_mut_ptr(),
61-
stream_wide.len()
68+
(*rename_info).FileName.as_mut_ptr(),
69+
stream_wide.len(),
6270
);
6371

64-
let path = current_exe().unwrap();
65-
let path_str = path.to_str().unwrap();
66-
67-
let mut full_path: Vec<u16> = path_str.encode_utf16().collect();
72+
let path = std::env::current_exe().unwrap();
73+
let mut full_path: Vec<u16> = OsString::from(path).encode_wide().collect();
6874
full_path.push(0);
6975

70-
let h_file = CreateFileW(
76+
// Open the file with delete and synchronize permissions
77+
let handle = CreateFileW(
7178
full_path.as_ptr(),
72-
0x00010000 | 0x00100000,
79+
0x00010000 | 0x00100000,
7380
0x00000001,
74-
null_mut(),
75-
3 as u32,
76-
0,
81+
core::ptr::null_mut(),
82+
3, // OPEN_EXISTING
83+
0 as u32, // FILE_ATTRIBUTE_NORMAL
7784
null_mut(),
7885
);
7986

80-
if h_file == INVALID_HANDLE_VALUE {
81-
error!("CreateFileW Error: {:?}",GetLastError());
87+
if handle.is_null() {
88+
panic!("Failed to open file");
8289
}
8390

84-
okey!("CreateFileW Adr: {:?}",h_file);
85-
86-
SetFileInformationByHandle(
87-
h_file,
88-
FileRenameInfo,
89-
rename_info as *mut _,
90-
length as u32,
91+
// rename the alternate data stream
92+
let setfileinfohandle = SetFileInformationByHandle(
93+
handle,
94+
FileRenameInfo,
95+
rename_info as *mut c_void,
96+
rename_info_size as u32
9197
);
92-
93-
CloseHandle(h_file);
9498

95-
let h_file = CreateFileW(
99+
if setfileinfohandle == 0 {
100+
panic!("Failed to set file information for rename");
101+
}
102+
103+
CloseHandle(handle);
104+
105+
// Re-open the file with delete on close flag
106+
let handle = CreateFileW(
96107
full_path.as_ptr(),
97-
0x00010000 | 0x00100000,
108+
0x00010000 | 0x40000000 | 0x00100000,
98109
0x00000001,
99-
null_mut(),
100-
3 as u32,
101-
0,
110+
std::ptr::null_mut(),
111+
3,
112+
FILE_ATTRIBUTE_NORMAL | FILE_FLAG_DELETE_ON_CLOSE,
102113
null_mut(),
103114
);
104115

105-
if h_file == INVALID_HANDLE_VALUE {
106-
error!("CreateFileW Error2: {}",GetLastError());
116+
if handle == null_mut() {
117+
panic!("Failed to re-open file for deletion");
107118
}
108119

109-
SetFileInformationByHandle(
110-
h_file,
111-
FileDispositionInfo,
112-
&delete_file as *const _ as *mut _,
113-
size_of_val(&delete_file) as u32,
120+
// Mark the file for deletion
121+
let setfileinfo = SetFileInformationByHandle(
122+
handle,
123+
FileDispositionInfo,
124+
&delete_file as *const FILE_DISPOSITION_INFO as *mut c_void,
125+
std::mem::size_of::<FILE_DISPOSITION_INFO>() as u32
114126
);
115127

116-
CloseHandle(h_file);
128+
if setfileinfo == 0 {
129+
panic!("Failed to mark file for deletion");
130+
}
131+
132+
CloseHandle(handle); // This will delete the file
117133

134+
// free the allocated memory
118135
HeapFree(
119-
GetProcessHeap(),
120-
0,
136+
GetProcessHeap(),
137+
0,
121138
rename_info as *mut c_void,
122139
);
123140
}
124-
}
125-
141+
}

0 commit comments

Comments
 (0)