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#[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 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
165pub 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(¤t_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}