v0.0.0b
This commit is contained in:
35
sub/winu/src/importer.rs
Normal file
35
sub/winu/src/importer.rs
Normal file
@@ -0,0 +1,35 @@
|
||||
use sub_core::fnv1;
|
||||
|
||||
#[inline(always)]
|
||||
pub unsafe fn find_import_hashed(module_name: u64, func_name: u64) -> Option<usize> {
|
||||
crate::modules::loaded_modules()
|
||||
.filter( |&(_,slice)|fnv1::hash_utf16(slice) == module_name).next()
|
||||
.and_then(|(i,_)|i.exports())
|
||||
.and_then(|v|{
|
||||
v.filter_map(|(p,n)|(fnv1::hash_utf8(n) == func_name).then_some(p)).next()
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
|
||||
pub macro lazy_import ( $module:literal $($v:vis fn $name:ident($($pname:ident: $ptype:ty),*) $(-> $rtype:ty)?; )* ) {
|
||||
$(
|
||||
#[allow(unused, non_snake_case)] #[inline(always)]
|
||||
$v fn $name($($pname: $ptype),*) $(-> $rtype)? {
|
||||
type FTYPE = extern "C" fn($($pname: $ptype),*) $(-> $rtype)?;
|
||||
static mut FUNC: Option<FTYPE> = None;
|
||||
let function = match unsafe { FUNC } {
|
||||
Some(function) => function,
|
||||
None => unsafe {
|
||||
let import = core::mem::transmute($crate::win32::importer::find_import_hashed(
|
||||
const { x::hash_utf8($module.as_bytes()) },
|
||||
const { x::hash_utf8(stringify!($name).as_bytes()) }
|
||||
).unwrap_or(0));
|
||||
FUNC = Some(import);
|
||||
import
|
||||
}
|
||||
};
|
||||
function($($pname),*)
|
||||
}
|
||||
)*
|
||||
}
|
||||
23
sub/winu/src/lib.rs
Normal file
23
sub/winu/src/lib.rs
Normal file
@@ -0,0 +1,23 @@
|
||||
#![no_std] #![feature(decl_macro)]
|
||||
|
||||
|
||||
//
|
||||
// Internal modules
|
||||
//
|
||||
mod modules;
|
||||
mod tls;
|
||||
mod importer;
|
||||
|
||||
//
|
||||
// Export Preludes:
|
||||
//
|
||||
|
||||
pub mod prelude {
|
||||
pub use crate::importer::lazy_import;
|
||||
}
|
||||
|
||||
pub mod public {
|
||||
pub use crate::importer::find_import_hashed;
|
||||
pub use crate::tls::*;
|
||||
pub use crate::modules::*;
|
||||
}
|
||||
92
sub/winu/src/modules.rs
Normal file
92
sub/winu/src/modules.rs
Normal file
@@ -0,0 +1,92 @@
|
||||
use sub_pe::imagebase::ImageBase;
|
||||
|
||||
|
||||
#[inline(always)]
|
||||
pub unsafe fn find_module(hash: u64) -> Option<&'static ImageBase> {
|
||||
use sub_core::fnv1::hash_utf16;
|
||||
loaded_modules()
|
||||
.find(|(_, n)|hash_utf16(*n) == hash)
|
||||
.map(|(i,_)|i)
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub unsafe fn process_image() -> &'static ImageBase {
|
||||
let mut process_exe: *const ImageBase;
|
||||
core::arch::asm!(
|
||||
"mov {x}, gs:[60h]", // TEB->PEB
|
||||
"mov {x}, [{x} + 10h]", // PEB->ImageBaseAddress
|
||||
x = out(reg) process_exe,
|
||||
);
|
||||
&*process_exe
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
pub unsafe fn loaded_modules() -> ModuleIter {
|
||||
let mut module_link: *const LDR_DATA_TABLE_ENTRY;
|
||||
core::arch::asm!(
|
||||
"mov {x}, gs:[60h]", // TEB->PEB
|
||||
"mov {x}, [{x} + 18h]", // PEB->LDR
|
||||
"mov {x}, [{x} + 10h]", // LDR->InLoadOrderModuleList
|
||||
x = out(reg) module_link,
|
||||
);
|
||||
ModuleIter {
|
||||
entry: (*module_link).prev,
|
||||
head: (*module_link).prev,
|
||||
}
|
||||
}
|
||||
|
||||
pub struct ModuleIter {
|
||||
entry: *const LDR_DATA_TABLE_ENTRY,
|
||||
head: *const LDR_DATA_TABLE_ENTRY,
|
||||
}
|
||||
|
||||
impl Iterator for ModuleIter {
|
||||
type Item = (&'static ImageBase, &'static [u16]);
|
||||
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
unsafe {
|
||||
self.entry = (&*self.entry).next;
|
||||
match self.entry == self.head {
|
||||
true => { None }
|
||||
false => {
|
||||
let module = (*self.entry).module;
|
||||
let name = (*self.entry).name.as_slice();
|
||||
Some((&*module,name))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*
|
||||
FFI STRUCTS
|
||||
*/
|
||||
#[repr(C)]
|
||||
#[derive(Copy, Clone)]
|
||||
#[allow(non_camel_case_types)]
|
||||
struct UNICODE_STRING {
|
||||
pub length: u16,
|
||||
pub capacity: u16,
|
||||
pub buffer: *const u16,
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
#[allow(non_camel_case_types)]
|
||||
struct LDR_DATA_TABLE_ENTRY {
|
||||
/* 0x00 */ pub next: *const LDR_DATA_TABLE_ENTRY,
|
||||
/* 0x08 */ pub prev: *const LDR_DATA_TABLE_ENTRY,
|
||||
/* 0x10 */ pub reserved2: [usize;4],
|
||||
/* 0x30 */ pub module: *const ImageBase,
|
||||
/* 0x38 */ pub entry_point: *const (),
|
||||
/* 0x40 */ pub reserved3: usize,
|
||||
/* 0x48 */ pub path: UNICODE_STRING,
|
||||
/* 0x58 */ pub name: UNICODE_STRING,
|
||||
}
|
||||
|
||||
impl UNICODE_STRING {
|
||||
pub fn as_slice(&self) -> &'static [u16] {
|
||||
unsafe { core::slice::from_raw_parts(self.buffer, (self.length / 2) as usize) }
|
||||
}
|
||||
}
|
||||
54
sub/winu/src/tls.rs
Normal file
54
sub/winu/src/tls.rs
Normal file
@@ -0,0 +1,54 @@
|
||||
/// read the value in the given tls slot
|
||||
pub unsafe fn read_tls(index: u32) -> usize {
|
||||
let mut tls_slot: usize;
|
||||
core::arch::asm!(
|
||||
"mov {x}, gs:[1480h + {y:r} * 8]",
|
||||
x = out(reg) tls_slot,
|
||||
y = in(reg) index
|
||||
);
|
||||
tls_slot
|
||||
}
|
||||
|
||||
/// write a value into the given tls slot
|
||||
pub unsafe fn write_tls(index: u32, value: usize) {
|
||||
core::arch::asm!(
|
||||
"mov gs:[1480h + {y:r} * 8], {x}",
|
||||
x = in(reg) value,
|
||||
y = in(reg) index
|
||||
);
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
unsafe fn read_tls_bitmap() -> u64 {
|
||||
let mut _tls: u64 = 0;
|
||||
core::arch::asm!(
|
||||
"mov {x}, gs:[60h]", // TEB->PEB
|
||||
"mov {x}, [{x} + 80h]", // PEB->TlsBitmap
|
||||
x = out(reg) _tls,
|
||||
);
|
||||
_tls
|
||||
}
|
||||
|
||||
#[inline(always)]
|
||||
unsafe fn write_tls_bitmap(value: u64) {
|
||||
let peb: u64 = 0;
|
||||
core::arch::asm!(
|
||||
"mov {x}, gs:[60h]", // TEB->PEB
|
||||
"mov [{x} + 80h], {y}", // PEB->TlsBitmap
|
||||
x = in(reg) peb,
|
||||
y = in(reg) value,
|
||||
);
|
||||
}
|
||||
|
||||
/// acquires a tls slot
|
||||
pub unsafe fn acquire_tls() -> Option<u32> {
|
||||
let bitmap = read_tls_bitmap();
|
||||
(0..64)
|
||||
.filter(|i| bitmap & ( 1u64 << i ) == 0)
|
||||
.inspect(|i|{ write_tls_bitmap(bitmap | ( 1u64 << i)) }).next()
|
||||
}
|
||||
|
||||
/// free's the given tls slot
|
||||
pub unsafe fn release_tls(slot: u32) {
|
||||
write_tls_bitmap(read_tls_bitmap() & !(1 << slot ))
|
||||
}
|
||||
Reference in New Issue
Block a user