mirror of
https://github.com/0xTriboulet/rdll-rs
synced 2026-06-06 15:14:27 +00:00
Add Reflective DLL support and xtask utility
Introduced a new `xtask` for building Reflective DLLs and integrated [pe_to_shellcode] for enhanced compatibility. Updated `dll/src/lib.rs` with ReflectiveLoader logic, added necessary FFI bindings, and extended documentation to include the build process and usage.
This commit is contained in:
+1
-1
@@ -1,5 +1,5 @@
|
||||
[workspace]
|
||||
members = ["dll", "exe"]
|
||||
members = ["dll", "exe", "xtask"]
|
||||
resolver = "3"
|
||||
|
||||
[profile.release]
|
||||
|
||||
+108
-2
@@ -24,12 +24,118 @@ unsafe extern "system" {
|
||||
fn GetProcAddress(hmodule: HANDLE, lpProcName: LPVOID) -> LPVOID;
|
||||
}
|
||||
|
||||
#[allow(non_snake_case)]
|
||||
#[link(name = "user32")]
|
||||
unsafe extern "system" {
|
||||
fn MessageBoxA(
|
||||
hWnd: HANDLE,
|
||||
lpText: LPVOID,
|
||||
lpCaption: LPVOID,
|
||||
uType: DWORD
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
#[repr(C)]
|
||||
struct ImageDosHeader {
|
||||
e_magic: u16,
|
||||
e_cblp: u16,
|
||||
e_cp: u16,
|
||||
e_crlc: u16,
|
||||
e_cparhdr: u16,
|
||||
e_minalloc: u16,
|
||||
e_maxalloc: u16,
|
||||
e_ss: u16,
|
||||
e_sp: u16,
|
||||
e_csum: u16,
|
||||
e_ip: u16,
|
||||
e_cs: u16,
|
||||
e_lfarlc: u16,
|
||||
e_ovno: u16,
|
||||
e_res: [u16; 4],
|
||||
e_oemid: u16,
|
||||
e_oeminfo: u16,
|
||||
e_res2: [u16; 10],
|
||||
e_lfanew: i32,
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
struct ImageNtHeaders {
|
||||
signature: u32,
|
||||
}
|
||||
|
||||
const IMAGE_DOS_SIGNATURE: u16 = 0x5A4D; // 'MZ'
|
||||
const IMAGE_NT_SIGNATURE: u32 = 0x00004550; // 'PE\0\0'
|
||||
|
||||
#[cfg(target_arch = "x86_64")]
|
||||
unsafe fn get_ip() -> usize {
|
||||
let rip: usize;
|
||||
unsafe { std::arch::asm!("lea {}, [rip]", out(reg) rip) };
|
||||
rip
|
||||
}
|
||||
|
||||
#[cfg(target_arch = "x86")]
|
||||
unsafe fn get_ip() -> usize {
|
||||
let eip: usize;
|
||||
unsafe{
|
||||
std::arch::asm!(
|
||||
"call 1f",
|
||||
"1: pop {}",
|
||||
out(reg) eip,
|
||||
);
|
||||
}
|
||||
|
||||
eip
|
||||
}
|
||||
|
||||
pub fn find_mz_pe_signature() -> Option<*const u8> {
|
||||
unsafe {
|
||||
let rip = get_ip();
|
||||
let mut ptr = rip as *const u8;
|
||||
|
||||
loop {
|
||||
if ptr < 2 as *const u8 {
|
||||
break;
|
||||
}
|
||||
|
||||
let dos_header = ptr.offset(-2) as *const ImageDosHeader;
|
||||
|
||||
if std::ptr::read_unaligned(&(*dos_header).e_magic) == IMAGE_DOS_SIGNATURE {
|
||||
let e_lfanew = std::ptr::read_unaligned(&(*dos_header).e_lfanew) as isize;
|
||||
|
||||
if e_lfanew >= std::mem::size_of::<ImageDosHeader>() as isize && e_lfanew < 1024 {
|
||||
let nt_header_ptr = (dos_header as *const u8).offset(e_lfanew) as *const ImageNtHeaders;
|
||||
|
||||
if std::ptr::read_unaligned(&(*nt_header_ptr).signature) == IMAGE_NT_SIGNATURE {
|
||||
return Some(dos_header as *const u8);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ptr = ptr.offset(-1);
|
||||
}
|
||||
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
/// ReflectiveLoader for compatability with legacy Reflective DLL loaders
|
||||
#[unsafe(no_mangle)]
|
||||
pub unsafe extern "system" fn ReflectiveLoader(){
|
||||
let module_base = find_mz_pe_signature();
|
||||
if module_base.is_some() {
|
||||
let module_base = module_base.unwrap();
|
||||
unsafe { std::arch::asm!("call {0}", in(reg) module_base) };
|
||||
}
|
||||
}
|
||||
|
||||
/// For maximum compatability with this template, all functionality should be called from `dll_main`
|
||||
#[unsafe(no_mangle)]
|
||||
#[allow(named_asm_labels)]
|
||||
#[allow(non_snake_case, unused_variables)]
|
||||
pub fn dll_main() {
|
||||
let cmd = b"calc.exe\0";
|
||||
unsafe { WinExec(cmd.as_ptr() as LPVOID, 0); }
|
||||
let msg = b"Hello from Rust Reflective DLL!\0";
|
||||
unsafe { MessageBoxA(std::ptr::null_mut(), msg.as_ptr() as LPVOID, msg.as_ptr() as LPVOID, 0 ); }
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
# dll-rs
|
||||
# rdll-rs
|
||||
|
||||
A Rust project that demonstrates Windows DLL functionality and WinAPI interaction.
|
||||
A Rust DLL template project that integrates [pe2shc](https://github.com/hasherezade/pe_to_shellcode) to facilitate the development of [Reflective DLLs](https://github.com/stephenfewer/ReflectiveDLLInjection). The template presently only supports 64-bit DLL development in most contexts, though with a few tweaks it should support 32-bit.
|
||||
|
||||
## Overview
|
||||
|
||||
dll-rs is a Rust template that can be compiled as both a dynamic-link library (DLL) and a regular executable. It provides an example of how to create Windows DLLs using Rust, including proper exports and Windows API integration.
|
||||
rdll-rs is a Rust template that can be compiled as both a dynamic-link library (DLL), a regular executable, or a Reflective DLL. It provides an example of how to create Windows DLLs using Rust, including proper exports and Windows API integration.
|
||||
|
||||
## Features
|
||||
|
||||
@@ -15,8 +15,9 @@ dll-rs is a Rust template that can be compiled as both a dynamic-link library (D
|
||||
|
||||
## Project Structure
|
||||
|
||||
- `src/main.rs` - Executable entry point
|
||||
- `src/lib.rs` - Library implementation with DLL exports
|
||||
- `dll/src/main.rs` - Executable entry point
|
||||
- `exe/src/lib.rs` - Library implementation with DLL exports
|
||||
- `build-deps/pe_to_shellcode` - Post-build stomp reflective loader
|
||||
- Supporting Rust source files
|
||||
|
||||
## Building
|
||||
@@ -29,10 +30,14 @@ Or to build in release:
|
||||
```bash
|
||||
cargo build --release
|
||||
```
|
||||
Or to build a Reflective DLL:
|
||||
```bash
|
||||
cargo run --bin xtask --release
|
||||
```
|
||||
|
||||
## Usage
|
||||
|
||||
The project can be used in two ways:
|
||||
The project can be used in thee ways:
|
||||
|
||||
1. As a DLL (**dll-rs.dll**):
|
||||
- Build in release mode to generate the DLL
|
||||
@@ -40,12 +45,16 @@ The project can be used in two ways:
|
||||
2. As an executable (**debug-executable.exe**):
|
||||
- Run in debug mode to test DLL functionality without DLL debugging gymnastics
|
||||
- Running in release mode will display a warning message
|
||||
3. As a Reflective DLL using [@hasherezade's](https://github.com/hasherezade) [pe_to_shellcode](https://github.com/hasherezade/pe_to_shellcode)
|
||||
- **NOTE: For maximum compatability with this template, all functionality should be called from `dll_main` in `dll/src/lib.rs`**
|
||||
3. As a Reflective DLL (**dll_rs.shc.dll**) using [@hasherezade's](https://github.com/hasherezade) [pe_to_shellcode](https://github.com/hasherezade/pe_to_shellcode)
|
||||
- Resolve submodules with `git submodule update --init --recursive`
|
||||
- `cd .\build-deps\pe_to_shellcode\`
|
||||
- `cmake .`
|
||||
- `cmake --build . --config Release`
|
||||
|
||||
- `cd ..\..`
|
||||
- `cargo run --bin xtask --release`
|
||||
- Use your Reflective DLL in `target/release/dll_rs.shc.dll`
|
||||
- **NOTE: If the build process above is too complicated/broken for your taste, simply placing the [`pe2shc.exe`](https://github.com/hasherezade/pe_to_shellcode/releases/download/v1.2/pe2shc.exe) executable in the proper folder structure (`build-deps/pe_to_shellcode/pe2shc/Release/pe2shc.exe`) will work**
|
||||
|
||||
## Technical Details
|
||||
|
||||
@@ -53,12 +62,16 @@ The project can be used in two ways:
|
||||
- Implements Windows API bindings
|
||||
- Provides internal FFI declarations for Windows types
|
||||
- Includes DLL entry point handling
|
||||
- Remember: maximum compatability with this template, all functionality should be called from `dll_main` in `dll/src/lib.rs`
|
||||
- Exports `ReflectiveLoader` and handles calling the real reflective loader to support legacy loader checks
|
||||
- Supports the command line ergonomics of both`shinject` and `dllinject` commands of your [favorite C2 Framework](https://www.cobaltstrike.com/).
|
||||
|
||||
## Requirements
|
||||
|
||||
- Rust 2024 edition
|
||||
- Windows operating system
|
||||
- Cargo build system
|
||||
- Cmake > 3.0
|
||||
|
||||
## Licensing
|
||||
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
[package]
|
||||
name = "xtask"
|
||||
version = "0.1.0"
|
||||
edition = "2024"
|
||||
|
||||
[dependencies]
|
||||
@@ -0,0 +1,26 @@
|
||||
use std::process::{Command, exit};
|
||||
|
||||
fn main() {
|
||||
let path = std::env::current_dir().unwrap();
|
||||
println!("The current directory is {}", path.display());
|
||||
|
||||
let status = Command::new("cargo")
|
||||
.args(&["build", "--release", "--manifest-path", "./Cargo.toml"])
|
||||
.current_dir("./dll")
|
||||
.status()
|
||||
.expect("Failed to build");
|
||||
if !status.success() {
|
||||
exit(1);
|
||||
}
|
||||
|
||||
let status = Command::new("build-deps/pe_to_shellcode/pe2shc/Release/pe2shc.exe")
|
||||
.args(&["dll_rs.dll"])
|
||||
.current_dir("./target/release")
|
||||
.status()
|
||||
.expect("Failed to run pe2shc.exe");
|
||||
if !status.success() {
|
||||
exit(1);
|
||||
}
|
||||
|
||||
println!("Done");
|
||||
}
|
||||
Reference in New Issue
Block a user