memexec/
lib.rs

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}