From 7e4d99503a46c92ee9528a6197ce0e50d61ba4cb Mon Sep 17 00:00:00 2001 From: safedv Date: Sat, 8 Mar 2025 11:50:06 +0100 Subject: [PATCH] feat: add MSVC PIC support, update to Rust 2024 --- CHANGELOG.md | 37 +++++++++++++++++++++++ Cargo.lock | 4 +-- Cargo.toml | 4 +-- Makefile.toml | 70 ++++++++++++++++++++++++++++++-------------- readme.md | 58 +++++++++++++++++++++++------------- src/common/crtapi.rs | 13 ++++---- src/main.rs | 1 + src/native/gate.rs | 2 +- src/premain.rs | 4 +-- 9 files changed, 138 insertions(+), 55 deletions(-) create mode 100644 CHANGELOG.md diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..63eae8c --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,37 @@ +# CHANGELOG + +## **[0.1.2]** - 2025-08-03 + +### Features: + +- **MSVC Support (PIC)**: RustiveDump can now be compiled using the MSVC toolchain as **Position Independent Code (PIC)**, allowing for more flexibility in cross-compilation scenarios. +- **Smaller Shellcode Size**: With the optimizations for MSVC, the shellcode size has been reduced to **14KB** when enabling features like **xor** and **remote**. +- **Updated to Rust 2024 Edition**: RustiveDump now supports the **Rust 2024 edition**. + +--- + +## **[0.1.1]** - 2024-10-14 + +### Features: + +- **Position Independent Code (PIC)**: RustiveDump can now be compiled as **Position Independent Code (PIC)**, making it possible to use the tool as **shellcode**. This flexibility allows RustiveDump to be embedded in other projects or used in memory-only payloads. +- **Refactored Code**: Significant code refactoring to improve the structure and efficiency of the tool. +- **Shellcode Size**: The shellcode, with the `xor` and `remote` features enabled, is **15KB** in size. + +--- + +## **[0.1.0]** - 2024-10-06 + +### Initial Release: + +- **Memory Dumping via NT System Calls**: RustiveDump uses only **NT system calls** to access the memory of **lsass.exe**. +- **Minimal Minidump Creation**: The tool creates a minimalistic minidump file containing only essential information, such as: + - **SystemInfo Stream**: Provides OS version and architecture details. + - **ModuleList Stream**: Lists the modules loaded in **lsass.exe**. + - **Memory64List Stream**: Contains the memory regions from **lsass.exe**. +- **XOR Encryption**: Option to encrypt the minidump file using XOR before saving or transmitting it. +- **Remote File Transmission**: The tool can send the dump file directly to a remote server using **Winsock** API calls, allowing remote exfiltration. +- **Debug Logging**: Optional debug mode to provide detailed logs of each step taken during the memory dump creation. +- **No-Std and CRT-Independent**: RustiveDump is built with the `no_std` feature in Rust, removing the dependency on the standard library. It is also independent of the **C Runtime (CRT)**. + +--- diff --git a/Cargo.lock b/Cargo.lock index 3051ab3..636207b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -11,6 +11,6 @@ dependencies = [ [[package]] name = "panic-halt" -version = "0.2.0" +version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "de96540e0ebde571dc55c73d60ef407c653844e6f9a1e2fdbd40c07b9252d812" +checksum = "a513e167849a384b7f9b746e517604398518590a9142f4846a32e3c2a4de7b11" diff --git a/Cargo.toml b/Cargo.toml index e642d7c..9c70402 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,11 +1,11 @@ [package] name = "RustiveDump" version = "0.1.1" -edition = "2021" +edition = "2024" authors = ["safedv"] [dependencies] -panic-halt = "0.2.0" +panic-halt = "1.0.0" [profile.dev] panic = "abort" diff --git a/Makefile.toml b/Makefile.toml index 674980f..881fae0 100644 --- a/Makefile.toml +++ b/Makefile.toml @@ -2,54 +2,80 @@ skip_core_tasks = true [env] -TARGET = "x86_64-pc-windows-gnu" -PIC_RUSTFLAGS = "-C link-arg=-nostdlib -C codegen-units=1 -C link-arg=-fno-ident -C link-arg=-fpack-struct=8 -C link-arg=-Wl,--gc-sections -C link-arg=-falign-jumps=1 -C link-arg=-w -C link-arg=-falign-labels=1 -C relocation-model=pic -C link-arg=-Wl,-T./Linker.ld,--build-id=none -C link-arg=-Wl,-s,--no-seh,--enable-stdcall-fixup -C link-arg=-Wl,--subsystem,console -C link-arg=-nostartfiles -C link-arg=-Wl,-e_start" -EXE_RUSTFLAGS = "-C link-arg=-nostdlib -C link-arg=-Wl,--gc-sections -C link-arg=-Wl,--subsystem,console -C link-arg=-nostartfiles -C link-arg=-Wl,-e_start" -FEATURES = "" +# Target platforms +TARGET_GNU = "x86_64-pc-windows-gnu" +TARGET_MSVC = "x86_64-pc-windows-msvc" + +# Flags for GNU PIC and EXE builds +RUSTFLAGS_GNU_PIC = "-C link-arg=-nostdlib -C codegen-units=1 -C link-arg=-fno-ident -C link-arg=-fpack-struct=8 -C link-arg=-Wl,--gc-sections -C link-arg=-falign-jumps=1 -C link-arg=-w -C link-arg=-falign-labels=1 -C relocation-model=pic -C link-arg=-Wl,-T./Linker.ld,--build-id=none -C link-arg=-Wl,-s,--no-seh,--enable-stdcall-fixup -C link-arg=-Wl,--subsystem,console -C link-arg=-nostartfiles -C link-arg=-Wl,-e_start" +RUSTFLAGS_GNU_EXE = "-C link-arg=-nostdlib -C link-arg=-Wl,--gc-sections -C link-arg=-Wl,--subsystem,console -C link-arg=-nostartfiles -C link-arg=-Wl,-e_start" + +# Flags for MSVC builds +RUSTFLAGS_MSVC_PIC = "-C codegen-units=1 -C strip=symbols -C opt-level=z -C link-arg=/NODEFAULTLIB -C link-arg=/ENTRY:_start -C link-arg=/SUBSYSTEM:CONSOLE -C link-arg=/OPT:REF,ICF -C link-arg=/SAFESEH:NO -C link-arg=/DEBUG:NONE -C link-arg=/FILEALIGN:512 -C link-arg=/ALIGN:16 -C link-arg=/SECTION:.bss,D -C link-arg=/SECTION:.edata,D -C link-arg=/SECTION:.idata,D -C link-arg=/SECTION:.pdata,D -C link-arg=/SECTION:.xdata,D" [tasks.default] -description = "Default task that builds the project." +description = "Default build task: builds the project as a GNU executable." dependencies = ["build"] [tasks.build] -description = "Clean, Builds, strips, and objcopy." +description = "Builds the project as a GNU executable, strips unnecessary sections." dependencies = ["clean", "cargo-build", "strip"] [tasks.clean] -description = "Cleans the project and removes the binary file." +description = "Cleans the project directory, removing old binaries." script = [ "cargo clean" ] [tasks.cargo-build] -description = "Build the project using cargo with custom rustflags." +description = "Compiles the project for the GNU target (exe)." command = "cargo" -args = ["build", "--release", "--target", "${TARGET}", "--features", "${FEATURES}"] -env = { "RUSTFLAGS" = "${EXE_RUSTFLAGS}" } +args = ["build", "--release", "--target", "${TARGET_GNU}", "--features", "${FEATURES}"] +env = { "RUSTFLAGS" = "${RUSTFLAGS_GNU_EXE}" } [tasks.strip] -description = "Strips unnecessary sections from the binary." +description = "Strips unneeded sections from the GNU binary." command = "strip" -args = ["-s", "--strip-unneeded", "-x", "-X", "target/x86_64-pc-windows-gnu/release/RustiveDump.exe"] +args = ["-s", "--strip-unneeded", "-x", "-X", "target/${TARGET_GNU}/release/RustiveDump.exe"] -[tasks.pic] -description = "Builds with PIC enabled." -dependencies = ["cleanpic", "cargo-build-pic", "strip", "objcopy"] +[tasks.pic-gnu] +description = "Builds the project as Shellcode (PIC) for the GNU target." +dependencies = ["cleanpic", "cargo-build-pic-gnu", "strip", "objcopy"] [tasks.cleanpic] -description = "Cleans the project and removes the binary file." +description = "Cleans the project and removes the old PIC binary." script = [ "cargo clean", "rm -f RustiveDump.bin" ] -[tasks.cargo-build-pic] -description = "Build the project using cargo with PIC enabled." +[tasks.cargo-build-pic-gnu] +description = "Compiles the project as PIC for the GNU target." command = "cargo" -args = ["build", "--release", "--target", "${TARGET}", "--features", "${FEATURES}"] -env = { "RUSTFLAGS" = "${PIC_RUSTFLAGS}" } +args = ["build", "--release", "--target", "${TARGET_GNU}", "--features", "${FEATURES}"] +env = { "RUSTFLAGS" = "${RUSTFLAGS_GNU_PIC}" } [tasks.objcopy] -description = "Converts the binary to a .bin file using objcopy." +description = "Converts the GNU binary to a .bin file using objcopy." command = "objcopy" -args = ["-O", "binary", "target/x86_64-pc-windows-gnu/release/RustiveDump.exe", "RustiveDump.bin"] \ No newline at end of file +args = ["-O", "binary", "target/${TARGET_GNU}/release/RustiveDump.exe", "RustiveDump.bin"] + +[tasks.pic-msvc] +description = "Builds the project as Shellcode (PIC) for the MSVC target." +dependencies = ["clean", "cargo-build-pic-msvc", "strip-msvc", "objcopy-msvc"] + +[tasks.cargo-build-pic-msvc] +description = "Compiles the project as PIC for the MSVC target." +command = "cargo" +args = ["build", "--release", "--target", "${TARGET_MSVC}", "--features", "${FEATURES}"] +env = { "RUSTFLAGS" = "${RUSTFLAGS_MSVC_PIC}" } + +[tasks.strip-msvc] +description = "Strips unneeded sections from the MSVC binary." +command = "strip" +args = ["-s", "--strip-unneeded", "-x", "-X", "target/${TARGET_MSVC}/release/RustiveDump.exe"] + +[tasks.objcopy-msvc] +description = "Converts the MSVC binary to a .bin file using objcopy." +command = "objcopy" +args = ["-O", "binary", "target/${TARGET_MSVC}/release/RustiveDump.exe", "RustiveDump.bin"] diff --git a/readme.md b/readme.md index cc64305..a3d6456 100644 --- a/readme.md +++ b/readme.md @@ -1,37 +1,44 @@ ## **RustiveDump** -**RustiveDump** is a Rust-based tool designed to dump the memory of the **lsass.exe** process using **only NT system calls**. - -It creates a minimal minidump file from scratch, containing essential components like **SystemInfo**, **ModuleList**, and **Memory64List**, with support for **XOR encryption** and **remote transmission**. - -Additionally, RustiveDump now implements the design of [Rustic64](https://github.com/safedv/Rustic64), allowing it to be compiled as **Position Independent Code (PIC)**, making it more versatile. +**RustiveDump** is a Rust-based tool designed to dump the memory of the **lsass.exe** process using **only NT system calls**. It creates a minimal minidump file from scratch, containing essential components like **SystemInfo**, **ModuleList**, and **Memory64List**, with support for **XOR encryption** and **remote transmission**. This project is a personal learning experience, focusing on leveraging native Windows APIs for memory dumping and building a minimalistic minidump file entirely from the ground up. +###### Shellcode (PIC) - v.0.1.1 + +RustiveDump now implements the design of [Rustic64](https://github.com/safedv/Rustic64), allowing it to be compiled as **Position Independent Code (PIC)**, making it more versatile. + +###### MSVC & Rust 2024 - v.0.1.2 + +The latest release of **RustiveDump** introduces support for **Position Independent Code (PIC)** compilation using the **MSVC toolchain**, along with updates to the **Rust 2024 edition**. + ## **Key Features** -1. **NT System Calls for Everything**: - RustiveDump bypasses standard APIs and leverages NT system calls for all its operations. - -2. **No-Std and CRT-Independent**: - RustiveDump is built using Rust's `no_std` feature, which removes reliance on Rust's standard library, and it's also **CRT library independent**. This resulting in a lean release build of only **18KB**. - -3. **Position Independent Code (PIC)**: +1. **Position Independent Code (PIC)**: RustiveDump now implements the design of Rustic64, allowing it to be compiled as `shellcode (PIC)`, making it more versatile. -4. **Indirect NT Syscalls**: +2. **Cross-Compilation Support**: + RustiveDump now supports both **GNU** and **MSVC** targets, enabling cross-compilation and compatibility across different environments. + +3. **NT System Calls for Everything**: + RustiveDump bypasses standard APIs and leverages NT system calls for all its operations. + +4. **No-Std and CRT-Independent**: + RustiveDump is built using Rust's `no_std` feature, which removes reliance on Rust's standard library, and it's also **CRT library independent**. This resulting in a lean release build of only **18KB**. + +5. **Indirect NT Syscalls**: The tool uses indirect syscalls, retrieving system service numbers (SSN) with techniques like **Hell’s Gate**, **Halo's Gate**, and **Tartarus' Gate**. -5. **Lean Memory Dump**: +6. **Lean Memory Dump**: RustiveDump generates a focused memory dump, containing only essential data (i.e., **SystemInfo**, **ModuleList**, and **Memory64List**), ensuring no bloated files—just enough to feed your memory analysis tools like **Mimikatz** or **Pypykatz**. -6. **XOR Encryption**: +7. **XOR Encryption**: RustiveDump can encrypt the dump file using XOR before saving or transmitting it, adding an extra layer of security to the dumped memory. -7. **Remote File Transmission**: +8. **Remote File Transmission**: The dump file can be sent directly to a remote server using **winsock** APIs calls -8. **Debug Mode**: +9. **Debug Mode**: The debug mode provides detailed logs of each step, which can be enabled during the build process. ## **How it works** @@ -72,15 +79,22 @@ To build RustiveDump with different combinations of features, use the following cargo make ``` -- **Build with specific features** +- **Build as Portable Executable (PE) with specific features** ```bash cargo make --env FEATURES=xor,remote,lsasrv,debug ``` -- **Build as Shellcode (PIC)** +- **Build as Shellcode (PIC) for GNU target** + ```bash - cargo make --env FEATURES=xor,remote pic + cargo make --env FEATURES=xor,remote pic-gnu + ``` + +- **Build as Shellcode (PIC) for MSVC target** + + ```bash + cargo make --env FEATURES=xor,remote pic-msvc ``` ## **Memory Dump File Structure** @@ -107,4 +121,6 @@ Always follow ethical guidelines and legal frameworks when doing security resear Contributions are welcome! If you want to help improve RustiveDump or report bugs, feel free to open an issue or a pull request in the repository. ---- +## Changelog + +See the full list of changes in the [Changelog](./CHANGELOG.md). diff --git a/src/common/crtapi.rs b/src/common/crtapi.rs index 84f0d50..363a42e 100644 --- a/src/common/crtapi.rs +++ b/src/common/crtapi.rs @@ -8,7 +8,7 @@ /// /// # Returns /// A pointer to the memory area `s`. -#[no_mangle] +#[unsafe(no_mangle)] pub extern "C" fn memset(s: *mut u8, c: i32, n: usize) -> *mut u8 { for i in 0..n { unsafe { *s.add(i) = c as u8 }; @@ -26,7 +26,7 @@ pub extern "C" fn memset(s: *mut u8, c: i32, n: usize) -> *mut u8 { /// /// # Returns /// A pointer to the destination `dest`. -#[no_mangle] +#[unsafe(no_mangle)] pub extern "C" fn memcpy(dest: *mut u8, src: *const u8, n: usize) -> *mut u8 { for i in 0..n { unsafe { @@ -46,7 +46,7 @@ pub extern "C" fn memcpy(dest: *mut u8, src: *const u8, n: usize) -> *mut u8 { /// /// # Returns /// A pointer to the destination `dest`. -#[no_mangle] +#[unsafe(no_mangle)] pub extern "C" fn memmove(dest: *mut u8, src: *const u8, n: usize) -> *mut u8 { if src < dest as *const u8 { for i in (0..n).rev() { @@ -74,7 +74,7 @@ pub extern "C" fn memmove(dest: *mut u8, src: *const u8, n: usize) -> *mut u8 { /// # Returns /// An integer less than, equal to, or greater than zero if the first `n` bytes of `s1` /// is found, respectively, to be less than, to match, or be greater than the first `n` bytes of `s2`. -#[no_mangle] +#[unsafe(no_mangle)] pub extern "C" fn memcmp(s1: *const u8, s2: *const u8, n: usize) -> i32 { for i in 0..n { let a = unsafe { *s1.add(i) }; @@ -93,7 +93,7 @@ pub extern "C" fn memcmp(s1: *const u8, s2: *const u8, n: usize) -> i32 { /// /// # Returns /// The number of bytes in the string pointed to by `s`, excluding the terminating null byte. -#[no_mangle] +#[unsafe(no_mangle)] pub extern "C" fn strlen(s: *const u8) -> usize { let mut count = 0; unsafe { @@ -103,3 +103,6 @@ pub extern "C" fn strlen(s: *const u8) -> usize { } count } + +#[unsafe(no_mangle)] +pub extern "C" fn __chkstk() {} diff --git a/src/main.rs b/src/main.rs index 9700618..dcd8c5d 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,5 +1,6 @@ #![no_std] #![no_main] +#![allow(unsafe_op_in_unsafe_fn)] extern crate alloc; extern crate panic_halt; diff --git a/src/native/gate.rs b/src/native/gate.rs index a569090..b8a17dc 100644 --- a/src/native/gate.rs +++ b/src/native/gate.rs @@ -1,4 +1,4 @@ -extern "C" { +unsafe extern "C" { // Declaration of an external syscall function with a variadic argument list pub fn isyscall(ssn: u16, addr: usize, n_args: u32, ...) -> i32; } diff --git a/src/premain.rs b/src/premain.rs index 5d42082..c995b4c 100644 --- a/src/premain.rs +++ b/src/premain.rs @@ -12,7 +12,7 @@ use crate::debug::k32::init_kernel32_funcs; #[cfg(feature = "remote")] use crate::remote::winsock::init_winsock_funcs; -#[no_mangle] +#[unsafe(no_mangle)] pub extern "C" fn initialize() { unsafe { // Stack allocation of Instance @@ -103,7 +103,7 @@ skip: "# ); -extern "C" { +unsafe extern "C" { pub fn _start(); }