1use pete::Tracee;
2use std::{
3 cell::RefCell,
4 ffi::{c_char, CStr, CString},
5 fs::read,
6 mem::size_of,
7 rc::Rc,
8 thread::sleep,
9 time::Duration,
10};
11use tracing::warn;
12
13pub struct RemoteMem {
14 base: usize,
15 offset: usize,
16 max: usize,
17}
18
19impl RemoteMem {
20 fn new(pid: i32) -> Self {
21 let mut retry = 5;
22 loop {
23 match read(inter_mem::mem_block_info_file().with_extension(pid.to_string()))
24 .map(|b| usize::from_le_bytes(b.try_into().unwrap_or_default()))
25 {
26 Err(e) => {
27 if retry >= 0 {
28 warn!("remote memory not ready try again, error: {:?}", e);
29 retry -= 1;
30 sleep(Duration::from_millis(50));
31 continue;
32 } else {
33 panic!("remote memory can not setup");
34 }
35 }
36 Ok(base) => {
37 return Self {
38 base,
39 offset: 0,
40 max: inter_mem::MEM_BLOCK_SIZE,
41 };
42 }
43 }
44 }
45 }
46}
47
48pub trait Read {
49 type InnerType;
50
51 fn read(remote: &mut Tracee, u: u64) -> MayBePtr<Self::InnerType>;
52}
53
54pub fn read_ptr_to_ptr(p: *const *const c_char) -> Vec<Vec<u8>> {
56 let mut offset = 0usize;
57 let mut result = Vec::new();
58 let mut buf = Vec::new();
59 loop {
60 let b: u8 = unsafe { std::ptr::read((p as usize + offset) as *const u8) };
61 if buf.is_empty() && b == 0 {
62 break;
63 }
64
65 buf.push(b);
66 if b == 0 {
67 result.push(buf);
68 buf = Vec::new();
69 }
70
71 offset += 1;
72 }
73
74 result
75}
76
77pub fn write_ptr_to_ptr(p: *const *const c_char, v: Vec<Vec<u8>>) {
79 let addr = p as usize;
80 let mut offset = 0usize;
81 v.into_iter().for_each(|x| unsafe {
82 std::ptr::copy_nonoverlapping(x.as_ptr() as *const u8, (addr + offset) as *mut u8, x.len());
83 offset += x.len()
84 });
85}
86
87pub trait Number {
88 fn from_u64(u: u64) -> Self;
89 fn to_u64(self) -> u64;
90}
91
92impl Read for *const *const c_char {
93 type InnerType = Vec<u8>;
94
95 fn read(remote: &mut Tracee, u: u64) -> MayBePtr<Self::InnerType> {
96 let mut mbp = MayBePtr {
97 inner: Vec::new(),
98 origin: u,
99 };
100
101 let mut offset = 0usize;
102 loop {
103 let mut buf = vec![0; size_of::<u64>()];
104 let n = remote
105 .read_memory_mut(u + offset as u64, &mut buf)
106 .unwrap_or_default();
107 let ptr = &buf[..n];
108 offset += size_of::<u64>();
109 let pdata =
110 remote.read_bytes_with_nul(u64::from_le_bytes(ptr.try_into().unwrap_or_default()));
111 if pdata.is_empty() {
112 mbp.inner.push(b'\0');
113 break;
114 }
115
116 mbp.inner.extend(pdata);
117 }
118
119 mbp
120 }
121}
122
123trait LendingIterator {
124 type Item<'a>
125 where
126 Self: 'a;
127 fn next<'a>(&'a mut self) -> Option<Self::Item<'a>>;
128}
129
130struct MayBePtrIter<'a> {
131 offset: usize,
132 inner: &'a MayBePtr<Vec<u8>>,
133}
134
135impl MayBePtr<Vec<u8>> {
136 fn iter(&self) -> MayBePtrIter {
137 MayBePtrIter {
138 offset: 0,
139 inner: self,
140 }
141 }
142}
143
144impl<'a> LendingIterator for MayBePtrIter<'a> {
145 type Item<'i> = &'i [u8] where Self: 'i;
146
147 fn next<'i>(&'i mut self) -> Option<Self::Item<'i>> {
148 let mut next = 0;
149 while let Some(v) = self.inner.inner.get(self.offset + next) {
150 if *v == 0 {
151 let offset = self.offset;
152 self.offset += next + 1;
153 return Some(&self.inner.inner[offset..=offset + next]);
154 }
155
156 next += 1;
157 }
158
159 None
160 }
161}
162
163impl Write<*const *const c_char> for MayBePtr<Vec<u8>> {
164 fn write(
165 &mut self,
166 remote: &mut Tracee,
167 _remote_mem: Rc<RefCell<Option<RemoteMem>>>,
168 v: Option<*const *const c_char>,
169 ) -> Option<u64> {
170 if let Some(v) = v {
171 if self.inner.as_ptr() != v as *const u8 {
172 panic!("*const *const c_char doesn't support change pointer");
173 }
174
175 let mut offset = 0usize;
176 let mut iter = self.iter();
177 loop {
178 let mut buf = vec![0; size_of::<u64>()];
179 let n = remote
180 .read_memory_mut(self.origin + offset as u64, &mut buf)
181 .unwrap_or_default();
182 let ptr = &buf[..n];
183 offset += size_of::<u64>();
184 let addr = u64::from_le_bytes(ptr.try_into().unwrap_or_default());
185 if addr != 0 {
186 let next = iter.next();
187 if let Some(next) = next {
188 remote
189 .write_memory(addr, next)
190 .expect("write remote memory for ptr to ptr error");
191 } else {
192 break;
193 }
194 } else {
195 break;
196 }
197 }
198
199 Some(self.origin)
200 } else {
201 None
202 }
203 }
204}
205
206impl Ptr<*const *const c_char> for MayBePtr<Vec<u8>> {
207 fn get(&self) -> *const *const c_char {
208 self.inner.as_ptr() as *const *const c_char
209 }
210}
211
212trait ReadRemote {
213 fn read_bytes_with_nul(&mut self, addr: u64) -> Vec<u8>;
214}
215
216impl ReadRemote for Tracee {
217 fn read_bytes_with_nul(&mut self, addr: u64) -> Vec<u8> {
218 let mut data = Vec::new();
219 if addr != 0 {
220 let mut offset = 0usize;
221 loop {
222 let mut buf = vec![0; size_of::<u64>()];
223 let n = self
224 .read_memory_mut(addr + offset as u64, &mut buf)
225 .unwrap_or_default();
226 if n == 0 {
227 break;
228 }
229 let buf = &buf[..n];
230 if let Some(i) = buf.iter().position(|x| *x == b'\0') {
231 data.extend(&buf[..=i]);
232 break;
233 }
234
235 offset += size_of::<u64>();
236 data.extend(buf);
237 }
238 }
239 data
240 }
241}
242
243macro_rules! ptr_impl {
244 ($t: ty) => {
245 impl Read for $t {
246 type InnerType = Vec<u8>;
247
248 fn read(remote: &mut Tracee, u: u64) -> MayBePtr<Vec<u8>> {
249 MayBePtr {
250 inner: remote.read_bytes_with_nul(u),
251 origin: u,
252 }
253 }
254 }
255
256 impl Ptr<$t> for MayBePtr<Vec<u8>> {
257 fn get(&self) -> $t {
258 self.inner.as_ptr() as $t
259 }
260 }
261
262 impl Write<$t> for MayBePtr<Vec<u8>> {
263 fn write(
264 &mut self,
265 remote: &mut Tracee,
266 remote_mem: Rc<RefCell<Option<RemoteMem>>>,
267 v: Option<$t>,
268 ) -> Option<u64> {
269 if let Some(v) = v {
270 if self.inner.as_ptr() == v as *const u8 {
271 remote
273 .write_memory(self.origin, &self.inner)
274 .expect("write origin memory error");
275 Some(self.origin)
276 } else {
277 let c = unsafe { CStr::from_ptr(v).to_bytes_with_nul() };
279 let remote_addr = alloc_remote_mem(remote, remote_mem, c.len()) as u64;
280 remote
281 .write_memory(remote_addr, &c)
282 .expect("write remote memory error");
283 drop(unsafe { CString::from_raw(v as *mut c_char) });
284 Some(remote_addr)
285 }
286 } else {
287 None
288 }
289 }
290 }
291 };
292}
293
294fn alloc_remote_mem(
295 remote: &mut Tracee,
296 remote_mem: Rc<RefCell<Option<RemoteMem>>>,
297 size: usize,
298) -> usize {
299 let mut mem = remote_mem.borrow_mut();
300 if mem.is_none() {
301 *mem = Some(RemoteMem::new(remote.pid.as_raw()));
302 }
303
304 let mut mem = mem.as_mut().unwrap();
305 if size > mem.max {
306 panic!("changed content is too large");
307 }
308
309 let addr = mem.base + mem.offset;
310 if mem.offset + size > mem.max {
311 mem.offset = 0;
312 } else {
313 mem.offset += size;
314 }
315
316 addr
317}
318
319pub trait Write<T> {
320 fn write(
321 &mut self,
322 remote: &mut Tracee,
323 remote_mem: Rc<RefCell<Option<RemoteMem>>>,
324 v: Option<T>,
325 ) -> Option<u64>;
326}
327
328macro_rules! not_ptr_impl {
329 ($t: ty) => {
330 impl Read for $t {
331 type InnerType = $t;
332
333 fn read(_: &mut Tracee, u: u64) -> MayBePtr<Self::InnerType> {
334 MayBePtr {
335 inner: u as $t,
336 origin: u,
337 }
338 }
339 }
340
341 impl Write<$t> for MayBePtr<$t> {
342 fn write(
343 &mut self,
344 _remote: &mut Tracee,
345 _remote_mem: Rc<RefCell<Option<RemoteMem>>>,
346 v: Option<$t>,
347 ) -> Option<u64> {
348 v.map(|x| x as u64)
349 }
350 }
351
352 impl Ptr<$t> for MayBePtr<$t> {
353 fn get(&self) -> $t {
354 self.inner
355 }
356 }
357
358 impl Number for $t {
359 fn from_u64(u: u64) -> Self {
360 u as Self
361 }
362
363 fn to_u64(self) -> u64 {
364 self as u64
365 }
366 }
367 };
368}
369
370ptr_impl!(*const c_char);
371ptr_impl!(*mut c_char);
372not_ptr_impl!(i8);
373not_ptr_impl!(i16);
374not_ptr_impl!(i32);
375not_ptr_impl!(i64);
376not_ptr_impl!(isize);
377not_ptr_impl!(u8);
378not_ptr_impl!(u16);
379not_ptr_impl!(u32);
380not_ptr_impl!(u64);
381not_ptr_impl!(usize);
382
383pub trait Ptr<T> {
384 fn get(&self) -> T;
385}
386
387pub struct MayBePtr<T> {
388 inner: T,
389 origin: u64,
390}