83 lines
2.1 kB
1
use anyhow::Result;
2
use libc::{c_void, iovec, process_vm_readv, process_vm_writev};
3
use log::info;
4
5
use crate::process::{MemoryRegion, Process};
6
7
pub struct MemoryReader {
8
process: Process,
9
}
10
11
impl 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
}
84