proc_mem_rs/process/
module.rs1use regex::bytes::Regex;
2
3use crate::ProcMemError;
4
5pub struct Signature {
7 pub name: String,
8 pub pattern: String,
9 pub offsets: Vec<isize>,
11 pub extra: isize,
13 pub relative: bool,
15 pub rip_relative: bool,
17 pub rip_offset: isize,
19}
20
21#[derive(Debug)]
23pub struct Module {
24 module_name: String,
25 module_path: String,
26 process_id: u32,
27 process_iswow64: bool,
28 module_baseaddr: usize,
29 module_basesize: usize,
30 module_data: Vec<u8>
31}
32
33impl Module {
34 pub fn new(mname: String, mpath: String, pid: u32, mbaseaddr: usize, mbasesize: usize, proc: &crate::Process) -> Self {
35 Module {
36 module_name: mname,
37 module_path: mpath,
38 process_id: pid,
39 process_iswow64: proc.iswow64(),
40 module_baseaddr: mbaseaddr,
41 module_basesize: mbasesize,
42 module_data: proc.read_module(mbaseaddr, mbasesize).unwrap_or_default(),
43 }
44 }
45
46 pub fn name(&self) -> &str {&self.module_name}
47 pub fn path(&self) -> &str {&self.module_path}
48 pub fn pid(&self) -> &u32 {&self.process_id}
49 pub fn base_address(&self) -> usize {self.module_baseaddr}
50 pub fn base_size(&self) -> &usize {&self.module_basesize}
51 pub fn data(&self) -> &Vec<u8>{&self.module_data}
52
53 pub fn get_raw<T: Copy>(&self, mut o: usize, is_relative: bool) -> Option<T> {
54 if !is_relative {
55 o -= self.module_baseaddr;
56 }
57 if o + std::mem::size_of::<T>() >= self.module_data.len() {
58 return None;
59 }
60 let ptr = self.module_data.get(o)?;
61 let raw: T = unsafe { std::mem::transmute_copy(ptr) };
62 Some(raw)
63 }
64
65
66 pub fn find_signature(&self, sig: &Signature) -> Result<usize, ProcMemError> {
83 let mut addr = Self::find_pattern(&self.module_data,&sig.pattern).ok_or(ProcMemError::SignatureNotFound)?;
84
85 for (_i,o) in sig.offsets.iter().enumerate() {
86 let pos = (addr as isize).wrapping_add(*o) as usize;
87 let data = self.module_data.get(pos).ok_or_else(|| {
88 ProcMemError::AddressOutOfBounds
89 })?;
90 let tmp = if self.process_iswow64 {
91 let raw: u32 = unsafe {(data as *const u8).cast::<u32>().read_unaligned()};
92 raw as usize
93 } else {
94 let raw: u64 = unsafe {(data as *const u8).cast::<u64>().read_unaligned()};
95 raw as usize
96 };
97
98 addr = tmp.wrapping_sub(self.module_baseaddr);
99 }
100
101 if sig.rip_relative {
102 addr = (addr as isize).wrapping_add(sig.rip_offset) as usize;
103
104 let rip: u32 = self
105 .get_raw(addr, true)
106 .ok_or(ProcMemError::RIPRelativeFailed)?;
107
108 addr = addr.wrapping_add(rip as usize + ::std::mem::size_of::<u32>());
109 }
110
111 addr = (addr as isize).wrapping_add(sig.extra) as usize;
112 if !sig.relative {
113 addr = addr.wrapping_add(self.module_baseaddr);
114 }
115
116 Ok(addr)
117 }
118
119
120 fn generate_regex(raw: &str) -> Option<Regex> {
121 let mut res = raw
122 .to_string()
123 .split_whitespace()
124 .map(|x| match &x {
125 &"?" => ".".to_string(),
126 x => format!("\\x{}", x),
127 })
128 .collect::<Vec<_>>()
129 .join("");
130 res.insert_str(0, "(?s-u)");
131 Regex::new(&res).ok()
132 }
133
134 fn find_pattern(data: &[u8], pattern: &str) -> Option<usize> {
135 Self::generate_regex(pattern)
136 .and_then(|r| r.find(data))
137 .and_then(|m| Some(m.start()))
138 }
139}