Skip to content

Commit

Permalink
wip
Browse files Browse the repository at this point in the history
  • Loading branch information
KiraCoding committed Aug 28, 2024
1 parent b372f6d commit b451a19
Show file tree
Hide file tree
Showing 7 changed files with 149 additions and 180 deletions.
5 changes: 1 addition & 4 deletions examples/sections.rs
Original file line number Diff line number Diff line change
@@ -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());
}
2 changes: 1 addition & 1 deletion src/base.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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) },
}
Expand Down
59 changes: 0 additions & 59 deletions src/hook.rs

This file was deleted.

2 changes: 0 additions & 2 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
146 changes: 146 additions & 0 deletions src/program.rs
Original file line number Diff line number Diff line change
@@ -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<Program> = LazyLock::new(Program::init);

pub fn program() -> &'static Program {
&PROGRAM
}

#[derive(Debug)]
pub struct Program {
base: Base,
len: usize,
sections: Vec<Section>,
}

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<NonNull<u8>> {
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<NonNull<u8>> {
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 = &section.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<I: SliceIndex<[u8]>> Index<I> 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(),
// }
// }
// }
113 changes: 0 additions & 113 deletions src/program/mod.rs → src/program_old/mod.rs
Original file line number Diff line number Diff line change
@@ -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<Program> = LazyLock::new(Program::init);

pub fn program() -> &'static Program {
&PROGRAM
}

#[derive(Debug)]
pub struct Program {
base: Base,
len: usize,
sections: Vec<Section>,
}

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<NonNull<u8>> {
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<NonNull<u8>> {
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<I: SliceIndex<[u8]>> Index<I> 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 {
Expand Down Expand Up @@ -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(),
}
}
}
2 changes: 1 addition & 1 deletion src/section.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 }
}
}
Expand Down

0 comments on commit b451a19

Please sign in to comment.