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! prim_read_impl {
16 ($t: ident) => {
17 paste! {
18 fn [<read_ $t>](
19 &self,
20 addr: i32
21 ) -> Result<$t, ProcessError> {
22 let mut bytes = [0u8; std::mem::size_of::<$t>()];
23 self.read(addr, std::mem::size_of::<$t>(), &mut bytes)?;
24
25 Ok($t::from_le_bytes(bytes))
26 }
27 }
28 };
29}
30
31macro_rules! prim_read_array_impl {
32 ($t: ident) => {
33 paste! {
34 fn [<read_ $t _array>](
35 &self,
36 addr: i32,
37 buff: &mut Vec<$t>
38 ) -> Result<(), ProcessError> {
39 let items_ptr = self.read_i32(addr + 4)?;
40 let size = self.read_i32(addr + 12)? as usize;
41
42 buff.resize(size, 0 as $t);
43
44 let byte_buff = unsafe { std::slice::from_raw_parts_mut(
45 buff.as_mut_ptr() as *mut u8,
46 buff.len() * std::mem::size_of::<$t>()
47 ) };
48
49
50 self.read(
51 items_ptr + 8,
52 size * std::mem::size_of::<$t>(),
53 byte_buff
54 )?;
55
56 Ok(())
57 }
58 }
59 };
60}
61
62pub struct Process {
63 #[cfg(target_os = "linux")]
64 pub pid: i32,
65
66 #[cfg(target_os = "windows")]
67 pub pid: u32,
68
69 #[cfg(target_os = "windows")]
70 pub handle: HANDLE,
71
72 pub maps: Vec<MemoryRegion>,
73
74 pub executable_dir: Option<PathBuf>,
75}
76
77pub trait ProcessTraits
78where
79 Self: Sized,
80{
81 fn initialize(
90 proc_name: &str,
91 exclude: &[&str],
92 ) -> Result<Self, ProcessError>;
93
94 fn find_process(
103 proc_name: &str,
104 exclude: &[&str],
105 ) -> Result<Self, ProcessError>;
106
107 fn read_regions(self) -> Result<Self, ProcessError>;
108
109 fn read_signature(&self, sign: &Signature) -> Result<i32, ProcessError>;
110
111 fn read(
112 &self,
113 addr: i32,
114 len: usize,
115 buff: &mut [u8],
116 ) -> Result<(), ProcessError>;
117
118 fn read_uleb128(&self, mut addr: i32) -> Result<u64, ProcessError> {
119 let mut value: u64 = 0;
120 let mut bytes_read = 0;
121
122 loop {
123 let byte = self.read_u8(addr)?;
124 addr += 1;
125
126 let byte_value = (byte & 0b0111_1111) as u64;
127 value |= byte_value << (7 * bytes_read);
128
129 bytes_read += 1;
130
131 if (byte & !0b0111_1111) == 0 {
132 break;
133 }
134 }
135
136 Ok(value)
137 }
138
139 fn read_string(&self, addr: i32) -> Result<String, ProcessError> {
140 let mut addr = self.read_i32(addr)?;
141 let len = self.read_u32(addr + 0x4)? as usize;
143 addr += 0x8;
144
145 let mut buff = vec![0u16; len];
146
147 let byte_buff = unsafe {
148 std::slice::from_raw_parts_mut(
149 buff.as_mut_ptr() as *mut u8,
150 buff.len() * 2,
151 )
152 };
153
154 self.read(addr, byte_buff.len(), byte_buff)?;
155
156 Ok(String::from_utf16_lossy(&buff))
157 }
158
159 prim_read_impl!(i8);
160 prim_read_impl!(i16);
161 prim_read_impl!(i32);
162 prim_read_impl!(i64);
163 prim_read_impl!(i128);
164
165 prim_read_impl!(u8);
166 prim_read_impl!(u16);
167 prim_read_impl!(u32);
168 prim_read_impl!(u64);
169 prim_read_impl!(u128);
170
171 prim_read_impl!(f32);
172 prim_read_impl!(f64);
173
174 prim_read_array_impl!(i8);
175 prim_read_array_impl!(i16);
176 prim_read_array_impl!(i32);
177 prim_read_array_impl!(i64);
178 prim_read_array_impl!(i128);
179
180 prim_read_array_impl!(u8);
181 prim_read_array_impl!(u16);
182 prim_read_array_impl!(u32);
183 prim_read_array_impl!(u64);
184 prim_read_array_impl!(u128);
185
186 prim_read_array_impl!(f32);
187 prim_read_array_impl!(f64);
188}