1use crate::data::*;
2use obfstr::obfstr as s;
3use core::ffi::c_void;
4use crate::{
5 GetModuleHandle,
6 dinvoke, get_ntdll_address,
7};
8
9#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
10use crate::breakpoint::{
11 is_breakpoint_enabled,
12 set_breakpoint,
13 WINAPI, CURRENT_API
14};
15
16pub fn LoadLibraryA(module: &str) -> *mut c_void {
18 let name = alloc::format!("{}\0", module);
19 let kernel32 = GetModuleHandle(s!("KERNEL32.DLL"), None);
20 dinvoke!(
21 kernel32,
22 s!("LoadLibraryA"),
23 LoadLibraryA,
24 name.as_ptr()
25 )
26 .unwrap_or(core::ptr::null_mut())
27}
28
29#[allow(unused_mut)]
31pub fn NtAllocateVirtualMemory(
32 mut process_handle: HANDLE,
33 base_address: *mut *mut c_void,
34 zero_bits: usize,
35 region_size: *mut usize,
36 allocation_type: u32,
37 mut protect: u32,
38) -> NTSTATUS {
39 let ntdll = get_ntdll_address();
41
42 cfg_if::cfg_if! {
43 if #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] {
44 if is_breakpoint_enabled() {
46 unsafe {
47 CURRENT_API = Some(WINAPI::NtAllocateVirtualMemory {
48 ProcessHandle: process_handle,
49 Protect: protect,
50 });
51 }
52
53 protect = 0x02;
56
57 process_handle = -23isize as HANDLE;
59
60 let addr = crate::GetProcAddress(ntdll, s!("NtAllocateVirtualMemory"), None);
62 if let Some(syscall_addr) = crate::get_syscall_address(addr) {
63 set_breakpoint(syscall_addr);
64 }
65 }
66 }
67 }
68
69 dinvoke!(
70 ntdll,
71 s!("NtAllocateVirtualMemory"),
72 NtAllocateVirtualMemory,
73 process_handle,
74 base_address,
75 zero_bits,
76 region_size,
77 allocation_type,
78 protect
79 )
80 .unwrap_or(STATUS_UNSUCCESSFUL)
81}
82
83#[allow(unused_mut)]
85pub fn NtProtectVirtualMemory(
86 mut process_handle: *mut c_void,
87 base_address: *mut *mut c_void,
88 region_size: *mut usize,
89 mut new_protect: u32,
90 old_protect: *mut u32,
91) -> NTSTATUS {
92 let ntdll = get_ntdll_address();
94
95 cfg_if::cfg_if! {
96 if #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] {
97 if is_breakpoint_enabled() {
99 unsafe {
100 CURRENT_API = Some(WINAPI::NtProtectVirtualMemory {
101 ProcessHandle: process_handle,
102 NewProtect: new_protect,
103 });
104 }
105
106 new_protect = 0x02;
108
109 process_handle = -23isize as HANDLE;
111
112 let addr = crate::GetProcAddress(ntdll, s!("NtProtectVirtualMemory"), None);
114 if let Some(syscall_addr) = crate::get_syscall_address(addr) {
115 set_breakpoint(syscall_addr);
116 }
117 }
118 }
119 }
120
121 dinvoke!(
122 ntdll,
123 s!("NtProtectVirtualMemory"),
124 NtProtectVirtualMemory,
125 process_handle,
126 base_address,
127 region_size,
128 new_protect,
129 old_protect
130 )
131 .unwrap_or(STATUS_UNSUCCESSFUL)
132}
133
134#[allow(unused_mut)]
136pub fn NtCreateThreadEx(
137 mut thread_handle: *mut HANDLE,
138 mut desired_access: u32,
139 mut object_attributes: *mut OBJECT_ATTRIBUTES,
140 mut process_handle: HANDLE,
141 start_routine: *mut c_void,
142 argument: *mut c_void,
143 create_flags: u32,
144 zero_bits: usize,
145 stack_size: usize,
146 maximum_stack_size: usize,
147 attribute_list: *mut PS_ATTRIBUTE_LIST
148) -> NTSTATUS {
149 let ntdll = get_ntdll_address();
151
152 cfg_if::cfg_if! {
153 if #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] {
154 if is_breakpoint_enabled() {
156 unsafe {
157 CURRENT_API = Some(WINAPI::NtCreateThreadEx {
158 ProcessHandle: process_handle,
159 ThreadHandle: thread_handle,
160 DesiredAccess: desired_access,
161 ObjectAttributes: object_attributes
162 });
163 }
164
165 process_handle = -12isize as HANDLE;
167 thread_handle = -43isize as *mut HANDLE;
168
169 desired_access = 0x80;
171
172 object_attributes = alloc::boxed::Box::leak(alloc::boxed::Box::new(OBJECT_ATTRIBUTES::default()));
174
175 let addr = crate::GetProcAddress(ntdll, s!("NtCreateThreadEx"), None);
177 if let Some(addr) = crate::get_syscall_address(addr) {
178 set_breakpoint(addr);
179 }
180 }
181 }
182 }
183
184 dinvoke!(
185 ntdll,
186 s!("NtCreateThreadEx"),
187 NtCreateThreadEx,
188 thread_handle,
189 desired_access,
190 object_attributes,
191 process_handle,
192 start_routine,
193 argument,
194 create_flags,
195 zero_bits,
196 stack_size,
197 maximum_stack_size,
198 attribute_list
199 )
200 .unwrap_or(STATUS_UNSUCCESSFUL)
201}
202
203#[allow(unused_mut)]
205pub fn NtWriteVirtualMemory(
206 mut process_handle: HANDLE,
207 base_address: *mut c_void,
208 mut buffer: *mut c_void,
209 mut number_of_bytes_to_write: usize,
210 number_of_bytes_written: *mut usize,
211) -> NTSTATUS {
212 let ntdll = get_ntdll_address();
214
215 cfg_if::cfg_if! {
216 if #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] {
217 if is_breakpoint_enabled() {
219 unsafe {
220 CURRENT_API = Some(WINAPI::NtWriteVirtualMemory {
221 ProcessHandle: process_handle,
222 Buffer: buffer,
223 NumberOfBytesToWrite: number_of_bytes_written
224 });
225 }
226
227 process_handle = -90isize as HANDLE;
229
230 let temp = [0u8; 10];
232 buffer = temp.as_ptr().cast_mut().cast();
233 number_of_bytes_to_write = temp.len();
234
235 let addr = crate::GetProcAddress(ntdll, s!("NtWriteVirtualMemory"), None);
237 if let Some(addr) = crate::get_syscall_address(addr) {
238 set_breakpoint(addr);
239 }
240 }
241 }
242 }
243
244 dinvoke!(
245 ntdll,
246 s!("NtWriteVirtualMemory"),
247 NtWriteVirtualMemory,
248 process_handle,
249 base_address,
250 buffer,
251 number_of_bytes_to_write,
252 number_of_bytes_written
253 )
254 .unwrap_or(STATUS_UNSUCCESSFUL)
255}
256
257pub fn HeapAlloc(
259 hheap: HANDLE,
260 dwflags: HEAP_FLAGS,
261 dwbytes: usize
262) -> *mut c_void {
263 let kernel32 = GetModuleHandle(s!("KERNEL32.DLL"), None);
264 dinvoke!(
265 kernel32,
266 s!("HeapAlloc"),
267 HeapAlloc,
268 hheap,
269 dwflags,
270 dwbytes
271 )
272 .unwrap_or(core::ptr::null_mut())
273}
274
275pub fn HeapFree(
277 hheap: HANDLE,
278 dwflags: HEAP_FLAGS,
279 lpmem: *const c_void,
280) -> *mut c_void {
281 let kernel32 = GetModuleHandle(s!("KERNEL32.DLL"), None);
282 dinvoke!(
283 kernel32,
284 s!("HeapFree"),
285 HeapFree,
286 hheap,
287 dwflags,
288 lpmem
289 )
290 .unwrap_or(core::ptr::null_mut())
291}
292
293pub fn HeapCreate(
295 floptions: HEAP_FLAGS,
296 dwinitialsize: usize,
297 dwmaximumsize: usize,
298) -> *mut c_void {
299 let kernel32 = GetModuleHandle(s!("KERNEL32.DLL"), None);
300 dinvoke!(
301 kernel32,
302 s!("HeapCreate"),
303 HeapCreate,
304 floptions,
305 dwinitialsize,
306 dwmaximumsize
307 )
308 .unwrap_or(core::ptr::null_mut())
309}
310
311pub fn AddVectoredExceptionHandler(
313 first: u32,
314 handler: PVECTORED_EXCEPTION_HANDLER,
315) -> *mut c_void {
316 let kernel32 = GetModuleHandle(s!("KERNEL32.DLL"), None);
317 dinvoke!(
318 kernel32,
319 s!("AddVectoredExceptionHandler"),
320 AddVectoredExceptionHandler,
321 first,
322 handler
323 )
324 .unwrap_or(core::ptr::null_mut())
325}
326
327pub fn RemoveVectoredExceptionHandler(
329 handle: *mut c_void,
330) -> u32 {
331 let kernel32 = GetModuleHandle(s!("KERNEL32.DLL"), None);
332 dinvoke!(
333 kernel32,
334 s!("RemoveVectoredExceptionHandler"),
335 RemoveVectoredExceptionHandler,
336 handle
337 )
338 .unwrap_or(0)
339}
340
341pub fn GetThreadContext(
343 hthread: HANDLE,
344 lpcontext: *mut CONTEXT,
345) -> i32 {
346 let kernel32 = GetModuleHandle(s!("KERNEL32.DLL"), None);
347 dinvoke!(
348 kernel32,
349 s!("GetThreadContext"),
350 GetThreadContext,
351 hthread,
352 lpcontext
353 )
354 .unwrap_or(0)
355}
356
357pub fn SetThreadContext(
359 hthread: HANDLE,
360 lpcontext: *const CONTEXT,
361) -> i32 {
362 let kernel32 = GetModuleHandle(s!("KERNEL32.DLL"), None);
363 dinvoke!(
364 kernel32,
365 s!("SetThreadContext"),
366 SetThreadContext,
367 hthread,
368 lpcontext
369 )
370 .unwrap_or(0)
371}
372
373pub fn GetStdHandle(nStdHandle: u32) -> HANDLE {
375 let kernel32 = GetModuleHandle(s!("KERNEL32.DLL"), None);
376 dinvoke!(
377 kernel32,
378 s!("GetStdHandle"),
379 GetStdHandle,
380 nStdHandle
381 )
382 .unwrap_or(core::ptr::null_mut())
383}