#![allow(non_camel_case_types)]
use core::ffi::c_void;
use core::ffi::CStr;
use core::arch::asm;
use crate::helper::JopcallError;
use crate::helper::UNICODE_STRING;
use crate::RUNTIME_HASHER;
pub unsafe fn get_dll_base_address(dll:u128)->Result<*const c_void, JopcallError>{
#[repr(C)]
#[derive(Clone, Copy, PartialEq, Debug)]
struct LIST_ENTRY<'a> {
pub flink: *mut LIST_ENTRY<'a>,
pub blink: *mut LIST_ENTRY<'a>,
}
let peb_address: *const *const c_void;
asm!("mov {}, gs:0x60", out(reg) peb_address);
let ldr_address: *const c_void = *(peb_address.cast::<u8>().offset(0x18) as *const *const c_void);
let in_memory_order_module_list: *const LIST_ENTRY = ldr_address.cast::<u8>().offset(0x20) as *const LIST_ENTRY;
let module_list: LIST_ENTRY = *in_memory_order_module_list;
let mut plink: LIST_ENTRY = *module_list.flink;
let guard: LIST_ENTRY = *module_list.flink;
let dll_base_address: *const c_void;
while *plink.flink != *guard.blink {
let clink = plink;
let entry = plink.flink as *const c_void;
let dllname:UNICODE_STRING = *(entry.cast::<u8>().offset(0x48) as *const UNICODE_STRING);
let length = dllname.length;
let wbuffer = core::slice::from_raw_parts(&*dllname.buffer, length as usize).iter().copied();
let mut buffer:[u8; 255] = core::mem::zeroed();
for (index, character) in core::char::decode_utf16(wbuffer).enumerate(){
match character {
Ok(x) => {
if x.is_ascii() && !x.is_control() && !x.is_ascii_whitespace() {
buffer[index] = x.to_ascii_lowercase() as u8
} else {
buffer[index] = 0x00;
break;
}},
Err(_) => continue,
}
}
let entry_name = match CStr::from_bytes_until_nul(&buffer){
Ok(x)=>x,
Err(_)=>continue,
};
if RUNTIME_HASHER(entry_name.to_str().unwrap()) == dll {
dll_base_address = *(entry.cast::<u8>().offset(0x20) as *const *const c_void);
return Ok(dll_base_address)
} else {
plink = *clink.flink;
continue
}
}
Err(JopcallError::DllNotFound)
}