Memflex - Memory hacking library
Installation
[dependencies]
memflex = "0.8"
Features
use memflex::{ida_pat, peid_pat};
// Pattern creation and parsing happens at compile time.
let ida = ida_pat!("13 ? D1");
let peid = peid_pat!("13 ?? D1");
#[cfg(windows)]
{
let first = memflex::internal::find_pattern_in_module(ida, "ntdll.dll").unwrap().next();
let last = memflex::internal::find_pattern_in_module(peid, "ntdll.dll").unwrap().last();
}
#[cfg(windows)]
let module = memflex::internal::find_module_by_name("ntdll.dll");
// module.size, module.base
- Read/Write external memory
#[cfg(windows)]
if let Ok(p) = memflex::external::open_process_by_id(666, false, memflex::types::win::PROCESS_ALL_ACCESS) {
let value = p.read::<u32>(0x7FFF)?;
p.write(0x7FFF, 100_u32)?;
}
Ok::<_, memflex::MfError>(())
- Macros for emulating C++ behavior
#[repr(C)]
pub struct ConcreteType {
vmt: memflex::VmtPtr
};
memflex::interface! {
pub trait IPlayer impl for ConcreteType {
// Notice missing `&self`, this is intentional and macro will implicitly add it.
// Functions without `&self` in interface doesn't make much sense.
extern "C" fn get_health() -> i32 = #0; // 0 - Index of the virtual function.
// *Returns old health*
extern "C" fn set_health(new: i32) -> i32 = #1; // 1 - Index of the virtual function.
}
trait Foo {
extern fn foo() = #0;
}
trait ParentVmt {
fn f1() -> i32 = #0;
fn f2() -> i32 = #1;
}
trait ChildVmt {
fn f3(a: i32) = #0;
fn f4(a: i32) = #1;
}
}
// Automatically wraps all structures in `#[repr(C)]`
// Virtual functions with inheritence is not tested(probably doesnt work).
memflex::makestruct! {
// Attributes works as expected
#[derive(Default)]
struct Parent {
// on fields as well
// #[serde(skip)]
first: f32
}
// `pub` means that `parent` field will be `pub`
// but Deref<Target = Parent> implementation will be generated regardless.
struct Child : pub Parent {
second: i32
}
// Implements `Foo` interface on `Nested`
struct Nested impl Foo : Child {
third: bool
}
struct ParentWithVmt impl ParentVmt {
vmt: usize,
t1: f32,
t2: bool
}
// By using `dyn ParentWithVmt`, child offsets all of their vfunc indices by the number of functions in `ParentWithVmt`,
// should work with nested inheritance but hasn't been tested so I just pray it works.
struct ChildInheritsParentVmt impl ChildVmt(dyn ParentWithVmt) : pub ParentWithVmt {
t3: u64,
t4: i8
}
}
memflex::global! {
// Uses default ldr resolver on windows
pub extern MY_GLOBAL: i32 = "ntdll.dll"#0x1000;
}
memflex::function! {
// Function with offset from the module
fn ADDER(i32, i32) -> i32 = "function.exe"#0x2790;
// Function with signature
fn MIXER(f32, f32, f32) -> u32 = "function.exe"%"48 81 EC B8 00 00 00 F3";
}
memflex::bitstruct! {
struct SomeStruct : u8 {
// Bits: 0, 1, 2
first: 0..=2,
// Bits: 3, 4, 5, 6, 7
next: 3..=7,
}
}
// Null terminated strings
use memflex::types::TStr;
let zero_terminated: TStr = memflex::tstr!("Hello, World!");