#memory #process #debugging #read-write #remote #memory-management #game

process-memory

A rust library that can read/write the memory of other processes

7 releases (4 breaking)

0.5.0 Oct 9, 2022
0.4.0 Jul 18, 2020
0.3.0 Jan 17, 2020
0.2.3 Jan 18, 2018
0.1.1 Jan 11, 2018

#252 in Unix APIs

Download history 15/week @ 2023-12-13 14/week @ 2023-12-20 4/week @ 2023-12-27 4/week @ 2024-01-03 16/week @ 2024-01-10 14/week @ 2024-01-17 5/week @ 2024-01-24 7/week @ 2024-01-31 23/week @ 2024-02-07 61/week @ 2024-02-14 102/week @ 2024-02-21 90/week @ 2024-02-28 70/week @ 2024-03-06 79/week @ 2024-03-13 62/week @ 2024-03-20 45/week @ 2024-03-27

263 downloads per month
Used in 5 crates (4 directly)

MIT license

39KB
602 lines

process-memory

Continuous Integration

This crate is loosely based on read-process-memory by luser, but has been extended to be able to write to process memory as well.

The current supported platforms are:

  • Windows
  • OSX
  • Linux

Some examples of use cases for this tool are:

  • Remote debugging tools
  • Game "trainers"
  • Rust clones of Cheat Engine

Examples

# use process_memory::{Memory, DataMember, Pid, TryIntoProcessHandle};
// We have a variable with some value
let x = 4_u32;
println!("Original x-value: {}", x);

// We need to make sure that we get a handle to a process, in this case, ourselves
let handle = (std::process::id() as Pid).try_into_process_handle().unwrap();
// We make a `DataMember` that has an offset referring to its location in memory
let member = DataMember::new_offset(handle, vec![&x as *const _ as usize]);
// The memory refered to is now the same
println!("Memory location: &x: {}, member: {}", &x as *const _ as usize,
    member.get_offset().unwrap());
assert_eq!(&x as *const _ as usize, member.get_offset().unwrap());
// The value of the member is the same as the variable
println!("Member value: {}", unsafe { member.read().unwrap() });
assert_eq!(x, unsafe { member.read().unwrap() });
// We can write to and modify the value of the variable using the member
member.write(&6_u32).unwrap();
println!("New x-value: {}", x);
assert_eq!(x, 6_u32);
# use process_memory::{Memory, LocalMember};
// We have a variable with some value
let x = 4_u32;
println!("Original x-value: {}", x);

// We make a `LocalMember` that has an offset referring to its location in memory
let member = LocalMember::new_offset(vec![&x as *const _ as usize]);
// The memory refered to is now the same
println!("Memory location: &x: {}, member: {}", &x as *const _ as usize,
    member.get_offset().unwrap());
assert_eq!(&x as *const _ as usize, member.get_offset().unwrap());
// The value of the member is the same as the variable
println!("Member value: {}", unsafe { member.read().unwrap() });
assert_eq!(x, unsafe { member.read().unwrap() });
// We can write to and modify the value of the variable using the member
member.write(&6_u32).unwrap();
println!("New x-value: {}", x);
assert_eq!(x, 6_u32);
# use process_memory::{Architecture, Memory, DataMember, Pid, ProcessHandleExt, TryIntoProcessHandle};
# fn get_pid(process_name: &str) -> Pid {
#     std::process::id() as Pid
# }
// We get a handle for a target process with a different architecture to ourselves
let handle = get_pid("32Bit.exe").try_into_process_handle().unwrap()
    .set_arch(Architecture::Arch32Bit);
// We make a `DataMember` that has a series of offsets refering to a known value in
// the target processes memory
let member = DataMember::new_offset(handle, vec![0x01_02_03_04, 0x04, 0x08, 0x10]);
// The memory offset can now be correctly calculated:
println!("Target memory location: {}", member.get_offset().unwrap());
// The memory offset can now be used to retrieve and modify values:
println!("Current value: {}", unsafe { member.read().unwrap() });
member.write(&123_u32).unwrap();

Dependencies

~235KB