1use crate::error::{Result, WraithError};
4
5pub unsafe fn read_memory<T: Copy>(address: usize) -> Result<T> {
10 if address == 0 {
11 return Err(WraithError::NullPointer {
12 context: "read_memory",
13 });
14 }
15
16 Ok(unsafe { (address as *const T).read_unaligned() })
18}
19
20pub unsafe fn write_memory<T: Copy>(address: usize, value: &T) -> Result<()> {
25 if address == 0 {
26 return Err(WraithError::NullPointer {
27 context: "write_memory",
28 });
29 }
30
31 unsafe {
33 (address as *mut T).write_unaligned(*value);
34 }
35 Ok(())
36}
37
38pub fn protect_memory(address: usize, size: usize, protection: u32) -> Result<u32> {
40 let mut old_protect: u32 = 0;
41
42 let result = unsafe {
43 VirtualProtect(
44 address as *mut _,
45 size,
46 protection,
47 &mut old_protect,
48 )
49 };
50
51 if result == 0 {
52 Err(WraithError::ProtectionChangeFailed {
53 address: u64::try_from(address).unwrap_or(u64::MAX),
54 size,
55 })
56 } else {
57 Ok(old_protect)
58 }
59}
60
61pub struct ProtectionGuard {
63 address: usize,
64 size: usize,
65 old_protection: u32,
66}
67
68impl ProtectionGuard {
69 pub fn new(address: usize, size: usize, new_protection: u32) -> Result<Self> {
71 let old_protection = protect_memory(address, size, new_protection)?;
72 Ok(Self {
73 address,
74 size,
75 old_protection,
76 })
77 }
78}
79
80impl Drop for ProtectionGuard {
81 fn drop(&mut self) {
82 let _ = protect_memory(self.address, self.size, self.old_protection);
83 }
84}
85
86#[link(name = "kernel32")]
87extern "system" {
88 fn VirtualProtect(
89 lpAddress: *mut core::ffi::c_void,
90 dwSize: usize,
91 flNewProtect: u32,
92 lpflOldProtect: *mut u32,
93 ) -> i32;
94}