1use std::path::PathBuf;
2
3use super::{error::ProcessError, signature::Signature};
4use paste::paste;
5
6#[cfg(target_os = "windows")]
7use windows::Win32::Foundation::HANDLE;
8
9#[derive(Debug)]
10pub struct MemoryRegion {
11 pub from: usize,
12 pub size: usize,
13}
14
15macro_rules! read_generic {
16 ($t: ty, $self: expr, $addr: expr) => {{
17 paste! {
18 let mut bytes = vec![0u8; std::mem::size_of::<T>()];
19
20 $self.read($addr, std::mem::size_of::<T>(), &mut bytes)?;
21
22 unsafe { std::ptr::read(bytes.as_ptr() as *const T) }
23 }
24 }};
25}
26
27macro_rules! prim_read_impl {
28 ($t: ident) => {
29 paste! {
30 fn [<read_ $t>]<T: TryInto<usize>>(
31 &self,
32 addr: T
33 ) -> Result<$t, ProcessError> {
34 let mut bytes = [0u8; std::mem::size_of::<$t>()];
35 self.read(addr, std::mem::size_of::<$t>(), &mut bytes)?;
36
37 Ok($t::from_le_bytes(bytes))
38 }
39 }
40 };
41}
42
43macro_rules! prim_read_array_impl {
44 ($t: ident) => {
45 paste! {
46 fn [<read_ $t _array>]<T: TryInto<usize>>(
47 &self,
48 addr: T,
49 buff: &mut Vec<$t>
50 ) -> Result<(), ProcessError> {
51 let addr: usize = addr.try_into()
52 .map_err(|_| ProcessError::AddressConvertError)?;
53
54 let items_ptr = self.read_i32(addr + 4)?;
55 let size = self.read_i32(addr + 12)? as usize;
56
57 buff.resize(size, 0 as $t);
58
59 let byte_buff = unsafe { std::slice::from_raw_parts_mut(
60 buff.as_mut_ptr() as *mut u8,
61 buff.len() * std::mem::size_of::<$t>()
62 ) };
63
64
65 self.read(
66 items_ptr + 8,
67 size * std::mem::size_of::<$t>(),
68 byte_buff
69 )?;
70
71 Ok(())
72 }
73 }
74 };
75}
76
77pub struct Process {
78 #[cfg(target_os = "linux")]
79 pub pid: i32,
80
81 #[cfg(target_os = "windows")]
82 pub pid: u32,
83
84 #[cfg(target_os = "windows")]
85 pub handle: HANDLE,
86
87 pub maps: Vec<MemoryRegion>,
88
89 pub executable_dir: Option<PathBuf>,
90}
91
92pub trait ProcessTraits
93where
94 Self: Sized,
95{
96 fn initialize(
105 proc_name: &str,
106 exclude: &[&str],
107 ) -> Result<Self, ProcessError>;
108
109 fn find_process(
118 proc_name: &str,
119 exclude: &[&str],
120 ) -> Result<Self, ProcessError>;
121
122 fn read_regions(self) -> Result<Self, ProcessError>;
128
129 fn read_signature<T: TryFrom<usize>>(
130 &self,
131 sign: &Signature,
132 ) -> Result<T, ProcessError>;
133
134 fn read<T: TryInto<usize>>(
135 &self,
136 addr: T,
137 len: usize,
138 buff: &mut [u8],
139 ) -> Result<(), ProcessError>;
140
141 fn read_uleb128<T: TryInto<usize>>(
142 &self,
143 addr: T,
144 ) -> Result<u64, ProcessError> {
145 let mut addr: usize = addr
146 .try_into()
147 .map_err(|_| ProcessError::AddressConvertError)?;
148
149 let mut value: u64 = 0;
150 let mut bytes_read = 0;
151
152 loop {
153 let byte = self.read_u8(addr)?;
154 addr += 1;
155
156 let byte_value = (byte & 0b0111_1111) as u64;
157 value |= byte_value << (7 * bytes_read);
158
159 bytes_read += 1;
160
161 if (byte & !0b0111_1111) == 0 {
162 break;
163 }
164 }
165
166 Ok(value)
167 }
168
169 fn read_string_with_limit_from_ptr<T: TryInto<usize>>(
181 &self,
182 addr: T,
183 limit: usize,
184 ) -> Result<String, ProcessError> {
185 let addr = read_generic!(T, self, addr);
186
187 self.read_string_with_limit(addr, limit)
188 }
189
190 fn read_string_with_limit<T: TryInto<usize>>(
196 &self,
197 addr: T,
198 limit: usize,
199 ) -> Result<String, ProcessError> {
200 let mut addr: usize = addr
201 .try_into()
202 .map_err(|_| ProcessError::AddressConvertError)?;
203
204 addr += std::mem::size_of::<T>();
205
206 let len = self.read_u32(addr)? as usize; if len > limit {
209 return Err(ProcessError::StringTooLarge);
210 }
211
212 addr += 0x4; let mut buff = vec![0u16; len];
215
216 let byte_buff = unsafe {
217 std::slice::from_raw_parts_mut(
218 buff.as_mut_ptr() as *mut u8,
219 buff.len() * 2,
220 )
221 };
222
223 self.read(addr, byte_buff.len(), byte_buff)?;
224
225 Ok(String::from_utf16_lossy(&buff))
226 }
227
228 fn read_string_from_ptr<T: TryInto<usize>>(
238 &self,
239 addr: T,
240 ) -> Result<String, ProcessError> {
241 let addr = read_generic!(T, self, addr);
242
243 self.read_string(addr)
244 }
245
246 fn read_string<T: TryInto<usize>>(
253 &self,
254 addr: T,
255 ) -> Result<String, ProcessError> {
256 let mut addr: usize = addr
257 .try_into()
258 .map_err(|_| ProcessError::AddressConvertError)?;
259
260 addr += std::mem::size_of::<T>(); let len = self.read_u32(addr)? as usize; addr += 0x4; let mut buff = vec![0u16; len];
267
268 let byte_buff = unsafe {
269 std::slice::from_raw_parts_mut(
270 buff.as_mut_ptr() as *mut u8,
271 buff.len() * 2,
272 )
273 };
274
275 self.read(addr, byte_buff.len(), byte_buff)?;
276
277 Ok(String::from_utf16_lossy(&buff))
278 }
279
280 prim_read_impl!(i8);
281 prim_read_impl!(i16);
282 prim_read_impl!(i32);
283 prim_read_impl!(i64);
284 prim_read_impl!(i128);
285
286 prim_read_impl!(u8);
287 prim_read_impl!(u16);
288 prim_read_impl!(u32);
289 prim_read_impl!(u64);
290 prim_read_impl!(u128);
291
292 prim_read_impl!(f32);
293 prim_read_impl!(f64);
294
295 prim_read_array_impl!(i8);
296 prim_read_array_impl!(i16);
297 prim_read_array_impl!(i32);
298 prim_read_array_impl!(i64);
299 prim_read_array_impl!(i128);
300
301 prim_read_array_impl!(u8);
302 prim_read_array_impl!(u16);
303 prim_read_array_impl!(u32);
304 prim_read_array_impl!(u64);
305 prim_read_array_impl!(u128);
306
307 prim_read_array_impl!(f32);
308 prim_read_array_impl!(f64);
309}