1
- //! This crate provides tools for working with the raw memory of programs.
2
- //!
3
- //! Some examples of use cases for this tool are:
4
- //! - Remote debugging tools
5
- //! - Game "trainers"
6
- //! - Rust clones of Cheat Engine
7
- //!
8
- //! ## Examples
9
- //! ```rust
10
- //! # use process_memory::{Memory, DataMember, Pid, TryIntoProcessHandle};
11
- //! // We have a variable with some value
12
- //! let x = 4_u32;
13
- //! println!("Original x-value: {}", x);
14
- //!
15
- //! // We need to make sure that we get a handle to a process, in this case, ourselves
16
- //! let handle = (std::process::id() as Pid).try_into_process_handle().unwrap();
17
- //! // We make a `DataMember` that has an offset referring to its location in memory
18
- //! let member = DataMember::new_offset(handle, vec![&x as *const _ as usize]);
19
- //! // The memory refered to is now the same
20
- //! println!("Memory location: &x: {}, member: {}", &x as *const _ as usize,
21
- //! member.get_offset().unwrap());
22
- //! assert_eq!(&x as *const _ as usize, member.get_offset().unwrap());
23
- //! // The value of the member is the same as the variable
24
- //! println!("Member value: {}", unsafe { member.read().unwrap() });
25
- //! assert_eq!(x, unsafe { member.read().unwrap() });
26
- //! // We can write to and modify the value of the variable using the member
27
- //! member.write(&6_u32).unwrap();
28
- //! println!("New x-value: {}", x);
29
- //! assert_eq!(x, 6_u32);
30
- //! ```
31
- //! ```rust
32
- //! # use process_memory::{Memory, LocalMember};
33
- //! // We have a variable with some value
34
- //! let x = 4_u32;
35
- //! println!("Original x-value: {}", x);
36
- //!
37
- //! // We make a `LocalMember` that has an offset referring to its location in memory
38
- //! let member = LocalMember::new_offset(vec![&x as *const _ as usize]);
39
- //! // The memory refered to is now the same
40
- //! println!("Memory location: &x: {}, member: {}", &x as *const _ as usize,
41
- //! member.get_offset().unwrap());
42
- //! assert_eq!(&x as *const _ as usize, member.get_offset().unwrap());
43
- //! // The value of the member is the same as the variable
44
- //! println!("Member value: {}", unsafe { member.read().unwrap() });
45
- //! assert_eq!(x, unsafe { member.read().unwrap() });
46
- //! // We can write to and modify the value of the variable using the member
47
- //! member.write(&6_u32).unwrap();
48
- //! println!("New x-value: {}", x);
49
- //! assert_eq!(x, 6_u32);
50
- //! ```
51
- //! ```no_run
52
- //! # use process_memory::{Architecture, Memory, DataMember, Pid, ProcessHandleExt, TryIntoProcessHandle};
53
- //! # fn get_pid(process_name: &str) -> Pid {
54
- //! # std::process::id() as Pid
55
- //! # }
56
- //! // We get a handle for a target process with a different architecture to ourselves
57
- //! let handle = get_pid("32Bit.exe").try_into_process_handle().unwrap()
58
- //! .set_arch(Architecture::Arch32Bit);
59
- //! // We make a `DataMember` that has a series of offsets refering to a known value in
60
- //! // the target processes memory
61
- //! let member = DataMember::new_offset(handle, vec![0x01_02_03_04, 0x04, 0x08, 0x10]);
62
- //! // The memory offset can now be correctly calculated:
63
- //! println!("Target memory location: {}", member.get_offset().unwrap());
64
- //! // The memory offset can now be used to retrieve and modify values:
65
- //! println!("Current value: {}", unsafe { member.read().unwrap() });
66
- //! member.write(&123_u32).unwrap();
67
- //! ```
1
+ #![ doc = include_str ! ( "../README.md" ) ]
68
2
#![ deny( missing_docs) ]
69
3
#![ deny( unused_results) ]
70
4
#![ deny( unreachable_pub) ]
@@ -109,6 +43,9 @@ pub trait CopyAddress {
109
43
///
110
44
/// # Errors
111
45
/// `std::io::Error` if an error occurs copying the address.
46
+ ///
47
+ /// [`copy_address`]: #tymethod.copy_address
48
+ /// [`get_pointer_width`]: #tymethod.get_pointer_width
112
49
fn get_offset ( & self , offsets : & [ usize ] ) -> std:: io:: Result < usize > {
113
50
// Look ma! No unsafes!
114
51
let mut offset: usize = 0 ;
@@ -131,6 +68,8 @@ pub trait CopyAddress {
131
68
/// Any implementation of this function should be marked with
132
69
/// `#[inline(always)]` as this function is *very* commonly called and
133
70
/// should be inlined.
71
+ ///
72
+ /// [`get_offset`]: #method.get_offset
134
73
fn get_pointer_width ( & self ) -> Architecture ;
135
74
}
136
75
@@ -180,9 +119,9 @@ impl TryIntoProcessHandle for ProcessHandle {
180
119
181
120
/// Additional functions on process handles
182
121
pub trait ProcessHandleExt {
183
- /// Returns `true` if the `ProcessHandle` is not null, and `false` otherwise.
122
+ /// Returns `true` if the [ `ProcessHandle`] is not null, and `false` otherwise.
184
123
fn check_handle ( & self ) -> bool ;
185
- /// Return the null equivalent of a `ProcessHandle`.
124
+ /// Return the null equivalent of a [ `ProcessHandle`] .
186
125
#[ must_use]
187
126
fn null_type ( ) -> ProcessHandle ;
188
127
/// Set this handle to use some architecture
@@ -253,7 +192,7 @@ pub trait Memory<T> {
253
192
254
193
/// Copy `length` bytes of memory at `addr` from `source`.
255
194
///
256
- /// This is just a convenient way to call `CopyAddress::copy_address` without
195
+ /// This is just a convenient way to call [ `CopyAddress::copy_address`] without
257
196
/// having to provide your own buffer.
258
197
///
259
198
/// # Errors
0 commit comments