1use super::{Win32Kernel, Win32ProcessInfo, Win32VirtualTranslate};
31
32use memflow::cglue::*;
33use memflow::error::PartialResultExt;
34use memflow::error::{Error, ErrorKind, ErrorOrigin, Result};
35use memflow::mem::{MemoryView, PhysicalMemory, VirtualDma, VirtualTranslate2};
36use memflow::os::keyboard::*;
37use memflow::prelude::{ExportInfo, ModuleInfo, Os, Pid, Process};
38use memflow::types::{umem, Address};
39
40#[cfg(feature = "plugins")]
41use memflow::cglue;
42
43use log::debug;
44use std::convert::TryInto;
45
46#[cfg(feature = "plugins")]
47cglue_impl_group!(Win32Keyboard<T>, IntoKeyboard);
48
49#[derive(Clone, Debug)]
51pub struct Win32Keyboard<T> {
52 pub virt_mem: T,
53 key_state_addr: Address,
54}
55
56impl<T: 'static + PhysicalMemory + Clone, V: 'static + VirtualTranslate2 + Clone>
57 Win32Keyboard<VirtualDma<T, V, Win32VirtualTranslate>>
58{
59 pub fn with_kernel(mut kernel: Win32Kernel<T, V>) -> Result<Self> {
60 let (user_process_info, key_state_addr) = Self::find_keystate(&mut kernel)?;
61
62 let (phys_mem, vat) = kernel.virt_mem.into_inner();
63 let virt_mem = VirtualDma::with_vat(
64 phys_mem,
65 user_process_info.base_info.proc_arch,
66 user_process_info.translator(),
67 vat,
68 );
69
70 Ok(Self {
71 virt_mem,
72 key_state_addr,
73 })
74 }
75
76 pub fn into_inner(self) -> (T, V) {
78 self.virt_mem.into_inner()
79 }
80}
81
82impl<'a, T: 'static + PhysicalMemory + Clone, V: 'static + VirtualTranslate2 + Clone>
83 Win32Keyboard<VirtualDma<Fwd<&'a mut T>, Fwd<&'a mut V>, Win32VirtualTranslate>>
84{
85 pub fn with_kernel_ref(kernel: &'a mut Win32Kernel<T, V>) -> Result<Self> {
95 let (user_process_info, key_state_addr) = Self::find_keystate(kernel)?;
96
97 let (phys_mem, vat) = kernel.virt_mem.mem_vat_pair();
98 let virt_mem = VirtualDma::with_vat(
99 phys_mem.forward_mut(),
100 user_process_info.base_info.proc_arch,
101 user_process_info.translator(),
102 vat.forward_mut(),
103 );
104
105 Ok(Self {
106 virt_mem,
107 key_state_addr,
108 })
109 }
110}
111
112impl<T> Win32Keyboard<T> {
113 fn find_keystate<
114 P: 'static + PhysicalMemory + Clone,
115 V: 'static + VirtualTranslate2 + Clone,
116 >(
117 kernel: &mut Win32Kernel<P, V>,
118 ) -> Result<(Win32ProcessInfo, Address)> {
119 let win32kbase_module_info = kernel.module_by_name("win32kbase.sys")?;
120 debug!("found win32kbase.sys: {:?}", win32kbase_module_info);
121
122 let procs = kernel.process_info_list()?;
123
124 let gaf = procs
125 .iter()
126 .filter(|p| {
127 p.name.as_ref() == "winlogon.exe"
128 || p.name.as_ref() == "explorer.exe"
129 || p.name.as_ref() == "taskhostw.exe"
130 || p.name.as_ref() == "smartscreen.exe"
131 || p.name.as_ref() == "dwm.exe"
132 })
133 .find_map(|p| Self::find_in_user_process(kernel, &win32kbase_module_info, p.pid).ok())
134 .ok_or_else(|| {
135 Error(ErrorOrigin::OsLayer, ErrorKind::ExportNotFound)
136 .log_info("unable to find any proxy process that contains gafAsyncKeyState")
137 })?;
138
139 Ok((gaf.0, gaf.1))
140 }
141
142 fn find_in_user_process<
143 P: 'static + PhysicalMemory + Clone,
144 V: 'static + VirtualTranslate2 + Clone,
145 >(
146 kernel: &mut Win32Kernel<P, V>,
147 win32kbase_module_info: &ModuleInfo,
148 pid: Pid,
149 ) -> Result<(Win32ProcessInfo, Address)> {
150 let user_process_info = kernel.process_info_by_pid(pid)?;
151 let user_process_info_win32 =
152 kernel.process_info_from_base_info(user_process_info.clone())?;
153 let mut user_process = kernel.process_by_info(user_process_info)?;
154 debug!(
155 "trying to find gaf signature in user proxy process `{}`",
156 user_process.info().name.as_ref()
157 );
158
159 let export_addr = Self::find_gaf_pe(&mut user_process.virt_mem, win32kbase_module_info)
161 .or_else(|_| Self::find_gaf_sig(&mut user_process.virt_mem, win32kbase_module_info))?;
162 debug!(
163 "found gaf signature in user proxy process `{}` at {:x}",
164 user_process.info().name.as_ref(),
165 export_addr
166 );
167
168 Ok((
169 user_process_info_win32,
170 win32kbase_module_info.base + export_addr,
171 ))
172 }
173
174 fn find_gaf_pe(
175 virt_mem: &mut impl MemoryView,
176 win32kbase_module_info: &ModuleInfo,
177 ) -> Result<umem> {
178 let mut offset = None;
179 let callback = &mut |export: ExportInfo| {
180 if export.name.as_ref() == "gafAsyncKeyState" {
181 offset = Some(export.offset);
182 false
183 } else {
184 true
185 }
186 };
187 memflow::os::util::module_export_list_callback(
188 virt_mem,
189 win32kbase_module_info,
190 callback.into(),
191 )?;
192 offset.ok_or_else(|| {
193 Error(ErrorOrigin::OsLayer, ErrorKind::ExportNotFound)
194 .log_info("unable to find gafAsyncKeyState")
195 })
196 }
197
198 #[cfg(feature = "regex")]
200 fn find_gaf_sig(
201 virt_mem: &mut impl MemoryView,
202 win32kbase_module_info: &ModuleInfo,
203 ) -> Result<umem> {
204 use ::regex::bytes::*;
205
206 let module_buf = virt_mem
207 .read_raw(
208 win32kbase_module_info.base,
209 win32kbase_module_info.size.try_into().unwrap(),
210 )
211 .data_part()?;
212
213 let re = Regex::new("(?-u)\\x48\\x8B\\x05(?s:.)(?s:.)(?s:.)(?s:.)\\x48\\x89\\x81(?s:.)(?s:.)\\x00\\x00\\x48\\x8B\\x8F")
215 .map_err(|_| Error(ErrorOrigin::OsLayer, ErrorKind::Encoding).log_info("malformed gafAsyncKeyState signature"))?;
216 let buf_offs = re
217 .find(module_buf.as_slice())
218 .ok_or_else(|| {
219 Error(ErrorOrigin::OsLayer, ErrorKind::NotFound)
220 .log_info("unable to find gafAsyncKeyState signature")
221 })?
222 .start()
223 + 0x3;
224
225 let export_offs = buf_offs as u32
227 + u32::from_le_bytes(module_buf[buf_offs..buf_offs + 4].try_into().unwrap())
228 + 0x4;
229 debug!("gafAsyncKeyState export found at: {:x}", export_offs);
230 Ok(export_offs as umem)
231 }
232
233 #[cfg(not(feature = "regex"))]
234 fn find_gaf_sig(
235 virt_mem: &mut impl MemoryView,
236 win32kbase_module_info: &ModuleInfo,
237 ) -> Result<umem> {
238 Err(
239 Error(ErrorOrigin::OsLayer, ErrorKind::UnsupportedOptionalFeature)
240 .log_error("signature scanning requires std"),
241 )
242 }
243}
244
245macro_rules! get_ks_byte {
246 ($vk:expr) => {
247 $vk * 2 / 8
248 };
249}
250
251macro_rules! get_ks_down_bit {
252 ($vk:expr) => {
253 1 << (($vk % 4) * 2)
254 };
255}
256
257macro_rules! is_key_down {
258 ($ks:expr, $vk:expr) => {
259 ($ks[get_ks_byte!($vk) as usize] & get_ks_down_bit!($vk)) != 0
260 };
261}
262
263macro_rules! set_key_down {
264 ($ks:expr, $vk:expr, $down:expr) => {
265 if $down {
266 ($ks[get_ks_byte!($vk) as usize] |= get_ks_down_bit!($vk))
267 } else {
268 ($ks[get_ks_byte!($vk) as usize] &= !get_ks_down_bit!($vk))
269 }
270 };
271}
272
273impl<T: MemoryView> Keyboard for Win32Keyboard<T> {
274 type KeyboardStateType = Win32KeyboardState;
275
276 fn is_down(&mut self, vk: i32) -> bool {
283 if !(0..=256).contains(&vk) {
284 false
285 } else if let Ok(buffer) = self
286 .virt_mem
287 .read::<[u8; 256 * 2 / 8]>(self.key_state_addr)
288 .data_part()
289 {
290 is_key_down!(buffer, vk)
291 } else {
292 false
293 }
294 }
295
296 fn set_down(&mut self, vk: i32, down: bool) {
303 if (0..=256).contains(&vk) {
304 if let Ok(mut buffer) = self.virt_mem.read::<[u8; 256 * 2 / 8]>(self.key_state_addr) {
305 set_key_down!(buffer, vk, down);
306 self.virt_mem.write(self.key_state_addr, &buffer).ok();
307 }
308 }
309 }
310
311 fn state(&mut self) -> memflow::error::Result<Self::KeyboardStateType> {
313 let buffer: [u8; 256 * 2 / 8] = self.virt_mem.read(self.key_state_addr)?;
314 Ok(Win32KeyboardState { buffer })
315 }
316}
317
318#[derive(Clone)]
322pub struct Win32KeyboardState {
323 buffer: [u8; 256 * 2 / 8],
324}
325
326impl KeyboardState for Win32KeyboardState {
327 fn is_down(&self, vk: i32) -> bool {
333 if !(0..=256).contains(&vk) {
334 false
335 } else {
336 is_key_down!(self.buffer, vk)
337 }
338 }
339}