From b451a19b970efd5edb1c43f5a58896461fda5e6c Mon Sep 17 00:00:00 2001 From: KiraCoding <38864051+KiraCoding@users.noreply.github.com> Date: Wed, 28 Aug 2024 20:43:08 +0200 Subject: [PATCH] wip --- examples/sections.rs | 5 +- src/base.rs | 2 +- src/hook.rs | 59 ----------- src/lib.rs | 2 - src/program.rs | 146 ++++++++++++++++++++++++++++ src/{program => program_old}/mod.rs | 113 --------------------- src/section.rs | 2 +- 7 files changed, 149 insertions(+), 180 deletions(-) delete mode 100644 src/hook.rs create mode 100644 src/program.rs rename src/{program => program_old}/mod.rs (51%) diff --git a/examples/sections.rs b/examples/sections.rs index 3872f61..1e911c7 100644 --- a/examples/sections.rs +++ b/examples/sections.rs @@ -1,8 +1,5 @@ use inka::program; fn main() { - let program = dbg!(program()); - let text = dbg!(program.get_section(".text").unwrap()); - - dbg!(unsafe { text.add(1) }); + dbg!(program()); } diff --git a/src/base.rs b/src/base.rs index 5c8c2dd..9af9031 100644 --- a/src/base.rs +++ b/src/base.rs @@ -19,7 +19,7 @@ impl Base { unsafe { self.ptr.add(count) } } - pub(crate) unsafe fn _new_unchecked(ptr: *mut u8) -> Self { + pub(crate) unsafe fn new_unchecked(ptr: *mut u8) -> Self { Self { ptr: unsafe { NonNull::new_unchecked(ptr) }, } diff --git a/src/hook.rs b/src/hook.rs deleted file mode 100644 index 7c53848..0000000 --- a/src/hook.rs +++ /dev/null @@ -1,59 +0,0 @@ -use core::ptr::null_mut; -use core::sync::atomic::{AtomicPtr, Ordering}; - -pub trait Hook: Copy { - fn hook(&self) -> HookGuard { - let self_ptr = self.as_ptr_u8(); - - HookGuard { bytes: [0; 16] } - } - - fn as_ptr_u8(self) -> *mut u8; - fn trampoline(f: F) -> Closure; -} - -pub struct HookGuard { - bytes: [u8; 16], -} - -impl HookGuard { - pub fn unhook(&self) {} -} - -pub struct Closure { - inner: Box>, -} - -#[repr(C)] -struct ClosureInner { - ptr: *const (), - data: F, -} - -static STATIC_CONTEXT: AtomicPtr<()> = AtomicPtr::new(null_mut()); - -impl Hook for unsafe extern "C" fn() -> R -where - F: FnMut() + 'static, -{ - fn as_ptr_u8(self) -> *mut u8 { - self as *mut u8 - } - - fn trampoline(f: F) -> Closure { - unsafe extern "C" fn thunk() - where - F: FnMut() + 'static, - { - let p = STATIC_CONTEXT.swap(null_mut(), Ordering::Relaxed) as *mut ClosureInner; - ((*p).data)(); - } - - Closure { - inner: Box::new(ClosureInner { - ptr: thunk:: as *const (), - data: f, - }), - } - } -} diff --git a/src/lib.rs b/src/lib.rs index a6a537d..24e06d8 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -2,8 +2,6 @@ mod base; mod program; mod section; -pub mod hook; - pub use base::Base; pub use program::{program, Program}; pub use section::Section; diff --git a/src/program.rs b/src/program.rs new file mode 100644 index 0000000..f2e2726 --- /dev/null +++ b/src/program.rs @@ -0,0 +1,146 @@ +use crate::{Base, Section}; +use core::ops::Index; +use core::ptr::NonNull; +use core::slice::{from_raw_parts, SliceIndex}; +use rayon::iter::IndexedParallelIterator; +use rayon::slice::ParallelSlice; +use std::sync::LazyLock; +use windows::core::PCWSTR; +use windows::Win32::System::Diagnostics::Debug::{IMAGE_NT_HEADERS64, IMAGE_SECTION_HEADER}; +use windows::Win32::System::LibraryLoader::GetModuleHandleW; +use windows::Win32::System::SystemServices::IMAGE_DOS_HEADER; + +static PROGRAM: LazyLock = LazyLock::new(Program::init); + +pub fn program() -> &'static Program { + &PROGRAM +} + +#[derive(Debug)] +pub struct Program { + base: Base, + len: usize, + sections: Vec
, +} + +impl Program { + /// Returns a raw pointer to this programs base. + #[inline] + pub fn as_ptr(&self) -> *const u8 { + self.base.as_ptr() + } + + /// Returns the length of this program in memory. + #[inline] + #[allow(clippy::len_without_is_empty)] + pub fn len(&self) -> usize { + self.len + } + + /// Returns a slice containing the entire program. + #[inline] + pub fn as_slice(&self) -> &[u8] { + unsafe { from_raw_parts(self.base.as_ptr(), self.len) } + } + + pub fn contains(&self, pattern: &[u8]) -> bool { + self.find(pattern).is_some() + } + + pub fn sections(&self) -> &[Section] { + &self.sections + } + + pub fn get_section(&self, name: &str) -> Option<&Section> { + self.sections.iter().find(|section| section.name() == name) + } + + pub fn find(&self, pattern: &[u8]) -> Option> { + self.as_slice() + .par_windows(pattern.len()) + .position_first(|window| window == pattern) + .map(|offset| unsafe { self.base.add(offset) }) + } + + pub fn rfind(&self, pattern: &[u8]) -> Option> { + self.as_slice() + .par_windows(pattern.len()) + .position_last(|window| window == pattern) + .map(|offset| unsafe { self.base.add(offset) }) + } + + fn init() -> Self { + let base = unsafe { + Base::new_unchecked(GetModuleHandleW(PCWSTR::null()).unwrap_unchecked().0.cast()) + }; + + let dos_header = base.as_ptr() as *const IMAGE_DOS_HEADER; + let nt_headers64: &IMAGE_NT_HEADERS64 = + unsafe { &*(base.add((*dos_header).e_lfanew as usize).as_ptr().cast()) }; + + let len = nt_headers64.OptionalHeader.SizeOfImage as usize; + + let section_header_ptr = unsafe { + (nt_headers64 as *const IMAGE_NT_HEADERS64).add(1) as *const IMAGE_SECTION_HEADER + }; + + let sections = (0..nt_headers64.FileHeader.NumberOfSections) + .map(|index| unsafe { &*section_header_ptr.add(index as usize) }) + .map(|section| { + let name = { + let raw_name = §ion.Name; + let name_len = raw_name + .iter() + .position(|&c| c == 0) + .unwrap_or(raw_name.len()); + + unsafe { core::str::from_utf8_unchecked(&raw_name[..name_len]) } + }; + + Section::new(name, base, len) + }) + .collect(); + + Self { + base, + len, + sections, + } + } +} + +impl> Index for Program { + type Output = I::Output; + + #[inline] + fn index(&self, index: I) -> &Self::Output { + self.as_slice().index(index) + } +} + +// #[cfg(target_os = "linux")] +// mod linux { +// use super::{Base, Program}; +// use core::mem::zeroed; +// use libc::{dladdr, getauxval, Dl_info, AT_PHDR}; + +// pub(crate) fn init() -> Program { +// let base = { +// let mut info: Dl_info = unsafe { zeroed() }; +// let dummy_address = unsafe { getauxval(AT_PHDR) as *const usize }; +// unsafe { dladdr(dummy_address.cast(), &mut info) }; + +// Base { +// ptr: info.dli_fbase as *const u8, +// } +// }; + +// let len = { 0 }; + +// Program { +// base, +// len, +// sections: Vec::new(), +// } +// } +// } diff --git a/src/program/mod.rs b/src/program_old/mod.rs similarity index 51% rename from src/program/mod.rs rename to src/program_old/mod.rs index e2c214e..81cd481 100644 --- a/src/program/mod.rs +++ b/src/program_old/mod.rs @@ -1,91 +1,4 @@ -use crate::{Base, Section}; -use core::ops::Index; -use core::ptr::NonNull; -use core::slice::{from_raw_parts, SliceIndex}; -use rayon::iter::IndexedParallelIterator; -use rayon::slice::ParallelSlice; -use std::sync::LazyLock; -static PROGRAM: LazyLock = LazyLock::new(Program::init); - -pub fn program() -> &'static Program { - &PROGRAM -} - -#[derive(Debug)] -pub struct Program { - base: Base, - len: usize, - sections: Vec
, -} - -impl Program { - /// Returns a raw pointer to this programs base. - #[inline] - pub fn as_ptr(&self) -> *const u8 { - self.base.as_ptr() - } - - /// Returns the length of this program in memory. - #[inline] - #[allow(clippy::len_without_is_empty)] - pub fn len(&self) -> usize { - self.len - } - - /// Returns a slice containing the entire program. - #[inline] - pub fn as_slice(&self) -> &[u8] { - unsafe { from_raw_parts(self.base.as_ptr(), self.len) } - } - - pub fn contains(&self, pattern: &[u8]) -> bool { - self.find(pattern).is_some() - } - - pub fn sections(&self) -> &[Section] { - &self.sections - } - - pub fn get_section(&self, name: &str) -> Option<&Section> { - self.sections.iter().find(|section| section.name() == name) - } - - pub fn find(&self, pattern: &[u8]) -> Option> { - self.as_slice() - .par_windows(pattern.len()) - .position_first(|window| window == pattern) - .map(|offset| unsafe { self.base.add(offset) }) - } - - pub fn rfind(&self, pattern: &[u8]) -> Option> { - self.as_slice() - .par_windows(pattern.len()) - .position_last(|window| window == pattern) - .map(|offset| unsafe { self.base.add(offset) }) - } - - fn init() -> Self { - #[cfg(target_os = "windows")] - { - windows::init() - } - - #[cfg(target_os = "linux")] - { - linux::init() - } - } -} - -impl> Index for Program { - type Output = I::Output; - - #[inline] - fn index(&self, index: I) -> &Self::Output { - self.as_slice().index(index) - } -} #[cfg(target_os = "windows")] mod windows { @@ -170,29 +83,3 @@ mod windows { } } -#[cfg(target_os = "linux")] -mod linux { - use super::{Base, Program}; - use core::mem::zeroed; - use libc::{dladdr, getauxval, Dl_info, AT_PHDR}; - - pub(crate) fn init() -> Program { - let base = { - let mut info: Dl_info = unsafe { zeroed() }; - let dummy_address = unsafe { getauxval(AT_PHDR) as *const usize }; - unsafe { dladdr(dummy_address.cast(), &mut info) }; - - Base { - ptr: info.dli_fbase as *const u8, - } - }; - - let len = { 0 }; - - Program { - base, - len, - sections: Vec::new(), - } - } -} diff --git a/src/section.rs b/src/section.rs index 83835f2..9a23834 100644 --- a/src/section.rs +++ b/src/section.rs @@ -56,7 +56,7 @@ impl Section { .map(|offset| unsafe { self.base.add(offset) }) } - pub(crate) fn _new(name: &'static str, base: Base, len: usize) -> Self { + pub(crate) fn new(name: &'static str, base: Base, len: usize) -> Self { Self { name, base, len } } }