Skip to main content

procmod_core/
process.rs

1use crate::error::Result;
2use crate::module::Module;
3use crate::platform;
4use crate::region::MemoryRegion;
5
6/// A handle to an external process for memory operations.
7pub struct Process {
8    inner: platform::ProcessHandle,
9    pid: u32,
10}
11
12impl Process {
13    /// Attach to a running process by its PID.
14    pub fn attach(pid: u32) -> Result<Self> {
15        let inner = platform::attach(pid)?;
16        Ok(Self { inner, pid })
17    }
18
19    /// Returns the PID of the attached process.
20    pub fn pid(&self) -> u32 {
21        self.pid
22    }
23
24    /// Read a typed value from the target process at the given address.
25    ///
26    /// # Safety
27    ///
28    /// `T` must be valid for any bit pattern. Primitive numeric types (`u8`, `i32`,
29    /// `f32`, `[u8; N]`, etc.) are safe. Types with validity invariants (`bool`,
30    /// `char`, enums, references) will cause undefined behavior if the remote
31    /// memory contains an invalid representation.
32    pub unsafe fn read<T: Copy>(&self, address: usize) -> Result<T> {
33        let mut value = std::mem::MaybeUninit::<T>::uninit();
34        let buf =
35            std::slice::from_raw_parts_mut(value.as_mut_ptr() as *mut u8, std::mem::size_of::<T>());
36        platform::read_bytes(&self.inner, address, buf)?;
37        Ok(value.assume_init())
38    }
39
40    /// Write a typed value to the target process at the given address.
41    pub fn write<T: Copy>(&self, address: usize, value: &T) -> Result<()> {
42        let buf = unsafe {
43            std::slice::from_raw_parts(value as *const T as *const u8, std::mem::size_of::<T>())
44        };
45        platform::write_bytes(&self.inner, address, buf)
46    }
47
48    /// Read raw bytes from the target process.
49    pub fn read_bytes(&self, address: usize, len: usize) -> Result<Vec<u8>> {
50        let mut buf = vec![0u8; len];
51        platform::read_bytes(&self.inner, address, &mut buf)?;
52        Ok(buf)
53    }
54
55    /// Write raw bytes to the target process.
56    pub fn write_bytes(&self, address: usize, bytes: &[u8]) -> Result<()> {
57        platform::write_bytes(&self.inner, address, bytes)
58    }
59
60    /// List all loaded modules in the target process.
61    pub fn modules(&self) -> Result<Vec<Module>> {
62        platform::modules(&self.inner, self.pid)
63    }
64
65    /// List all memory regions in the target process.
66    pub fn regions(&self) -> Result<Vec<MemoryRegion>> {
67        platform::regions(&self.inner, self.pid)
68    }
69}