mem_rs/process/refresh.rs
1// This file is part of the mem-rs distribution (https://github.com/FrankvdStam/mem-rs).
2// Copyright (c) 2022 Frank van der Stam.
3// https://github.com/FrankvdStam/mem-rs/blob/main/LICENSE
4//
5// This program is free software: you can redistribute it and/or modify
6// it under the terms of the GNU General Public License as published by
7// the Free Software Foundation, version 3.
8//
9// This program is distributed in the hope that it will be useful, but
10// WITHOUT ANY WARRANTY without even the implied warranty of
11// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12// General Public License for more details.
13//
14// You should have received a copy of the GNU General Public License
15// along with this program. If not, see <http://www.gnu.org/licenses/>.
16
17use std::mem::size_of;
18use windows::Win32::Foundation::{CloseHandle, FALSE, HANDLE};
19use windows::Win32::System::ProcessStatus::{K32EnumProcesses, K32GetModuleFileNameExW};
20use windows::Win32::System::Threading::{GetExitCodeProcess, IsWow64Process, OpenProcess, PROCESS_QUERY_INFORMATION, PROCESS_VM_OPERATION, PROCESS_VM_READ, PROCESS_VM_WRITE};
21use crate::helpers::{get_file_name_from_string, w32str_to_string};
22use crate::prelude::Process;
23use crate::process::STILL_ACTIVE;
24
25impl Process
26{
27 /// Attempts to "attach" to a running process by name.
28 /// Returns an error when the process is not running or when it has exited.
29 /// Caches the main module so that pattern scans can be done against it.
30 ///
31 /// # Examples
32 ///
33 /// ```
34 /// use mem_rs::prelude::*;
35 ///
36 /// let mut process = Process::new("name_of_process.exe");
37 /// process.refresh().expect("Failed to attach/refresh!");
38 /// ```
39 pub fn refresh(&mut self) -> Result<(), String>
40 {
41 unsafe
42 {
43 //Check if a previously attached process has exited
44 let mut lp_exit_code: u32 = 0;
45 if self.process_data.borrow().attached && (!GetExitCodeProcess(self.process_data.borrow().handle, &mut lp_exit_code).is_ok() || lp_exit_code != STILL_ACTIVE)
46 {
47 let mut process_data = self.process_data.borrow_mut();
48
49 process_data.attached = false;
50 process_data.id = 0;
51 process_data.handle = HANDLE::default();
52 process_data.filename = String::new();
53 process_data.path = String::new();
54
55 return Err(String::from("Process exited"));
56 }
57
58 if self.process_data.borrow().attached
59 {
60 return Ok(());
61 }
62
63 //Look for a running process with the correct name and attach to it
64 let mut process_ids = [0u32; 2048];
65 let mut out_size = 0;
66
67 if !K32EnumProcesses(process_ids.as_mut_ptr(), (process_ids.len() * size_of::<u32>()) as u32, &mut out_size).as_bool()
68 {
69 return Err(String::from("Failed to get running processes"));
70 }
71
72 let count = out_size as usize / std::mem::size_of::<u32>();
73 for i in 0..count
74 {
75 let pid = process_ids[i];
76
77 match OpenProcess(
78 PROCESS_QUERY_INFORMATION
79 | PROCESS_VM_READ
80 | PROCESS_VM_WRITE
81 | PROCESS_VM_OPERATION,
82 false,
83 pid,
84 )
85 {
86 Ok(handle) =>
87 {
88 let mut mod_name = [0; windows::Win32::Foundation::MAX_PATH as usize];
89
90 if K32GetModuleFileNameExW(Some(handle), None, &mut mod_name) != 0
91 {
92 let file_path = w32str_to_string(&mod_name.to_vec());
93 let file_name = get_file_name_from_string(&file_path);
94
95 //println!("{}", filename);
96
97 if self.process_data.borrow().name.to_lowercase() == file_name.to_lowercase()
98 {
99 let mut wow64 = FALSE;
100 if IsWow64Process(handle, &mut wow64).is_ok()
101 {
102 let mut process_data = self.process_data.borrow_mut();
103 process_data.id = pid;
104 process_data.handle = handle;
105 process_data.is_64_bit = !wow64.as_bool();
106 process_data.filename = file_name;
107 process_data.path = file_path;
108 process_data.attached = true;
109 drop(process_data);
110
111 let mut main_module = Process::get_process_modules(handle, &self.process_data).remove(0);
112 main_module.dump_memory();
113 self.main_module = Some(main_module);
114
115 return Ok(());
116 }
117 }
118 }
119
120 let _ = CloseHandle(handle);
121 }
122 _ => {},
123 }
124 }
125 return Err(String::from("Process not running"));
126 }
127 }
128}