ddcore_rs/memory/
proc_mem_wrapper.rs1use anyhow::Result;
6
7#[cfg(target_os = "windows")]
8use std::os::windows::prelude::OwnedHandle;
9#[cfg(target_os = "windows")]
10use process_memory::Architecture;
11
12#[cfg(target_os = "linux")]
13use process_memory::{CopyAddress, ProcessHandle, ProcessHandleExt, TryIntoProcessHandle};
14
15#[cfg(target_os = "windows")]
16pub struct Handle {
17 pub win_handle: OwnedHandle,
18 pub pid: usize,
19}
20
21#[cfg(target_os = "linux")]
22pub struct Handle {
23 pub inner: ProcessHandle,
24 pub pid: usize,
25}
26
27impl Handle {
28 #[cfg(target_os = "windows")]
29 pub fn new(pid: usize) -> Result<Self> {
30 use std::os::windows::prelude::FromRawHandle;
31
32 use winapi::shared::minwindef::DWORD;
33 let handle = unsafe {
34 winapi::um::processthreadsapi::OpenProcess(
35 winapi::um::winnt::PROCESS_ALL_ACCESS,
36 winapi::shared::minwindef::FALSE,
37 pid as DWORD,
38 )
39 };
40 if handle == (0 as winapi::um::winnt::HANDLE) {
41 Err(anyhow::anyhow!(std::io::Error::last_os_error()))
42 } else {
43 let handle = unsafe { OwnedHandle::from_raw_handle(handle) };
44 Ok(Handle { win_handle: handle, pid })
45 }
46 }
47
48 #[cfg(target_os = "windows")]
49 pub fn get_offset(&self, offsets: &[usize]) -> Result<usize> {
50 let mut offset: usize = 0;
51 let noffsets: usize = offsets.len();
52 let arch = Architecture::from_native();
53 let mut copy = vec![0_u8; arch as usize];
54 for next_offset in offsets.iter().take(noffsets - 1) {
55 offset += next_offset;
56 self.copy_address(offset, &mut copy)?;
57 offset = arch.pointer_from_ne_bytes(©);
58 }
59
60 offset += offsets[noffsets - 1];
61 Ok(offset)
62 }
63
64 #[cfg(target_os = "windows")]
65 pub fn check_handle(&self) -> bool {
66 use std::os::windows::prelude::AsRawHandle;
67 self.win_handle.as_raw_handle().is_null()
68 }
69
70 #[cfg(target_os = "windows")]
71 pub fn copy_address(&self, addr: usize, buf: &mut [u8]) -> Result<()> {
72 use std::os::windows::prelude::AsRawHandle;
73 use winapi::shared::minwindef;
74 if buf.is_empty() {
75 return Ok(());
76 }
77
78 if unsafe {
79 winapi::um::memoryapi::ReadProcessMemory(
80 self.win_handle.as_raw_handle(),
81 addr as minwindef::LPVOID,
82 buf.as_mut_ptr() as minwindef::LPVOID,
83 buf.len() as winapi::shared::basetsd::SIZE_T,
84 std::ptr::null_mut(),
85 )
86 } == winapi::shared::minwindef::FALSE
87 {
88 Err(anyhow::anyhow!(std::io::Error::last_os_error()))
89 } else {
90 Ok(())
91 }
92 }
93
94 #[cfg(target_os = "windows")]
95 pub fn put_address(&self, addr: usize, buf: &[u8]) -> Result<()> {
96 use std::os::windows::prelude::AsRawHandle;
97 use winapi::shared::minwindef;
98
99 if buf.is_empty() {
100 return Ok(());
101 }
102 if unsafe {
103 winapi::um::memoryapi::WriteProcessMemory(
104 self.win_handle.as_raw_handle(),
105 addr as minwindef::LPVOID,
106 buf.as_ptr() as minwindef::LPCVOID,
107 buf.len() as winapi::shared::basetsd::SIZE_T,
108 std::ptr::null_mut(),
109 )
110 } == winapi::shared::minwindef::FALSE
111 {
112 Err(anyhow::anyhow!(std::io::Error::last_os_error()))
113 } else {
114 Ok(())
115 }
116 }
117
118 #[cfg(target_os = "windows")]
119 pub fn null_type() -> Self {
120 use std::os::windows::prelude::FromRawHandle;
121 Self {
122 win_handle: unsafe { OwnedHandle::from_raw_handle(std::ptr::null_mut()) },
123 pid: 0,
124 }
125 }
126
127 #[cfg(target_os = "linux")]
128 pub fn new(pid: usize) -> Result<Self> {
129 Ok(Self {
130 inner: (pid as i32).try_into_process_handle()?,
131 pid
132 })
133 }
134
135 #[cfg(target_os = "linux")]
136 pub fn null_type() -> Self {
137 Self {
138 inner: ProcessHandle::null_type(),
139 pid: 0
140 }
141 }
142
143 #[cfg(target_os = "linux")]
144 pub fn copy_address(&self, addr: usize, buf: &mut [u8]) -> Result<()> {
145 Ok(self.inner.copy_address(addr, buf)?)
146 }
147
148 #[cfg(target_os = "linux")]
149 pub fn put_address(&self, addr: usize, buf: &[u8]) -> Result<()> {
150 use process_memory::PutAddress;
151 self.inner.put_address(addr, buf)?;
152 Ok(())
153 }
154
155 #[cfg(target_os = "linux")]
156 pub fn get_offset(&self, offsets: &[usize]) -> Result<usize> {
157 Ok(self.inner.get_offset(offsets)?)
158 }
159
160 #[cfg(target_os = "linux")]
161 pub fn check_handle(&self) -> bool {
162 self.inner.check_handle()
163 }
164}