scanmem alternative with concurrent memory scanning
1use anyhow::Result;
2use libc::{c_void, iovec, process_vm_readv, process_vm_writev};
3use log::info;
4
5use crate::process::{MemoryRegion, Process};
6
7pub struct MemoryReader {
8 process: Process,
9}
10
11impl MemoryReader {
12 pub fn new(process: Process) -> Self {
13 Self { process }
14 }
15
16 pub fn read_memory(&self, address: usize, size: usize) -> Result<Vec<u8>> {
17 let mut buffer = vec![0u8; size];
18
19 let local_iov = iovec {
20 iov_base: buffer.as_mut_ptr() as *mut c_void,
21 iov_len: size,
22 };
23
24 let remote_iov = iovec {
25 iov_base: address as *mut c_void,
26 iov_len: size,
27 };
28
29 let result = unsafe {
30 process_vm_readv(
31 self.process.pid as libc::pid_t,
32 &local_iov,
33 1,
34 &remote_iov,
35 1,
36 0,
37 )
38 };
39
40 if result == -1 {
41 let err = std::io::Error::last_os_error();
42 anyhow::bail!("Failed to read memory at 0x{:x}: {}", address, err);
43 }
44
45 Ok(buffer)
46 }
47
48 pub fn write_memory(&self, address: usize, data: &[u8]) -> Result<()> {
49 let local_iov = iovec {
50 iov_base: data.as_ptr() as *mut c_void,
51 iov_len: data.len(),
52 };
53
54 let remote_iov = iovec {
55 iov_base: address as *mut c_void,
56 iov_len: data.len(),
57 };
58
59 let result = unsafe {
60 process_vm_writev(
61 self.process.pid as libc::pid_t,
62 &local_iov,
63 1,
64 &remote_iov,
65 1,
66 0,
67 )
68 };
69
70 if result == -1 {
71 let err = std::io::Error::last_os_error();
72 anyhow::bail!("Failed to write memory at 0x{:x}: {}", address, err);
73 }
74
75 info!("setting *0x{:x} to {:?}...", address, data);
76 Ok(())
77 }
78
79 pub fn read_region(&self, region: &MemoryRegion) -> Result<Vec<u8>> {
80 let size = region.end_addr - region.start_addr;
81 self.read_memory(region.start_addr, size)
82 }
83}