1#![allow(non_camel_case_types)]
2#![allow(non_snake_case)]
3#![allow(overflowing_literals)]
4#![allow(non_upper_case_globals)]
5
6pub mod error;
7pub mod peloader;
8pub mod peparser;
9
10use error::Result;
11use peloader::{DllLoader, ExeLoader};
12use peparser::PE;
13use std::os::raw::c_void;
14
15#[cfg(feature = "hook")]
16pub use peloader::hook;
17#[cfg(feature = "hook")]
18use peloader::hook::ProcDesc;
19#[cfg(feature = "hook")]
20use std::collections::HashMap;
21
22pub unsafe fn memexec_exe(bs: &[u8]) -> Result<()> {
23 let pe = PE::new(bs)?;
24 #[cfg(feature = "hook")]
25 let loader = ExeLoader::new(&pe, None)?;
26 #[cfg(not(feature = "hook"))]
27 let loader = ExeLoader::new(&pe)?;
28 Ok(loader.invoke_entry_point())
29}
30
31#[cfg(feature = "hook")]
32pub unsafe fn memexec_exe_with_hooks(
33 bs: &[u8],
34 hooks: &HashMap<ProcDesc, *const c_void>,
35) -> Result<()> {
36 let pe = PE::new(bs)?;
37 let loader = ExeLoader::new(&pe, Some(hooks))?;
38 Ok(loader.invoke_entry_point())
39}
40
41pub unsafe fn memexec_dll(
42 bs: &[u8],
43 hmod: *const c_void,
44 reason_for_call: u32,
45 lp_reserved: *const c_void,
46) -> Result<bool> {
47 let pe = PE::new(bs)?;
48 #[cfg(feature = "hook")]
49 let loader = DllLoader::new(&pe, None)?;
50 #[cfg(not(feature = "hook"))]
51 let loader = DllLoader::new(&pe)?;
52 Ok(loader.invoke_entry_point(hmod, reason_for_call, lp_reserved))
53}
54
55#[cfg(feature = "hook")]
56pub unsafe fn memexec_dll_with_hooks(
57 bs: &[u8],
58 hmod: *const c_void,
59 reason_for_call: u32,
60 lp_reserved: *const c_void,
61 hooks: &HashMap<ProcDesc, *const c_void>,
62) -> Result<bool> {
63 let pe = PE::new(bs)?;
64 let loader = DllLoader::new(&pe, Some(hooks))?;
65 Ok(loader.invoke_entry_point(hmod, reason_for_call, lp_reserved))
66}
67
68#[cfg(test)]
69mod tests {
70 use super::*;
71 use std::fs::File;
72 use std::io::Read;
73
74 #[test]
75 #[cfg(not(feature = "hook"))]
76 fn test_dll() {
77 let mut buf = Vec::new();
78 #[cfg(all(target_arch = "x86_64", target_os = "windows"))]
79 File::open("./test.x64.dll")
80 .unwrap()
81 .read_to_end(&mut buf)
82 .unwrap();
83 #[cfg(all(target_arch = "x86", target_os = "windows"))]
84 File::open("./test.x86.dll")
85 .unwrap()
86 .read_to_end(&mut buf)
87 .unwrap();
88
89 unsafe {
90 memexec_dll(&buf, 0 as _, peloader::def::DLL_PROCESS_ATTACH, 0 as _).unwrap();
91 }
92 }
93
94 #[test]
95 #[cfg(not(feature = "hook"))]
96 fn test_exe() {
97 let mut buf = Vec::new();
98 #[cfg(all(target_arch = "x86_64", target_os = "windows"))]
99 File::open("./test.x64.exe")
100 .unwrap()
101 .read_to_end(&mut buf)
102 .unwrap();
103 #[cfg(all(target_arch = "x86", target_os = "windows"))]
104 File::open("./test.x86.exe")
105 .unwrap()
106 .read_to_end(&mut buf)
107 .unwrap();
108
109 unsafe {
110 memexec_exe(&buf).unwrap();
111 }
112 }
113
114 #[cfg(feature = "hook")]
115 use std::mem;
116
117 #[cfg(feature = "hook")]
118 #[cfg(all(target_arch = "x86", target_os = "windows"))]
119 extern "cdecl" fn __wgetmainargs(
120 _Argc: *mut i32,
121 _Argv: *mut *const *const u16,
122 _Env: *const c_void,
123 _DoWildCard: i32,
124 _StartInfo: *const c_void,
125 ) -> i32 {
126 unsafe {
127 *_Argc = 2;
128 let a0: Vec<_> = "program_name\0"
129 .chars()
130 .map(|c| (c as u16).to_le())
131 .collect();
132 let a1: Vec<_> = "token::whoami\0"
133 .chars()
134 .map(|c| (c as u16).to_le())
135 .collect();
136 *_Argv = [a0.as_ptr(), a1.as_ptr()].as_ptr();
137
138 mem::forget(a0);
139 mem::forget(a1);
140 }
141
142 0
143 }
144
145 #[test]
146 #[cfg(feature = "hook")]
147 #[cfg(all(target_arch = "x86", target_os = "windows"))]
148 fn hook_x86() {
149 let mut buf = Vec::new();
150 File::open("./test.x86.exe")
151 .unwrap()
152 .read_to_end(&mut buf)
153 .unwrap();
154
155 let mut hooks = HashMap::new();
156
157 unsafe {
158 hooks.insert(
159 "msvcrt.dll!__wgetmainargs".into(),
160 mem::transmute::<
161 extern "cdecl" fn(
162 *mut i32,
163 *mut *const *const u16,
164 *const c_void,
165 i32,
166 *const c_void,
167 ) -> i32,
168 *const c_void,
169 >(__wgetmainargs),
170 );
171 memexec_exe_with_hooks(&buf, &hooks).unwrap();
172 }
173 }
174
175 #[cfg(feature = "hook")]
176 #[cfg(all(target_arch = "x86_64", target_os = "windows"))]
177 extern "win64" fn __wgetmainargs(
178 _Argc: *mut i32,
179 _Argv: *mut *const *const u16,
180 _Env: *const c_void,
181 _DoWildCard: i32,
182 _StartInfo: *const c_void,
183 ) -> i32 {
184 unsafe {
185 *_Argc = 2;
186
187 let a0: Vec<_> = "program_name\0"
188 .chars()
189 .map(|c| (c as u16).to_le())
190 .collect();
191 let a1: Vec<_> = "token::whoami\0"
192 .chars()
193 .map(|c| (c as u16).to_le())
194 .collect();
195 *_Argv = [a0.as_ptr(), a1.as_ptr()].as_ptr();
196
197 mem::forget(a0);
198 mem::forget(a1);
199 }
200
201 0
202 }
203
204 #[test]
205 #[cfg(feature = "hook")]
206 #[cfg(all(target_arch = "x86_64", target_os = "windows"))]
207 fn hook_x64() {
208 let mut buf = Vec::new();
209 File::open("./test.x64.exe")
210 .unwrap()
211 .read_to_end(&mut buf)
212 .unwrap();
213
214 let mut hooks = HashMap::new();
215
216 unsafe {
217 hooks.insert(
218 "msvcrt.dll!__wgetmainargs".into(),
219 mem::transmute::<
220 extern "win64" fn(
221 *mut i32,
222 *mut *const *const u16,
223 *const c_void,
224 i32,
225 *const c_void,
226 ) -> i32,
227 *const c_void,
228 >(__wgetmainargs),
229 );
230 memexec_exe_with_hooks(&buf, &hooks).unwrap();
231 }
232 }
233}