implement r/w of process memory

This commit is contained in:
2024-12-30 18:06:33 +00:00
parent ff7674615d
commit d6fb43adc1
6 changed files with 103 additions and 10 deletions
+1
View File
@@ -14,4 +14,5 @@ features = [
"Win32_Foundation", "Win32_Foundation",
"Win32_System_Threading", "Win32_System_Threading",
"Win32_System_Diagnostics_ToolHelp", "Win32_System_Diagnostics_ToolHelp",
"Win32_System_Diagnostics_Debug"
] ]
+2
View File
@@ -10,4 +10,6 @@ pub enum Error {
SnapshotError(String), SnapshotError(String),
#[error("failed to convert integer")] #[error("failed to convert integer")]
IntegerConversionError(#[from] std::num::TryFromIntError), IntegerConversionError(#[from] std::num::TryFromIntError),
#[error("failed to access process memory")]
MemoryError(String),
} }
+1 -1
View File
@@ -5,7 +5,7 @@ use windows::Win32::System::Threading::{
OpenProcess, PROCESS_ALL_ACCESS, PROCESS_VM_READ, PROCESS_VM_WRITE, OpenProcess, PROCESS_ALL_ACCESS, PROCESS_VM_READ, PROCESS_VM_WRITE,
}; };
#[derive(Debug, Default)] #[derive(Debug, Default, Clone)]
pub struct Handle(pub HANDLE); pub struct Handle(pub HANDLE);
impl Deref for Handle { impl Deref for Handle {
+51
View File
@@ -0,0 +1,51 @@
use super::handle::Handle;
use std::ffi::c_void;
use windows::Win32::System::Diagnostics::Debug::{ReadProcessMemory, WriteProcessMemory};
pub fn read_process_memory<T>(
handle: &Handle,
address: usize,
value: &mut T,
) -> Result<(), crate::Error> {
unsafe {
match ReadProcessMemory(
handle.0,
address as *const c_void,
value as *mut T as *mut c_void,
size_of::<T>(),
None,
) {
Ok(()) => return Ok(()),
Err(why) => {
return Err(crate::Error::MemoryError(format!(
"failed to read memory: {why}"
)));
}
};
}
}
pub fn write_process_memory<T>(
handle: &Handle,
address: usize,
value: &mut T,
) -> Result<(), crate::Error> {
unsafe {
match WriteProcessMemory(
handle.0,
address as *const c_void,
value as *mut T as *mut c_void,
size_of::<T>(),
None,
) {
Ok(()) => return Ok(()),
Err(why) => {
return Err(crate::Error::MemoryError(format!(
"failed to write memory: {why}"
)));
}
};
}
}
+1
View File
@@ -1,4 +1,5 @@
mod handle; mod handle;
mod memory;
mod process; mod process;
mod snapshot; mod snapshot;
+47 -9
View File
@@ -1,16 +1,22 @@
use super::{handle::Handle, snapshot}; use super::{
handle::Handle,
memory::{read_process_memory, write_process_memory},
snapshot,
};
use derive_more::derive::Display; use derive_more::derive::Display;
#[allow(dead_code)] #[derive(Debug, Default, Clone)]
#[derive(Debug, Default)]
pub struct Process { pub struct Process {
name: String, pub name: String,
id: u32, pub id: u32,
base_address: usize, pub base_address: usize,
handle: Handle, pub handle: Handle,
} }
unsafe impl Send for Process {}
unsafe impl Sync for Process {}
#[derive(Display)] #[derive(Display)]
pub enum Identifier { pub enum Identifier {
Id(u32), Id(u32),
@@ -32,12 +38,13 @@ impl Process {
"failed to find a process with identifier `{identifier}`", "failed to find a process with identifier `{identifier}`",
))); )));
}; };
let process = Self { let mut process = Self {
name: snapshot.name, name: snapshot.name,
id: snapshot.id, id: snapshot.id,
base_address: 0, base_address: 0,
handle: Handle::from_pid(snapshot.id)?, handle: Handle::from_pid(snapshot.id)?,
}; };
process.base_address = process.module(&process.name)?.base_address;
Ok(process) Ok(process)
} }
@@ -50,7 +57,6 @@ impl Process {
} }
pub fn module(&self, name: &str) -> Result<snapshot::Module, crate::Error> { pub fn module(&self, name: &str) -> Result<snapshot::Module, crate::Error> {
dbg!(snapshot::Module::get_modules(self.id)?);
let Some(module) = snapshot::Module::get_modules(self.id)? let Some(module) = snapshot::Module::get_modules(self.id)?
.into_iter() .into_iter()
.find(|snapshot| snapshot.name == name) .find(|snapshot| snapshot.name == name)
@@ -61,4 +67,36 @@ impl Process {
}; };
Ok(module) Ok(module)
} }
pub fn read_mem<T: Default>(&self, address: usize) -> Result<T, crate::Error> {
let mut value = Default::default();
read_process_memory(&self.handle, address, &mut value)?;
Ok(value)
}
pub fn read_mem_from_ptr_chain<T: Default>(&self, chain: &[usize]) -> Result<T, crate::Error> {
let mut chain = chain.to_vec();
let mut address = chain.remove(0);
while chain.len() > 1 {
address += chain.remove(0);
address = self.read_mem(address)?;
}
let value = self.read_mem(address + chain.remove(0))?;
Ok(value)
}
pub fn get_addr_from_ptr_chain(&self, chain: &[usize]) -> Result<usize, crate::Error> {
let mut chain = chain.to_vec();
let mut address = chain.remove(0);
while chain.len() > 1 {
address += chain.remove(0);
address = self.read_mem(address)?;
}
Ok(address + chain.remove(0))
}
pub fn write_mem<T: Default>(&self, address: usize, mut value: T) -> Result<(), crate::Error> {
write_process_memory(&self.handle, address, &mut value)?;
Ok(())
}
} }