mod injector;
mod pe;
mod shellcode;
use windows_sys::Win32::Foundation::HANDLE;
#[derive(Debug)]
pub enum Error {
InvalidPe,
Win32(u32),
InvalidArgument,
ShellcodeFailed(usize),
SehRegistrationFailed,
ShellcodeCrashed(u32, usize),
}
impl Error {
fn last_win32() -> Self {
use windows_sys::Win32::Foundation::GetLastError;
Error::Win32(unsafe { GetLastError() })
}
}
impl std::fmt::Display for Error {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Error::InvalidPe => write!(f, "not a valid x64 PE/DLL"),
Error::Win32(code) => write!(f, "Win32 error 0x{code:08X}"),
Error::InvalidArgument => write!(f, "invalid argument"),
Error::ShellcodeFailed(code) => {
let name = crate::shellcode::step_name(*code);
write!(f, "shellcode failed: {name} (0x{code:08X})")
}
Error::SehRegistrationFailed => write!(f, "DLL injected but SEH registration failed"),
Error::ShellcodeCrashed(code, step) => {
let name = crate::shellcode::step_name(*step);
write!(f, "shellcode crashed at step '{name}' (exit 0x{code:08X})")
}
}
}
}
impl std::error::Error for Error {}
pub type Result<T> = std::result::Result<T, Error>;
pub unsafe fn inject_dll(process: HANDLE, dll_bytes: &[u8]) -> Result<()> {
unsafe { injector::inject(process, dll_bytes) }
}