1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
use crate::error::{Error, Result};
use crate::memory::{error::MemoryError, error::MemoryResult, MemoryManipulation};
use crate::process::Process;
use sysinfo::{ProcessExt, System, SystemExt};
#[cfg(target_os = "linux")]
use {
nix::{
sys::uio::{self, IoVec, RemoteIoVec},
unistd::Pid,
},
std::{
fs::OpenOptions,
io::{prelude::*, SeekFrom},
},
};
#[derive(Default, Debug, Copy, Clone, PartialEq, Eq)]
pub struct ExternalManipulator {
pid: i32,
}
impl ExternalManipulator {
pub fn new_unchecked(pid: i32) -> ExternalManipulator {
ExternalManipulator { pid }
}
pub fn new(name: &str) -> Result<ExternalManipulator> {
let system = System::new_all();
let process_list = system.get_process_by_name(name);
if !process_list.is_empty() {
let pid = process_list[0].pid();
return Ok(ExternalManipulator { pid });
}
Err(Error::ProcessNotFound(name.to_owned()))
}
}
#[cfg(target_os = "linux")]
impl MemoryManipulation for ExternalManipulator {
fn read(&self, address: usize, buf: &mut [u8]) -> MemoryResult<usize> {
let remote = [RemoteIoVec {
base: address,
len: std::mem::size_of_val(buf),
}];
let local = [IoVec::from_mut_slice(buf)];
match uio::process_vm_readv(Pid::from_raw(self.pid), &local, &remote) {
Ok(x) if x > 0 => Ok(x),
Err(e) => Err(MemoryError::ReadError(e.to_string())),
_ => Err(MemoryError::ReadError("No bytes read".to_owned())),
}
}
fn write(&self, address: usize, payload: &[u8]) -> MemoryResult<usize> {
let remote = [RemoteIoVec {
base: address,
len: std::mem::size_of_val(payload),
}];
let local = [IoVec::from_slice(payload)];
match uio::process_vm_writev(Pid::from_raw(self.pid), &local, &remote) {
Ok(x) if x > 0 => Ok(x),
Err(e) => Err(MemoryError::WriteError(e.to_string())),
_ => Err(MemoryError::WriteError("No bytes written".to_owned())),
}
}
}
impl Process for ExternalManipulator {
fn pid(&self) -> i32 {
self.pid
}
}
#[cfg(target_os = "linux")]
#[derive(Default, Debug, Copy, Clone, PartialEq, Eq)]
pub struct AnonManipulator {
pid: i32,
}
impl AnonManipulator {
pub fn new(name: &str) -> Result<AnonManipulator> {
let system = System::new_all();
let process_list = system.get_process_by_name(name);
if !process_list.is_empty() {
let pid = process_list[0].pid();
return Ok(AnonManipulator { pid });
}
Err(Error::ProcessNotFound(name.to_owned()))
}
}
#[cfg(target_os = "linux")]
impl MemoryManipulation for AnonManipulator {
fn read(&self, address: usize, buf: &mut [u8]) -> MemoryResult<usize> {
let mut mem_file = OpenOptions::new()
.read(true)
.open(format!("/proc/{}/mem", self.pid))?;
mem_file.seek(SeekFrom::Start(address as u64))?;
mem_file.read_exact(buf)?;
Ok(buf.len())
}
fn write(&self, address: usize, payload: &[u8]) -> MemoryResult<usize> {
let mut mem_file = OpenOptions::new()
.write(true)
.append(false)
.open(format!("/proc/{}/mem", self.pid))?;
mem_file.seek(SeekFrom::Start(address as u64))?;
mem_file.write_all(payload)?;
Ok(payload.len())
}
}
impl Process for AnonManipulator {
fn pid(&self) -> i32 {
self.pid
}
}