dinvk/
macros.rs

1/// Macro to dynamically invoke a function from a specified module.
2/// 
3/// # Example
4/// 
5/// ```
6/// let ntdll = get_ntdll_address();
7/// let result = dinvoke!(ntdll, "NtQueryInformationProcess", extern "system" fn(...) -> u32, ...);
8/// ``` 
9#[macro_export]
10macro_rules! dinvoke {
11    ($module:expr, $function:expr, $ty:ty, $($arg:expr),*) => {{
12        // Get the address of the function in the specified module
13        let address = $crate::module::get_proc_address($module, $function, None);
14        if address.is_null() {
15            None
16        } else {
17            // Transmute the function pointer to the desired type and invoke it with the provided arguments
18            let func = unsafe { core::mem::transmute::<*mut core::ffi::c_void, $ty>(address) };
19            Some(unsafe { func($($arg),*) })
20        }
21    }};
22}
23
24/// Macro to perform a system call (syscall) by dynamically resolving its function name.
25///
26/// # Example
27///
28/// ```
29/// let mut addr = null_mut::<c_void>();
30/// let mut size = (1 << 12) as usize;
31/// let status = syscall!("NtAllocateVirtualMemory", -1isize as HANDLE, &mut addr, 0, &mut size, 0x3000, 0x04)
32///    .ok_or("syscall resolution failed")?;
33///
34/// if !NT_SUCCESS(status) {
35///     eprintln!("[-] NtAllocateVirtualMemory Failed With Status: {}", status);
36/// }
37/// ```
38#[macro_export]
39#[cfg(any(target_arch = "x86_64", target_arch = "x86"))]
40macro_rules! syscall {
41    ($function_name:expr, $($y:expr), +) => {{
42        // Retrieve the address of ntdll.dll
43        let ntdll = $crate::module::get_ntdll_address();
44
45        // Get the address of the specified function in ntdll.dll
46        let addr = $crate::module::get_proc_address(ntdll, $function_name, None);
47        if addr.is_null() {
48            None
49        } else {
50            // Retrieve the SSN for the target function
51            match $crate::ssn($function_name, ntdll) {
52                None => None,
53                Some(ssn) => {
54                    // Calculate the syscall address
55                    match $crate::get_syscall_address(addr) {
56                        None => None,
57                        Some(syscall_addr) => {
58                            // Count number of args
59                            let cnt = 0u32 $(+ { let _ = &$y; 1u32 })+;
60                            
61                            // Execute syscall
62                            Some(unsafe { $crate::asm::do_syscall(ssn, syscall_addr, cnt, $($y),+) })
63                        }
64                    }
65                }
66            }
67        }
68    }};
69}
70
71/// Prints output to the Windows console.
72#[macro_export]
73macro_rules! println {
74    ($($arg:tt)*) => {{
75        use core::fmt::Write;
76        
77        let mut console = $crate::console::ConsoleWriter;
78        let _ = writeln!(console, $($arg)*);
79    }};
80}