stealth/
debug.rs

1use windows_sys::Win32::{
2    Foundation::{HANDLE, NTSTATUS},
3    System::Threading::{ProcessDebugPort, PROCESSINFOCLASS},
4};
5
6use crate::{
7    hash::fnv1a_ci,
8    import::{get_function, get_module},
9    peb::{
10        get_peb, FLG_HEAP_ENABLE_FREE_CHECK, FLG_HEAP_ENABLE_TAIL_CHECK,
11        FLG_HEAP_VALIDATE_PARAMETERS,
12    },
13};
14
15/// Checks the PEB if BeingDebugged is zero.
16///
17/// returns: bool
18#[inline(always)]
19pub fn check_being_debugged() -> bool {
20    get_peb().BeingDebugged == 0
21}
22
23/// Checks the PEB if NtGlobalFlag contains FLG_HEAP_ENABLE_TAIL_CHECK,
24/// FLG_HEAP_ENABLE_FREE_CHECK or FLG_HEAP_VALIDATE_PARAMETERS.
25///
26/// returns: bool
27#[inline(always)]
28pub fn check_nt_global_flag() -> bool {
29    get_peb().NtGlobalFlag
30        & (FLG_HEAP_ENABLE_TAIL_CHECK | FLG_HEAP_ENABLE_FREE_CHECK | FLG_HEAP_VALIDATE_PARAMETERS)
31        == 0
32}
33
34/// Checks if the DebugPort retrieved via syscall ZwQueryInformationProcess is
35/// zero.
36///
37/// returns: bool
38#[inline(always)]
39pub fn check_debug_port() -> bool {
40    type NtQueryInformationProcess = unsafe extern "system" fn(
41        HANDLE,
42        PROCESSINFOCLASS,
43        *mut std::ffi::c_void,
44        u32,
45        *mut u32,
46    ) -> NTSTATUS;
47
48    let mut debug_port = 0;
49    unsafe {
50        let nt_query_system_information: NtQueryInformationProcess = std::mem::transmute(
51            get_function(
52                get_module(fnv1a_ci(b"ntdll.dll")).unwrap(),
53                fnv1a_ci(b"NtQueryInformationProcess"),
54            )
55            .unwrap(),
56        );
57        if nt_query_system_information(
58            -1,
59            ProcessDebugPort,
60            &mut debug_port as *mut i32 as *mut _,
61            std::mem::size_of_val(&debug_port) as u32,
62            std::ptr::null_mut(),
63        ) == 0
64        {
65            return false;
66        }
67    }
68    debug_port == 0
69}