implement r/w of process memory
This commit is contained in:
@@ -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"
|
||||||
]
|
]
|
||||||
|
|||||||
@@ -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),
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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 {
|
||||||
|
|||||||
@@ -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,4 +1,5 @@
|
|||||||
mod handle;
|
mod handle;
|
||||||
|
mod memory;
|
||||||
mod process;
|
mod process;
|
||||||
mod snapshot;
|
mod snapshot;
|
||||||
|
|
||||||
|
|||||||
+47
-9
@@ -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(())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user