memory_rs/external/
memory.rs1use std::ffi::c_void;
2
3use windows_sys::Win32::{
4 Foundation::HANDLE,
5 System::{
6 Diagnostics::Debug::{ReadProcessMemory, WriteProcessMemory},
7 Memory::{
8 VirtualAllocEx, VirtualProtectEx, MEM_COMMIT, MEM_RESERVE, PAGE_EXECUTE_READWRITE,
9 },
10 },
11};
12
13pub fn get_aob(h_process: HANDLE, ptr: *const c_void, n: usize) -> Vec<u8> {
16 let mut read = 0;
17 let mut buffer: Vec<u8> = vec![0; n];
18
19 unsafe {
20 ReadProcessMemory(
21 h_process,
22 ptr as *const c_void,
23 buffer.as_mut_ptr() as *mut c_void,
24 n,
25 &mut read,
26 );
27 }
28
29 assert_eq!(n, read, "get_aob isn't the requested size");
30
31 buffer
32}
33
34pub fn write_aob(h_process: HANDLE, ptr: usize, source: &[u8]) -> usize {
35 let mut protection_bytes: u32 = 0x0;
36 let c_addr = ptr;
37 let size = source.len();
38 let mut written = 0;
39
40 unsafe {
41 VirtualProtectEx(
42 h_process,
43 c_addr as *const c_void,
44 size,
45 PAGE_EXECUTE_READWRITE,
46 &mut protection_bytes as _,
47 );
48
49 WriteProcessMemory(
50 h_process,
51 c_addr as *const c_void,
52 source[..].as_ptr() as *const c_void,
53 size,
54 &mut written,
55 );
56
57 VirtualProtectEx(
58 h_process,
59 c_addr as *const c_void,
60 size,
61 protection_bytes,
62 &mut protection_bytes as _,
63 );
64 }
65
66 assert_eq!(
67 written,
68 source.len(),
69 "write_aob didn't write the correct number of bytes"
70 );
71
72 written
73}
74
75pub fn write_nops(h_process: HANDLE, ptr: usize, n: usize) {
76 let nops: Vec<u8> = vec![0x90; n];
77 write_aob(h_process, ptr, &nops);
78}
79
80pub fn hook_function(h_process: HANDLE, to_hook: usize, f: usize, len: usize) {
81 assert!(len >= 5, "Not enough space to inject the shellcode");
82
83 let mut current_protection: u32 = 0x0;
84
85 unsafe {
86 VirtualProtectEx(
87 h_process,
88 to_hook as *const c_void,
89 len,
90 PAGE_EXECUTE_READWRITE,
91 &mut current_protection as _,
92 );
93 }
94
95 let nops = vec![0x90; len];
97 write_aob(h_process, to_hook, &nops);
98
99 let _diff = f as i64 - to_hook as i64;
100 let relative_address: u32 = (_diff as u32 - 5) as u32;
101 let relative_aob: [u8; 4] = relative_address.to_le_bytes();
102
103 let mut instructions: Vec<u8> = vec![0xE8];
104 instructions.extend_from_slice(&relative_aob[..]);
105
106 let written = write_aob(h_process, to_hook, &instructions);
107 assert_eq!(written, 5);
108
109 unsafe {
110 VirtualProtectEx(
111 h_process,
112 to_hook as *const c_void,
113 len,
114 current_protection,
115 &mut current_protection as _,
116 );
117 }
118}
119
120pub unsafe fn inject_shellcode(
127 h_process: HANDLE,
128 module_base_address: usize,
129 entry_point: *const c_void,
130 instruction_size: usize,
131 f_start: *const u8,
132 f_end: *const u8,
133) -> *const c_void {
134 let f_size = f_end as usize - f_start as usize;
135 let shellcode_bytes: &'static [u8] = std::slice::from_raw_parts(f_start, f_size);
137
138 let mut shellcode_space: *const c_void = std::ptr::null();
139 for i in 1..1000 {
141 let current_address = module_base_address - (0x1000 * i);
142 shellcode_space = VirtualAllocEx(
143 h_process,
144 current_address as _,
145 0x1000_usize,
146 MEM_RESERVE | MEM_COMMIT,
147 PAGE_EXECUTE_READWRITE,
148 );
149
150 if !shellcode_space.is_null() {
151 break;
152 }
153 }
154
155 let written = write_aob(h_process, shellcode_space as _, &shellcode_bytes.to_vec());
156 assert_eq!(written, f_size, "The size of the injection doesnt match");
157
158 let module_injection_address = module_base_address + (entry_point as usize);
159 hook_function(
160 h_process,
161 module_injection_address,
162 shellcode_space as _,
163 instruction_size,
164 );
165
166 shellcode_space
167}