Personal commit
This commit is contained in:
@@ -0,0 +1,128 @@
|
||||
#![no_std]
|
||||
#![feature(core_intrinsics)]
|
||||
#![allow(internal_features)]
|
||||
#![allow(unused_imports)]
|
||||
|
||||
use core::{arch::asm, ffi::CStr, intrinsics, slice};
|
||||
use windows_sys::{
|
||||
core::PCSTR,
|
||||
Win32::{
|
||||
Foundation::{HMODULE, UNICODE_STRING},
|
||||
System::{
|
||||
Diagnostics::Debug::{
|
||||
IMAGE_DIRECTORY_ENTRY_EXPORT, IMAGE_NT_HEADERS32, IMAGE_NT_HEADERS64,
|
||||
},
|
||||
SystemServices::{IMAGE_DOS_HEADER, IMAGE_EXPORT_DIRECTORY},
|
||||
Threading::TEB,
|
||||
WindowsProgramming::LDR_DATA_TABLE_ENTRY,
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
pub unsafe fn get_module_handle_from_peb(module_name: &[u16]) -> Option<HMODULE> {
|
||||
// Start at the top boys
|
||||
let mut teb: *mut TEB;
|
||||
#[cfg(target_arch = "x86")]
|
||||
asm!(
|
||||
"mov {}, fs:[0x18]",
|
||||
out(reg) teb
|
||||
);
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
asm!(
|
||||
"mov {}, gs:[0x30]",
|
||||
out(reg) teb
|
||||
);
|
||||
|
||||
// I will dereference every pointer
|
||||
let teb = *teb;
|
||||
let peb = *(teb.ProcessEnvironmentBlock);
|
||||
let ldr_data = *(peb.Ldr);
|
||||
|
||||
// Hidden fields of PEB_LDR_DATA and LDR_DATA_TABLE_ENTRY abound
|
||||
// Reserved2[0] = SsHandle, Reserved[1] = InLoadOrderLinks.Flink, Reserved[2] = InLoadOrderLinks.Blink
|
||||
let mut module_list = *(ldr_data.Reserved2[1] as *mut LDR_DATA_TABLE_ENTRY);
|
||||
|
||||
while !module_list.DllBase.is_null() {
|
||||
// BaseDllName
|
||||
let base_dll_name = *(module_list.Reserved4.as_ptr() as *mut UNICODE_STRING);
|
||||
let base_dll_name = slice::from_raw_parts(
|
||||
base_dll_name.Buffer,
|
||||
base_dll_name.Length as usize / size_of::<u16>(),
|
||||
);
|
||||
|
||||
if module_name == base_dll_name {
|
||||
return Some(module_list.DllBase as HMODULE);
|
||||
}
|
||||
|
||||
// Reserved1[0] = InLoadOrderLinks.Flink, Reserved1[1] = InLoadOrderLinks.Blink
|
||||
module_list = *(module_list.Reserved1[0] as *mut LDR_DATA_TABLE_ENTRY);
|
||||
}
|
||||
None
|
||||
}
|
||||
|
||||
pub unsafe fn get_procedure_from_edt<F>(module: HMODULE, proc_name: &str) -> Option<F> {
|
||||
let module = module as usize;
|
||||
let proc_name = CStr::from_ptr(proc_name.as_ptr() as *const _);
|
||||
|
||||
let dos_headers = *(module as *const IMAGE_DOS_HEADER);
|
||||
|
||||
#[cfg(target_arch = "x86")]
|
||||
let nt_headers = *((module + dos_headers.e_lfanew as usize) as *const IMAGE_NT_HEADERS32);
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
let nt_headers = *((module + dos_headers.e_lfanew as usize) as *const IMAGE_NT_HEADERS64);
|
||||
|
||||
let export_directory = *((module
|
||||
+ nt_headers.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT as usize]
|
||||
.VirtualAddress as usize)
|
||||
as *const IMAGE_EXPORT_DIRECTORY);
|
||||
|
||||
let functions_table_ptr =
|
||||
(module + export_directory.AddressOfFunctions as usize) as *const usize;
|
||||
let names_table_ptr = (module + export_directory.AddressOfNames as usize) as *const usize;
|
||||
let ordinals_table_ptr =
|
||||
(module + export_directory.AddressOfNameOrdinals as usize) as *const u16;
|
||||
|
||||
let functions_table = slice::from_raw_parts(
|
||||
functions_table_ptr,
|
||||
export_directory.NumberOfFunctions as usize,
|
||||
);
|
||||
let names_table =
|
||||
slice::from_raw_parts(names_table_ptr, export_directory.NumberOfNames as usize);
|
||||
let ordinals_table =
|
||||
slice::from_raw_parts(ordinals_table_ptr, export_directory.NumberOfNames as usize);
|
||||
|
||||
for i in 0..names_table.len() {
|
||||
let name = CStr::from_ptr((module + names_table[i]) as *const _);
|
||||
let ordinal = ordinals_table[i];
|
||||
let address = functions_table[ordinal as usize];
|
||||
|
||||
if name == proc_name {
|
||||
return Some(intrinsics::transmute_unchecked(module + address));
|
||||
}
|
||||
}
|
||||
None
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
use utf16_lit::utf16;
|
||||
|
||||
fn get_module_test() {
|
||||
let module = unsafe { get_module_handle_from_peb(&utf16!("KERNEL32.DLL")) };
|
||||
assert!(!module.is_some());
|
||||
}
|
||||
|
||||
fn get_procedure_test() {
|
||||
let module = unsafe { get_module_handle_from_peb(&utf16!("KERNEL32.DLL")) };
|
||||
assert!(module.is_some());
|
||||
|
||||
let procedure = unsafe {
|
||||
get_procedure_from_edt::<extern "system" fn() -> u32>(module.unwrap(), "GetProcessId\0")
|
||||
};
|
||||
assert!(procedure.is_some());
|
||||
|
||||
let procedure = procedure.unwrap();
|
||||
assert_ne!(procedure(), 0)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user