toy_arms/internal/
internal.rs1use std::mem::{size_of, zeroed};
2use std::str::Utf8Error;
3use winapi::shared::minwindef::{DWORD, FARPROC, HMODULE, MAX_PATH};
4use winapi::um::libloaderapi::GetProcAddress;
5use winapi::um::processthreadsapi::GetCurrentProcess;
6use winapi::um::psapi::{EnumProcessModules, GetModuleBaseNameA, GetModuleInformation, MODULEINFO};
7use winapi::um::winnt::{CHAR, LPSTR};
8use crate::{cast};
9use crate::utils_common::read_null_terminated_string;
10use crate::internal::{
11 utils::get_module_handle,
12 pattern_scan::boyer_moore_horspool,
13};
14
15pub enum TAInternalError {
16 GetAllModuleHandlesFailed,
17}
18
19#[derive(Debug)]
20pub struct Module<'a> {
21 pub module_name: &'a str,
22 pub module_handle: HMODULE,
23 pub module_size: u32,
24 pub module_base_address: usize,
25}
26
27impl<'a> Default for Module<'a> {
28 fn default() -> Self {
29 Module {
30 module_name: "",
31 module_handle: 0x0 as HMODULE,
32 module_size: 0,
33 module_base_address: 0,
34 }
35 }
36}
37
38impl<'a> Module<'a> {
39 pub fn from_module_name(module_name: &'a str) -> Option<Self> {
40 let module_handle: HMODULE = match get_module_handle(module_name) {
41 Some(e) => e,
42 None => return None,
43 };
44 unsafe {
45 let mut module_info: MODULEINFO = zeroed::<MODULEINFO>();
46 GetModuleInformation(
47 GetCurrentProcess(),
48 module_handle,
49 &mut module_info,
50 size_of::<MODULEINFO>() as u32,
51 );
52 Some(Module {
53 module_name,
54 module_handle,
55 module_base_address: module_info.lpBaseOfDll as usize,
56 module_size: module_info.SizeOfImage,
57 })
58 }
59 }
60
61 pub fn read<T>(&self, address: u32) -> *mut T {
64 cast!(mut self.module_handle as usize + address as usize, T)
65 }
66
67 pub fn read_string(&self, address: i32) -> Result<String, Utf8Error> {
70 unsafe { read_null_terminated_string(self.module_handle as usize + address as usize) }
71 }
72
73 pub fn find_pattern(&self, pattern: &str) -> Option<usize> {
76 let base = self.module_base_address;
77 let end = self.module_base_address + self.module_size as usize;
78 unsafe { boyer_moore_horspool(pattern, base, end).map(|e| e as usize) }
79 }
80
81 pub fn pattern_scan(&self, pattern: &str, offset: isize, extra: usize) -> Option<usize> {
86 unsafe {
87 let address = self.find_pattern(pattern)?;
88 let address = (address as *mut u8).offset(offset) as *mut usize;
89 Some(*address - self.module_base_address + extra)
91 }
92 }
93}
94
95pub fn pattern_scan_all_modules(pattern: &str) -> Option<(usize, String)> {
100 unsafe {
101 let all_handles = get_all_module_handles().ok()?;
102 let process_handle = GetCurrentProcess();
103 for handle in all_handles {
104 let mut module_info: MODULEINFO = std::mem::zeroed::<MODULEINFO>();
105 GetModuleInformation(
106 process_handle,
107 handle,
108 &mut module_info,
109 size_of::<MODULEINFO>() as u32,
110 );
111 let base = module_info.lpBaseOfDll as usize;
112 let end = module_info.lpBaseOfDll as usize + module_info.SizeOfImage as usize;
113 match boyer_moore_horspool(pattern, base, end) {
114 Some(e) => {
115 let mut module_name: [CHAR; MAX_PATH] = [0; MAX_PATH];
116 GetModuleBaseNameA(
117 GetCurrentProcess(),
118 handle,
119 &mut module_name as LPSTR,
120 std::mem::size_of_val(&module_name) as u32,
121 );
122 let module_name =
123 read_null_terminated_string(&mut module_name as *mut i8 as usize).unwrap();
124 return Some((e as usize, module_name));
125 }
126 None => continue,
127 }
128 }
129 None
130 }
131}
132
133pub fn pattern_scan_specific_range(pattern: &str, start: usize, end: usize) -> Option<*mut u8> {
134 unsafe { boyer_moore_horspool(pattern, start, end) }
135}
136
137pub unsafe fn get_module_function_address(
140 module_name: &str,
141 function_name: &str,
142) -> Option<FARPROC> {
143 let module_handle = match get_module_handle(module_name) {
144 Some(e) => e,
145 None => return None,
146 };
147 Some(GetProcAddress(
148 module_handle,
149 crate::internal::utils::make_lpcstr(function_name),
150 ))
151}
152
153fn get_all_module_handles() -> Result<Vec<HMODULE>, TAInternalError> {
154 unsafe {
155 for size_indice in 3..=10 {
156 let mut module_handles = vec![0 as HMODULE; size_indice * 100];
158 let mut required_size = std::mem::zeroed::<DWORD>();
160 return if EnumProcessModules(
162 GetCurrentProcess(),
163 module_handles.as_mut_ptr(),
164 (module_handles.len() * size_of::<HMODULE>()) as u32,
165 &mut required_size,
166 ) != 0
167 {
168 let number_of_handles = required_size as usize / std::mem::size_of::<HMODULE>();
169 if size_indice * 100 < number_of_handles {
171 continue;
172 }
173 Ok(module_handles
174 .iter()
175 .filter(|e| **e != 0 as HMODULE)
176 .map(|e| e.clone())
177 .collect::<Vec<HMODULE>>())
178 } else {
179 Err(TAInternalError::GetAllModuleHandlesFailed)
180 };
181 }
182 Err(TAInternalError::GetAllModuleHandlesFailed)
183 }
184}