memory_rs/internal/
memory_region.rs1use crate::error::*;
2use crate::internal::memory;
3use anyhow::Result;
4
5#[derive(Debug)]
6pub struct MemoryRegion {
7 pub start_address: usize,
8 pub size: usize,
9 is_safe: bool,
10}
11
12impl MemoryRegion {
13 pub fn new(start_address: usize, size: usize, is_safe: bool) -> Result<Self> {
14 let memory_region = Self {
15 start_address,
16 size,
17 is_safe,
18 };
19
20 memory::check_valid_region(start_address, size)?;
22
23 Ok(memory_region)
24 }
25
26 fn check_valid_region(&self) -> Result<()> {
27 if !self.is_safe {
28 memory::check_valid_region(self.start_address, self.size)?;
29 }
30
31 Ok(())
32 }
33
34 pub fn scan_aob(&self, pat: &memory::MemoryPattern) -> Result<Option<usize>> {
35 self.check_valid_region()?;
36
37 let data = unsafe { std::slice::from_raw_parts(self.start_address as *mut u8, self.size) };
38 let index = data.windows(pat.size).position(pat.pattern);
39
40 match index {
41 Some(addr) => Ok(Some(self.start_address + addr)),
42 None => Ok(None),
43 }
44 }
45
46 pub fn scan_aob_all_matches(&self, pat: &memory::MemoryPattern) -> Result<Vec<usize>> {
47 self.check_valid_region()?;
48 let data = unsafe { std::slice::from_raw_parts(self.start_address as *mut u8, self.size) };
49 let mut iter = data.windows(pat.size);
50 let mut matches = Vec::new();
51
52 loop {
53 let val = iter.position(pat.pattern);
54 if val.is_none() {
55 break;
56 }
57
58 let val = val.unwrap();
59 match matches.last() {
60 Some(&last_val) => matches.push(val + last_val + 0x1),
61 None => matches.push(self.start_address + val),
62 };
63 }
64
65 Ok(matches)
66 }
67
68 pub fn scan_aob_all_matches_aligned(
70 &self,
71 pat: &memory::MemoryPattern,
72 align: Option<usize>,
73 ) -> Result<Vec<usize>> {
74 self.check_valid_region()?;
75 let data = unsafe { std::slice::from_raw_parts(self.start_address as *mut u8, self.size) };
76 let align = align.unwrap_or(4);
77 let padding = (align - (pat.size % align)) % align;
78 let chunk_size = pat.size + padding;
79 let mut iter = data.chunks_exact(chunk_size);
80 let mut matches = Vec::new();
81
82 loop {
83 let val = iter.position(|x| pat.scan(&x[..pat.size]));
84 if val.is_none() {
85 break;
86 }
87
88 let val = val.unwrap();
89 match matches.last() {
90 Some(&last_val) => matches.push((val + 0x1) * chunk_size + last_val),
91 None => matches.push(self.start_address + val),
92 };
93 }
94
95 Ok(matches)
96 }
97
98 pub fn scan_aligned_value<T>(&self, value: T) -> Result<Vec<usize>>
99 where
100 T: Copy + PartialEq,
101 {
102 self.check_valid_region()?;
103 let size_type = std::mem::size_of::<T>();
104 let mut matches = Vec::new();
105
106 if self.size / size_type == 0 {
107 return Err(Error::new(
108 ErrorType::Internal,
109 "The space to scan is smaller than the type size".into(),
110 )
111 .into());
112 }
113
114 let data = unsafe {
115 std::slice::from_raw_parts(self.start_address as *mut T, self.size / size_type)
116 };
117 let mut iter = data.iter();
118
119 let match_function = |&x| x == value;
120
121 while let Some(val) = iter.position(match_function) {
122 match matches.last() {
123 Some(&last_val) => matches.push((val + 0x1) * size_type + last_val),
124 None => matches.push((val * size_type) + self.start_address),
125 };
126 }
127
128 Ok(matches)
129 }
130}