4 个版本
0.2.0 | 2020年11月25日 |
---|---|
0.1.2 | 2020年11月12日 |
0.1.1 | 2020年11月10日 |
0.1.0 | 2020年11月10日 |
#591 in 文件系统
24 每月下载次数
62KB
1.5K SLoC
memexec
一个用于从内存中加载和执行 PE(可移植可执行文件)而不接触磁盘的库
特性
- 适用于 EXE 和 DLL(除 .NET 集合外)
- 跨架构,适用于 x86 和 x86-64
- 零依赖
- 包含一个简单、零拷贝的 PE 解析子模块
- 提供 IAT 钩子接口
安装
# Cargo.toml
[dependencies]
memexec = "0.2"
用法
从内存中执行
⚠目标程序的架构必须与当前进程相同,否则将发生错误
use memexec;
use std::fs::File;
use std::io::Read;
/***********************************************************/
/* EXE */
/***********************************************************/
let mut buf = Vec::new();
File::open("./test.exe")
.unwrap()
.read_to_end(&mut buf)
.unwrap();
unsafe {
// If you need to pass command line parameters,
// try to modify PEB's command line buffer
// Or use `memexec_exe_with_hooks` to hook related functions (see below)
memexec::memexec_exe(&buf).unwrap();
}
/***********************************************************/
/* DLL */
/***********************************************************/
let mut buf = Vec::new();
File::open("./test.dll")
.unwrap()
.read_to_end(&mut buf)
.unwrap();
use memexec::peloader::def::DLL_PROCESS_ATTACH;
unsafe {
// DLL's entry point is DllMain
memexec_dll(&buf, 0 as _, DLL_PROCESS_ATTACH, 0 as _).unwrap();
}
IAT 钩子
在 Cargo.toml
中添加 hook
功能
[dependencies]
memexec = { version="0.2", features=[ "hook" ] }
钩子 __wgetmainargs
函数(参见 example/hook.rs
)
let mut buf = Vec::new();
File::open("./test.x64.exe")
.unwrap()
.read_to_end(&mut buf)
.unwrap();
let mut hooks = HashMap::new();
unsafe {
hooks.insert(
"msvcrt.dll!__wgetmainargs".into(),
mem::transmute::<
extern "win64" fn(
*mut i32,
*mut *const *const u16,
*const c_void,
i32,
*const c_void,
) -> i32,
*const c_void,
>(__wgetmainargs),
);
memexec::memexec_exe_with_hooks(&buf, &hooks).unwrap();
}
__wgetmainargs
的定义(注意不同架构上的调用约定)
// https://docs.microsoft.com/en-us/cpp/c-runtime-library/getmainargs-wgetmainargs?view=msvc-160
/*
int __wgetmainargs (
int *_Argc,
wchar_t ***_Argv,
wchar_t ***_Env,
int _DoWildCard,
_startupinfo * _StartInfo)
*/
#[cfg(all(target_arch = "x86_64", target_os = "windows"))]
extern "win64" fn __wgetmainargs(
_Argc: *mut i32,
_Argv: *mut *const *const u16,
_Env: *const c_void,
_DoWildCard: i32,
_StartInfo: *const c_void,
) -> i32 {
unsafe {
*_Argc = 2;
let a0: Vec<_> = "program_name\0"
.chars()
.map(|c| (c as u16).to_le())
.collect();
let a1: Vec<_> = "token::whoami\0"
.chars()
.map(|c| (c as u16).to_le())
.collect();
*_Argv = [a0.as_ptr(), a1.as_ptr()].as_ptr();
// Avoid calling destructor
mem::forget(a0);
mem::forget(a1);
}
0
}
解析 PE
PE 解析器可以解析与当前进程具有不同架构的程序
use memexec::peparser::PE;
// Zero copy
// Make sure that the lifetime of `buf` is longer than `pe`
let pe = PE::new(&buf);
println!("{:?}", pe);
待办事项
-
将
LoadLibrary
替换为递归调用load_pe_into_mem
-
将
GetProcAddress
替换为自行实现的LdrpSnapThunk
,以便支持通过IMAGE_IMPORT_BY_NAME.Hint
解析进程地址
许可证
GPLv3 许可证