A library for loading and executing PE (Portable Executable) from memory without ever touching the disk

Related tags

Command-line memexec
Overview

memexec

A library for loading and executing PE (Portable Executable) from memory without ever touching the disk

This is my own version for specific projects.
Original crate: https://crates.io/crates/memexec

Features

  • Applicable to EXE and DLL (except .NET assembly)
  • Cross-architecture, applicable to x86 and x86-64
  • Zero-dependency
  • Contains a simple, zero-copy PE parser submodule
  • Provides an IAT hooking interface

Install

# Cargo.toml

[dependencies]
git = "https://github.com/DmitrijVC/memexec"
memexec = "0.3"

Usage

Execute from memory

The architecture of target program must be same as current process, otherwise an error will occur

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 hooking

Add the hook feature in Cargo.toml

[dependencies]
memexec = { git = "https://github.com/DmitrijVC/memexec", version="0.3", features=[ "hook" ] }

Hook the __wgetmainargs function (see example/__wgetmainargs_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(_, _, _, _, _) -> _, _>(__wgetmainargs),
    );
    memexec::memexec_exe_with_hooks(&buf, &hooks).unwrap();
}

The definition of __wgetmainargs (notice the calling convention on different archtectures):

// 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 parser

PE parser could parse programs which have different architectures from current process

use memexec::peparser::PE;

// Zero copy
// Make sure that the lifetime of `buf` is longer than `pe`
let pe = PE::new(&buf);
println!("{:?}", pe);

TODO

  • Replace LoadLibrary with calling load_pe_into_mem recursively

  • Replace GetProcAddress with self-implemented LdrpSnapThunk, so as to support resolving proc address by IMAGE_IMPORT_BY_NAME.Hint

License

The GPLv3 license

You might also like...
Zenith - sort of like top or htop but with zoom-able charts, CPU, GPU, network, and disk usage
Zenith - sort of like top or htop but with zoom-able charts, CPU, GPU, network, and disk usage

Zenith - sort of like top or htop but with zoom-able charts, CPU, GPU, network, and disk usage

garbage-collecting on-disk object store, supporting higher level KV stores and databases.

marble Garbage-collecting disk-based object-store. See examples/kv.rs for a minimal key-value store built on top of this. Supports 4 methods: read: de

Shared memory - A Rust wrapper around native shared memory for Linux and Windows

shared_memory A crate that allows you to share memory between processes. This crate provides lightweight wrappers around shared memory APIs in an OS a

A new, portable, regular expression language

rulex A new, portable, regular expression language Read the book to get started! Examples On the left are rulex expressions (rulexes for short), on th

A new, portable, regular expression language

rulex A new, portable, regular expression language Read the book to get started! Examples On the left are rulex expressions (rulexes for short), on th

🐚+🦞 Ultra-portable Rust game engine suited for offline 2D games powered by WebAssembly

pagurus 🐚 + 🦞 Ultra-portable Rust game engine suited for offline 2D games powered by WebAssembly. Examples Snake Traditional snake game: examples/sn

Terminal disk space navigator 🔭
Terminal disk space navigator 🔭

Given a path on your hard-drive (which could also be the root path, eg. /). diskonaut scans it and indexes its metadata to memory so that you could explore its contents (even while still scanning!).

Executables on Disk? Bleh 🤮
Executables on Disk? Bleh 🤮

Executables on Disk? Preposterous! Saving executables to disk is like telling EDRs that "Hey! Take a look at this thing I just fetched from the Intern

A user-friendly, lightweight TUI for disk imaging
A user-friendly, lightweight TUI for disk imaging

Caligula Burning Tool Caligula is a user-friendly, lightweight TUI for imaging disks. $ caligula burn -h Burn an image to a disk Usage: caligula burn

Owner
FssAy
I hate frontend.
FssAy
High-performance and normalised trading interface capable of executing across many financial venues

High-performance and normalised trading interface capable of executing across many financial venues. Also provides a feature rich simulated exchange to assist with backtesting and dry-trading.

Barter 7 Dec 28, 2022
Peakrs Dataframe is a library and framework facilitates the extraction, transformation, and loading (ETL) of data.

Peakrs Dataframe Peakrs Dataframe is a library and framework facilitates the extraction, transformation, and loading (ETL) of data. Its first applicat

Max Yu 5 Sep 6, 2023
This is the weirdest thing I've ever seen

strange-config-format I got nerdsniped on Twitter. Here's the fastest way to get a solution I could manage. It took about 90 minutes. Usage $ cargo ru

Charlotte Som 2 Jul 25, 2022
Dura - You shouldn't ever lose your work if you're using Git

Dura Dura is a background process that watches your Git repositories and commits your uncommitted changes without impacting HEAD, the current branch,

Tim Kellogg 4.1k Jan 8, 2023
A Rust 🦀️ font loading, positioning and rendering toolkit

Toolkit used to load, match, measure and render texts. NOTE: This project is a work in progress. Text measuring and positioning is a complex topic. A

Alibaba 63 Dec 27, 2022
Safer Nostr is a service that helps protect users by loading sensitive information (IP leak) and using AI to prevent inappropriate images from being uploaded.

Safer Nostr is a service that helps protect users by loading sensitive information (IP leak) and using AI to prevent inappropriate images from being uploaded. It also offers image optimization and storage options. It has configurable privacy and storage settings, as well as custom cache expiration.

Thomas 4 Dec 29, 2022
Coffee is a loader for ELF (Executable and Linkable Format) object files written in Rust

Coffee is a loader for ELF (Executable and Linkable Format) object files written in Rust. It provides a mechanism to load and parse ELF files similar to COFFLoader, but specifically designed for ELF files used in Unix-like systems.

Sndav Bai 13 Jun 22, 2023
A self-contained, unopinionated, fast and lightweight executable launcher.

Kickoff ?? A self-contained, unopinionated, fast and lightweight executable launcher. Supported Platforms Platform Host Target aarch64-apple-macos-non

Nimbus 18 Oct 27, 2023
Revolutionize handheld gaming with adaptive game settings. Optimize graphics and gameplay experience based on real-time system metrics. Open-source project empowering developers to enhance games on portable devices

Welcome to the server-side application for the HarmonyLink project. This innovative software is developed with the Rust programming language and is ai

Jordon Brooks 5 Jun 28, 2023
Tool to allow parsing large JSON files without laoding into memory

Tool to allow parsing large JSON files without laoding into memory. Developed in Rust with adapters in other programming langauges for easy adoption

Salaah Amin 7 Jul 11, 2023