use core::ffi::c_void;
use core::mem::size_of;
use core::slice;
use crate::types::{ImageDataDirectory, ImageRuntimeFunction, IMAGE_DIRECTORY_ENTRY_EXCEPTION};
pub unsafe fn runtime_function_table<'a>(
module_base: *mut c_void,
) -> Option<&'a [ImageRuntimeFunction]> {
let base = module_base as *const u8;
let nt_offset = *(base.add(0x3C) as *const i32);
if nt_offset <= 0 {
return None;
}
let nt_header = base.add(nt_offset as usize);
if *(nt_header as *const u32) != 0x0000_4550 {
return None;
}
let optional_header = nt_header.add(0x18);
let magic = *(optional_header as *const u16);
if magic != 0x020b {
return None;
}
let data_dirs_base = optional_header.add(0x70);
let dir_ptr = data_dirs_base
.add(IMAGE_DIRECTORY_ENTRY_EXCEPTION * size_of::<ImageDataDirectory>())
as *const ImageDataDirectory;
let dir = *dir_ptr;
if dir.VirtualAddress == 0 || dir.Size == 0 {
return None;
}
let table_addr = (module_base as usize + dir.VirtualAddress as usize) as *const ImageRuntimeFunction;
let count = dir.Size as usize / size_of::<ImageRuntimeFunction>();
Some(slice::from_raw_parts(table_addr, count))
}
pub fn function_by_rva<'a>(
table: &'a [ImageRuntimeFunction],
rva: u32,
) -> Option<&'a ImageRuntimeFunction> {
table.iter().find(|f| f.BeginAddress == rva)
}