1use robs::{scanner, signature::Signature};
2use thiserror::Error;
3
4#[cfg(target_family = "windows")]
5pub mod windows;
6
7pub struct RemoteMemory {
8 #[cfg(target_family = "windows")]
9 windows_remote_memory: windows::windows_remote_memory::WindowsRemoteMemory,
10}
11
12#[derive(Debug, Error)]
13pub enum RemoteMemoryError {
14 #[cfg(target_family = "windows")]
15 #[error("{0}")]
16 WindowsError(windows::windows_remote_memory::WindowsError),
17 #[error("'{0}' OS is not supported")]
18 OsNotSupported(String),
19}
20
21#[cfg(target_family = "windows")]
22impl From<windows::windows_remote_memory::WindowsError> for RemoteMemoryError {
23 fn from(e: windows::windows_remote_memory::WindowsError) -> Self {
24 RemoteMemoryError::WindowsError(e)
25 }
26}
27
28#[cfg(target_family = "windows")]
29impl RemoteMemory {
30 pub fn new(process_id: u32) -> Result<RemoteMemory, RemoteMemoryError> {
31 Ok(RemoteMemory {
32 windows_remote_memory: windows::windows_remote_memory::WindowsRemoteMemory::new(
33 process_id,
34 )?,
35 })
36 }
37
38 pub fn new_by_name(process_name: &str) -> Result<RemoteMemory, RemoteMemoryError> {
39 Ok(RemoteMemory {
40 windows_remote_memory:
41 windows::windows_remote_memory::WindowsRemoteMemory::new_by_name(process_name)?,
42 })
43 }
44
45 pub fn read_bytes(&self, address: usize, buffer: &mut [u8]) -> Result<(), RemoteMemoryError> {
46 Ok(self.windows_remote_memory.read_bytes(address, buffer)?)
47 }
48
49 pub fn write_ptr(
50 &self,
51 address: usize,
52 ptr: usize,
53 num_bytes_to_write: usize,
54 ) -> Result<(), RemoteMemoryError> {
55 Ok(self
56 .windows_remote_memory
57 .write_ptr(address, ptr, num_bytes_to_write)?)
58 }
59
60 pub fn get_base_address(&self) -> usize {
61 self.windows_remote_memory.base_module.mod_base_addr as usize
62 }
63
64 pub fn get_base_size(&self) -> usize {
65 self.windows_remote_memory.base_module.mod_base_size as usize
66 }
67}
68
69impl RemoteMemory {
70 pub fn read<T: Sized + Copy>(&self, address: usize) -> Result<T, RemoteMemoryError> {
71 let size = std::mem::size_of::<T>();
72 let mut buffer: Vec<u8> = vec![0; size];
73 self.read_bytes(address, &mut buffer)?;
74 Ok(unsafe { (buffer.as_ptr() as *const T).read_unaligned() })
75 }
76
77 pub fn write_bytes(&self, address: usize, buffer: &[u8]) -> Result<(), RemoteMemoryError> {
78 self.write_ptr(address, buffer.as_ptr() as usize, buffer.len())
79 }
80
81 pub fn write<T: Sized + Copy>(
82 &self,
83 address: usize,
84 value: T,
85 ) -> Result<(), RemoteMemoryError> {
86 let size = std::mem::size_of::<T>();
87 self.write_ptr(address, std::ptr::addr_of!(value) as usize, size)
88 }
89
90 pub fn find_signature(&self, signature: &Signature) -> Option<usize> {
91 let base_address = self.get_base_address();
92 let base_size = self.get_base_size();
93 let mut buffer = vec![0; base_size];
94 self.read_bytes(base_address, &mut buffer).ok()?;
95 scanner::find_signature(&buffer, signature)
96 }
97}
98
99#[cfg(test)]
100mod test {
101 #[test]
102 fn test_read_bytes() {
103 let buffer = vec![0xFF, 0x00, 0x12, 0xCD];
104 let buffer_ptr = buffer.as_ptr() as usize;
105 let process_id = std::process::id();
106 let remote_memory = super::RemoteMemory::new(process_id);
107 assert!(remote_memory.is_ok());
108 let remote_memory = remote_memory.unwrap();
109 let mut read_buffer = vec![0; 4];
110 assert!(remote_memory
111 .read_bytes(buffer_ptr, &mut read_buffer)
112 .is_ok());
113 assert_eq!(buffer, read_buffer);
114 }
115
116 #[test]
117 fn test_read_u32() {
118 let value = 12345;
119 let value_ptr = std::ptr::addr_of!(value) as usize;
120 let process_id = std::process::id();
121 let remote_memory = super::RemoteMemory::new(process_id);
122 assert!(remote_memory.is_ok());
123 let remote_memory = remote_memory.unwrap();
124 let read_value = remote_memory.read::<u32>(value_ptr);
125 assert!(read_value.is_ok());
126 let read_value = read_value.unwrap();
127 assert_eq!(read_value, value);
128 }
129
130 #[test]
131 fn test_write_bytes() {
132 let data = vec![0xFF, 0x00, 0x12, 0xCD];
133 let buffer = vec![0; 4];
134 let buffer_ptr = buffer.as_ptr() as usize;
135 let process_id = std::process::id();
136 let remote_memory = super::RemoteMemory::new(process_id);
137 assert!(remote_memory.is_ok());
138 let remote_memory = remote_memory.unwrap();
139 assert_ne!(data, buffer);
140 assert!(remote_memory.write_bytes(buffer_ptr, &data).is_ok());
141 assert_eq!(data, buffer);
142 }
143
144 #[test]
145 fn test_write_u32() {
146 let data: usize = 12345;
147 let buffer: usize = 0;
148 let buffer_ptr = std::ptr::addr_of!(buffer) as usize;
149 let process_id = std::process::id();
150 let remote_memory = super::RemoteMemory::new(process_id);
151 assert!(remote_memory.is_ok());
152 let remote_memory = remote_memory.unwrap();
153 assert_ne!(data, buffer);
154 assert!(remote_memory.write::<usize>(buffer_ptr, data).is_ok());
155 assert_eq!(data, buffer);
156 }
157}