From d6fb43adc15fe68061a5fe78e5423896a081acdb Mon Sep 17 00:00:00 2001 From: futile Date: Mon, 30 Dec 2024 18:06:33 +0000 Subject: [PATCH] implement r/w of process memory --- Cargo.toml | 1 + src/error.rs | 2 ++ src/process/handle.rs | 2 +- src/process/memory.rs | 51 ++++++++++++++++++++++++++++++++++++++ src/process/mod.rs | 1 + src/process/process.rs | 56 +++++++++++++++++++++++++++++++++++------- 6 files changed, 103 insertions(+), 10 deletions(-) create mode 100644 src/process/memory.rs diff --git a/Cargo.toml b/Cargo.toml index ba81461..c808abb 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -14,4 +14,5 @@ features = [ "Win32_Foundation", "Win32_System_Threading", "Win32_System_Diagnostics_ToolHelp", + "Win32_System_Diagnostics_Debug" ] diff --git a/src/error.rs b/src/error.rs index 28f31ef..eb206bb 100644 --- a/src/error.rs +++ b/src/error.rs @@ -10,4 +10,6 @@ pub enum Error { SnapshotError(String), #[error("failed to convert integer")] IntegerConversionError(#[from] std::num::TryFromIntError), + #[error("failed to access process memory")] + MemoryError(String), } diff --git a/src/process/handle.rs b/src/process/handle.rs index d210f58..b55c8a7 100644 --- a/src/process/handle.rs +++ b/src/process/handle.rs @@ -5,7 +5,7 @@ use windows::Win32::System::Threading::{ OpenProcess, PROCESS_ALL_ACCESS, PROCESS_VM_READ, PROCESS_VM_WRITE, }; -#[derive(Debug, Default)] +#[derive(Debug, Default, Clone)] pub struct Handle(pub HANDLE); impl Deref for Handle { diff --git a/src/process/memory.rs b/src/process/memory.rs new file mode 100644 index 0000000..2a37711 --- /dev/null +++ b/src/process/memory.rs @@ -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( + 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::(), + None, + ) { + Ok(()) => return Ok(()), + Err(why) => { + return Err(crate::Error::MemoryError(format!( + "failed to read memory: {why}" + ))); + } + }; + } +} + +pub fn write_process_memory( + 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::(), + None, + ) { + Ok(()) => return Ok(()), + Err(why) => { + return Err(crate::Error::MemoryError(format!( + "failed to write memory: {why}" + ))); + } + }; + } +} diff --git a/src/process/mod.rs b/src/process/mod.rs index 1d31196..86f55bd 100644 --- a/src/process/mod.rs +++ b/src/process/mod.rs @@ -1,4 +1,5 @@ mod handle; +mod memory; mod process; mod snapshot; diff --git a/src/process/process.rs b/src/process/process.rs index d72f0d9..988e773 100644 --- a/src/process/process.rs +++ b/src/process/process.rs @@ -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; -#[allow(dead_code)] -#[derive(Debug, Default)] +#[derive(Debug, Default, Clone)] pub struct Process { - name: String, - id: u32, - base_address: usize, - handle: Handle, + pub name: String, + pub id: u32, + pub base_address: usize, + pub handle: Handle, } +unsafe impl Send for Process {} +unsafe impl Sync for Process {} + #[derive(Display)] pub enum Identifier { Id(u32), @@ -32,12 +38,13 @@ impl Process { "failed to find a process with identifier `{identifier}`", ))); }; - let process = Self { + let mut process = Self { name: snapshot.name, id: snapshot.id, base_address: 0, handle: Handle::from_pid(snapshot.id)?, }; + process.base_address = process.module(&process.name)?.base_address; Ok(process) } @@ -50,7 +57,6 @@ impl Process { } pub fn module(&self, name: &str) -> Result { - dbg!(snapshot::Module::get_modules(self.id)?); let Some(module) = snapshot::Module::get_modules(self.id)? .into_iter() .find(|snapshot| snapshot.name == name) @@ -61,4 +67,36 @@ impl Process { }; Ok(module) } + + pub fn read_mem(&self, address: usize) -> Result { + let mut value = Default::default(); + read_process_memory(&self.handle, address, &mut value)?; + Ok(value) + } + + pub fn read_mem_from_ptr_chain(&self, chain: &[usize]) -> Result { + 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 { + 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(&self, address: usize, mut value: T) -> Result<(), crate::Error> { + write_process_memory(&self.handle, address, &mut value)?; + Ok(()) + } }