rsmemoryapi/
lib.rs

1#![allow(dead_code)]
2
3#[link(name="psapi")]
4extern "system"
5{
6    fn EnumProcesses(id_processes: *mut u32, cb: u32, cb_needed: *mut u32) -> i32;
7    fn GetProcessImageFileNameA(handle: usize, image_filename: *mut u8, size: u32) -> u32;
8}
9
10#[link(name="kernel32")]
11extern "system"
12{
13    fn IsWow64Process(handle: usize, bool_result: *mut i32) -> i32;
14    fn OpenProcess(desired_access: u32, inherit_handle: i32, process_id: u32) -> usize;
15    fn GetModuleBaseNameA(handle: usize, module_handle: usize, name: *mut u8, size: u32) -> u32;
16    fn GetModuleInformation(handle: usize, module_handle: usize, module_pointer: *mut Module, cb: u32) -> i32;
17    fn EnumProcessModulesEx(handle: usize, modules_array: *mut usize, cb: u32, cb_needed: *mut u32, filter_flag: u32) -> i32;
18    fn ReadProcessMemory(handle: usize, base_address: *const usize, buffer: *mut u8, size: usize, bytes_read: *mut usize) -> i32;
19    fn WriteProcessMemory(handle: usize, base_address: *const usize, buffer: *const u8, size: usize, bytes_written: *mut usize) -> i32;
20}
21
22const PATH_SIZE: usize = 260;
23const PROCESS_ALL_ACCESS: u32 = 0x001F0FFF;
24
25// Стркуктуры
26#[repr(C)]
27#[derive(Debug)]
28#[derive(Clone, Copy)]
29#[derive(PartialEq, PartialOrd)]
30pub struct Module
31{
32    pub base_address: usize,
33    pub size_of_image: usize,
34    pub entry_point: usize
35}
36
37#[repr(C)]
38#[derive(Debug)]
39pub struct Process
40{
41    pub process_name: String,
42    pub process_handle: usize,
43    pub process_id: u32,
44}
45
46impl Process
47{
48    pub fn new_from_id(process_id: u32) -> Option<Process>
49    {
50        let active_process_ids: Vec<u32> = list_processes().unwrap().into_iter().map(|(x, _)| x).collect();
51
52        match active_process_ids.iter().position(|&x| x == process_id)
53        {
54            None => panic!("Process with \"{}\" id not found", process_id),
55            Some(_) => 
56            {
57                let handle: usize = unsafe {OpenProcess(PROCESS_ALL_ACCESS, 0, process_id)};
58                let mut image_file_name: [u8; PATH_SIZE] = [0; PATH_SIZE];
59
60                
61                unsafe {GetProcessImageFileNameA(handle, &mut image_file_name as *mut u8, 260)};
62                let file_name_decoded: String = String::from_utf8(image_file_name.to_vec()).unwrap().trim_end_matches("\0").to_string();
63
64                match file_name_decoded.split("\\").last()
65                {
66                    Some(name) => {Some(Process{process_name: name.to_string(), process_handle: handle, process_id: process_id})}
67                    None => {Some(Process{process_name: "".to_string(), process_handle: handle, process_id: process_id})}
68                }
69            }    
70        }
71    }
72
73    pub fn new_from_name(process_name: String) -> Option<Process>
74    {
75        let active_process_ids: Vec<u32> = list_processes().unwrap().into_iter().map(|(x, _)| x).collect();
76        let active_process_names: Vec<String> = list_processes().unwrap().into_iter().map(|(_, x)| x).collect();
77
78        match active_process_names.into_iter().position(|x| x.to_lowercase() == process_name.to_lowercase())
79        {
80            None => panic!("Process with \"{}\" name not found", process_name),
81            Some(index) =>
82            {
83                let handle: usize = unsafe {OpenProcess(PROCESS_ALL_ACCESS, 0, active_process_ids[index])};
84                let mut image_file_name: [u8; PATH_SIZE] = [0; PATH_SIZE];
85
86                
87                unsafe {GetProcessImageFileNameA(handle, &mut image_file_name as *mut u8, 260)};
88                let file_name_decoded: String = String::from_utf8(image_file_name.to_vec()).unwrap().trim_end_matches("\0").to_string();
89
90                match file_name_decoded.split("\\").last()
91                {
92                    Some(name) => {Some(Process{process_name: name.to_string(), process_handle: handle, process_id: active_process_ids[index]})}
93                    None => {Some(Process{process_name: "".to_string(), process_handle: handle, process_id: active_process_ids[index]})}
94                }
95            }
96        }
97    }
98
99    pub fn is_64x(&self) -> bool
100    {
101        let mut is_64: i32 = 0;
102        if unsafe {IsWow64Process(self.process_handle, &mut is_64 as *mut i32)} != 0 {true} else {false}
103    }
104
105    pub fn read_memory<T>(&self, address: usize) -> Option<T>
106    {
107        let mut buffer: T = unsafe {std::mem::zeroed::<T>()};
108        let mut bytes_read: usize = 0;
109
110        let success: i32 = unsafe {ReadProcessMemory(self.process_handle, address as *const usize, &mut buffer as *mut T as *mut u8, std::mem::size_of::<T>(), &mut bytes_read)};
111        if success != 0 {Some(buffer)} else {None}
112    }
113
114    pub fn write_memory<T>(&self, address: usize, value: T) -> bool
115    {
116        let mut bytes_written: usize = 0;
117
118        let success: i32 = unsafe {WriteProcessMemory(self.process_handle, address as *const usize, &value as *const T as *const u8, std::mem::size_of::<T>(), &mut bytes_written)};
119        if success != 0 {true} else {false}
120    }
121
122    // TODO
123    pub fn get_module_info(&self, module_name: String) -> Option<Module>
124    {
125        let modules = self.list_modules().unwrap();
126
127        for (name, module_object) in modules
128        {
129            if module_name.to_lowercase() == name.to_lowercase()
130            {
131                return Some(module_object);
132            }
133        }
134        None
135    }
136
137    pub fn list_modules(&self) -> Option<Vec<(String, Module)>>
138    {
139        let mut current_module_objects: Vec<(String, Module)> = Vec::new();
140        let mut module_handles: [usize; 2048] = [0; 2048];
141        let mut cb_needed: u32 = 0;
142
143        match unsafe {EnumProcessModulesEx(self.process_handle, &mut module_handles as *mut usize, std::mem::size_of_val(&module_handles) as u32, &mut cb_needed as *mut u32, 0x003)}
144        {
145            0 => {}
146            _ =>
147            {
148                let active_modules_count: usize = (cb_needed / std::mem::size_of::<u32>() as u32) as usize;
149                for module_handle in 0..active_modules_count
150                {
151                    let mut module_info: Module = unsafe{std::mem::zeroed::<Module>()};
152                    unsafe {GetModuleInformation(self.process_handle, module_handles[module_handle], &mut module_info as *mut Module, std::mem::size_of_val(&mut module_handles) as u32)};
153                    
154                    if !current_module_objects.contains(&(get_module_name(self.process_handle, module_handles[module_handle]), module_info))
155                    {
156                        current_module_objects.push((get_module_name(self.process_handle, module_handles[module_handle]), module_info));
157                    }
158                }
159            }
160        }
161        if !current_module_objects.is_empty() {Some(current_module_objects)} else {None}
162    }
163}
164
165// Функции
166pub fn get_module_name(process_handle: usize, module_hande: usize) -> String
167{
168    let mut buffer: [u8; PATH_SIZE] = [0; PATH_SIZE];
169    unsafe {GetModuleBaseNameA(process_handle, module_hande, &mut buffer as *mut u8, std::mem::size_of_val(&mut buffer) as u32)};
170
171    let decoded_buffer: String = String::from_utf8(buffer.to_vec()).unwrap().trim_end_matches("\0").to_string();
172    decoded_buffer
173    
174}
175
176pub fn list_processes() -> Option<Vec<(u32, String)>>
177{
178    let mut current_process_names: Vec<(u32, String)> = Vec::new();
179    let mut current_process_ids: [u32; 2048] = [0; 2048];
180    let mut cb_needed: u32 = 0;
181
182    match unsafe {EnumProcesses(current_process_ids.as_mut_ptr(), std::mem::size_of_val(&current_process_ids) as u32, &mut cb_needed)}
183    {
184        0 => {},
185        _ => 
186        {
187            let active_processes_count: usize = (cb_needed / std::mem::size_of::<u32>() as u32) as usize;
188            for process_id in 0..active_processes_count
189            {
190                let handle: usize = unsafe {OpenProcess(PROCESS_ALL_ACCESS, 0, current_process_ids[process_id] as u32)};
191
192                match handle
193                {
194                    0 => {}
195                    _ =>
196                    {
197                        let mut image_file_name: [u8; PATH_SIZE] = [0; PATH_SIZE];
198                        unsafe {GetProcessImageFileNameA(handle, &mut image_file_name as *mut u8, 260)};
199                        
200                        let file_name_decoded: String = String::from_utf8(image_file_name.to_vec()).unwrap().trim_end_matches("\0").to_string();
201                        
202                        match file_name_decoded.split("\\").last()
203                        {
204                            None => {}
205                            Some(name) => {current_process_names.push((current_process_ids[process_id], name.to_string()))}
206                        }
207                    }
208                }
209            }
210        }
211    }
212    if !current_process_names.is_empty() {Some(current_process_names)} else {None}
213}