-
Notifications
You must be signed in to change notification settings - Fork 42
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
15 changed files
with
359 additions
and
41 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,6 +1,7 @@ | ||
//! Wrappers around FFI functions | ||
|
||
pub mod errors; | ||
pub mod socket; | ||
|
||
#[cfg(target_os = "linux")] | ||
pub mod linux; | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
use std::{marker::PhantomData, ptr::NonNull}; | ||
|
||
use crate::internal::SealedTrait; | ||
|
||
pub trait SockAddrFamily: SealedTrait { | ||
type Inner; | ||
} | ||
|
||
pub struct AfInet; | ||
impl SealedTrait for AfInet {} | ||
|
||
pub struct AfInet6; | ||
impl SealedTrait for AfInet6 {} | ||
|
||
pub struct AfUnspec; | ||
impl SealedTrait for AfUnspec {} | ||
|
||
pub enum SockAddr<'a> { | ||
AfInet(SockAddrIn<'a, AfInet>), | ||
AfInet6(SockAddrIn<'a, AfInet6>), | ||
} | ||
|
||
#[repr(transparent)] | ||
pub struct SockAddrIn<'a, S: SockAddrFamily> { | ||
pub(crate) addr: NonNull<S::Inner>, | ||
_marker: PhantomData<&'a S::Inner>, | ||
} | ||
|
||
impl<'a, S: SockAddrFamily> SockAddrIn<'a, S> { | ||
pub(crate) unsafe fn from_raw(addr: NonNull<S::Inner>) -> SockAddrIn<'a, S> { | ||
SockAddrIn { | ||
addr, | ||
_marker: PhantomData, | ||
} | ||
} | ||
} |
173 changes: 173 additions & 0 deletions
173
Payload_Type/thanatos/agent/ffiwrappers/src/windows/interfaces/adapters.rs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,173 @@ | ||
use std::{cell::UnsafeCell, ffi::c_void, marker::PhantomData, ptr::NonNull}; | ||
|
||
use windows::Win32::{ | ||
Foundation::{ERROR_BUFFER_OVERFLOW, ERROR_SUCCESS}, | ||
NetworkManagement::IpHelper::{ | ||
GetAdaptersAddresses, GAA_FLAG_INCLUDE_ALL_INTERFACES, GAA_FLAG_INCLUDE_GATEWAYS, | ||
GAA_FLAG_INCLUDE_PREFIX, GAA_FLAG_INCLUDE_TUNNEL_BINDINGORDER, GAA_FLAG_SKIP_ANYCAST, | ||
GAA_FLAG_SKIP_MULTICAST, GAA_FLAG_SKIP_UNICAST, GET_ADAPTERS_ADDRESSES_FLAGS, | ||
IP_ADAPTER_ADDRESSES_LH, | ||
}, | ||
}; | ||
|
||
use crate::errors::FfiError; | ||
|
||
use super::{AdapterFamily, UnicastAddress}; | ||
|
||
bitflags::bitflags! { | ||
pub struct AdapterFlags: u32 { | ||
const SKIP_UNICAST = GAA_FLAG_SKIP_UNICAST.0; | ||
const SKIP_ANYCAST = GAA_FLAG_SKIP_ANYCAST.0; | ||
const SKIP_MULTICAST = GAA_FLAG_SKIP_MULTICAST.0; | ||
const INCLUDE_PREFIX = GAA_FLAG_INCLUDE_PREFIX.0; | ||
const INCLUDE_GATEWAYS = GAA_FLAG_INCLUDE_GATEWAYS.0; | ||
const INCLUDE_ALL_INTERFACES = GAA_FLAG_INCLUDE_ALL_INTERFACES.0; | ||
const INCLUDE_TUNNEL_BINDINGORDER = GAA_FLAG_INCLUDE_TUNNEL_BINDINGORDER.0; | ||
} | ||
} | ||
|
||
pub struct IpAdaptersList<IpvType: AdapterFamily> { | ||
backing: UnsafeCell<Vec<u8>>, | ||
_family: PhantomData<IpvType>, | ||
} | ||
|
||
impl<IpvType: AdapterFamily> IpAdaptersList<IpvType> { | ||
pub fn addresses() -> Result<IpAdaptersList<IpvType>, FfiError> { | ||
Self::with_flags(None) | ||
} | ||
pub fn with_flags(flags: Option<AdapterFlags>) -> Result<IpAdaptersList<IpvType>, FfiError> { | ||
let flags = GET_ADAPTERS_ADDRESSES_FLAGS(flags.map(|f| f.bits()).unwrap_or(0)); | ||
|
||
let mut size_required = 0; | ||
|
||
let ret = unsafe { | ||
GetAdaptersAddresses(IpvType::VALUE.into(), flags, None, None, &mut size_required) | ||
}; | ||
|
||
if ret != ERROR_BUFFER_OVERFLOW.0 { | ||
return Err(FfiError::OsError(ret as i32)); | ||
} | ||
|
||
let mut buffer: Vec<u8> = Vec::with_capacity(size_required as usize); | ||
|
||
let ret = unsafe { | ||
GetAdaptersAddresses( | ||
IpvType::VALUE.into(), | ||
flags, | ||
None, | ||
Some(buffer.as_mut_ptr().cast()), | ||
&mut size_required, | ||
) | ||
}; | ||
|
||
if ret != ERROR_SUCCESS.0 { | ||
return Err(FfiError::OsError(ret as i32)); | ||
} | ||
|
||
unsafe { buffer.set_len(size_required as usize) }; | ||
|
||
Ok(IpAdaptersList { | ||
backing: UnsafeCell::new(buffer), | ||
_family: PhantomData, | ||
}) | ||
} | ||
|
||
pub fn first(&self) -> IpAdapter<IpvType> { | ||
IpAdapter { | ||
adapter: unsafe { NonNull::new_unchecked((*self.backing.get()).as_mut_ptr().cast()) }, | ||
_marker: PhantomData, | ||
_family: PhantomData, | ||
} | ||
} | ||
|
||
pub fn iter(&self) -> IpAdaptersListIterator<IpvType> { | ||
IpAdaptersListIterator { | ||
adapter: unsafe { (*self.backing.get()).as_mut_ptr().cast() }, | ||
_marker: PhantomData, | ||
_family: PhantomData, | ||
} | ||
} | ||
} | ||
|
||
#[repr(transparent)] | ||
pub struct IpAdaptersListIterator<'a, IpvType: AdapterFamily> { | ||
adapter: *mut IP_ADAPTER_ADDRESSES_LH, | ||
_marker: PhantomData<&'a IP_ADAPTER_ADDRESSES_LH>, | ||
_family: PhantomData<IpvType>, | ||
} | ||
|
||
impl<'a, IpvType: AdapterFamily> Iterator for IpAdaptersListIterator<'a, IpvType> { | ||
type Item = IpAdapter<'a, IpvType>; | ||
|
||
fn next(&mut self) -> Option<Self::Item> { | ||
let adapter = NonNull::new(self.adapter)?; | ||
self.adapter = unsafe { adapter.as_ref() }.Next; | ||
|
||
Some(IpAdapter { | ||
adapter, | ||
_marker: PhantomData, | ||
_family: PhantomData, | ||
}) | ||
} | ||
} | ||
|
||
#[repr(transparent)] | ||
pub struct IpAdapter<'a, IpvType: AdapterFamily> { | ||
adapter: NonNull<IP_ADAPTER_ADDRESSES_LH>, | ||
_marker: PhantomData<&'a IP_ADAPTER_ADDRESSES_LH>, | ||
_family: PhantomData<IpvType>, | ||
} | ||
|
||
impl<'a, IpvType: AdapterFamily> IpAdapter<'_, IpvType> { | ||
pub const fn if_index(&self) -> u32 { | ||
unsafe { self.adapter.as_ref() }.IfType | ||
} | ||
|
||
pub fn adapter_name(&self) -> Result<String, FfiError> { | ||
unsafe { self.adapter.as_ref().AdapterName.to_string() } | ||
.map_err(|_| FfiError::StringParseError) | ||
} | ||
|
||
pub fn first_unicast_address(&self) -> Option<UnicastAddress<IpvType>> { | ||
let unicast_address = NonNull::new(unsafe { self.adapter.as_ref() }.FirstUnicastAddress)?; | ||
Some(unsafe { UnicastAddress::from_raw(unicast_address) }) | ||
} | ||
|
||
pub const fn first_anycast_address(&self) -> *const c_void { | ||
unsafe { self.adapter.as_ref() }.FirstAnycastAddress.cast() | ||
} | ||
|
||
pub const fn first_multicast_address(&self) -> *const c_void { | ||
unsafe { self.adapter.as_ref() } | ||
.FirstMulticastAddress | ||
.cast() | ||
} | ||
|
||
pub fn dns_suffix(&self) -> Result<String, FfiError> { | ||
unsafe { self.adapter.as_ref().DnsSuffix.to_string() } | ||
.map_err(|_| FfiError::StringParseError) | ||
} | ||
|
||
pub fn description(&self) -> Result<String, FfiError> { | ||
unsafe { self.adapter.as_ref().Description.to_string() } | ||
.map_err(|_| FfiError::StringParseError) | ||
} | ||
|
||
pub fn friendly_name(&self) -> Result<String, FfiError> { | ||
unsafe { self.adapter.as_ref().FriendlyName.to_string() } | ||
.map_err(|_| FfiError::StringParseError) | ||
} | ||
} | ||
|
||
#[cfg(test)] | ||
mod tests { | ||
use super::IpAdaptersList; | ||
use crate::socket::AfUnspec; | ||
|
||
#[test] | ||
fn adapters() { | ||
let interfaces: IpAdaptersList<AfUnspec> = IpAdaptersList::addresses().unwrap(); | ||
|
||
for interface in interfaces.iter() {} | ||
} | ||
} |
Empty file.
Empty file.
Empty file.
40 changes: 40 additions & 0 deletions
40
Payload_Type/thanatos/agent/ffiwrappers/src/windows/interfaces/mod.rs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,40 @@ | ||
use crate::internal::SealedTrait; | ||
|
||
mod socket; | ||
|
||
mod adapters; | ||
pub use adapters::*; | ||
|
||
mod unicast; | ||
pub use unicast::*; | ||
|
||
pub trait AdapterFamily: SealedTrait { | ||
const VALUE: u16; | ||
} | ||
|
||
pub mod adaptertypes { | ||
use super::AdapterFamily; | ||
use crate::socket::{AfInet, AfInet6, AfUnspec, SockAddrFamily}; | ||
use windows::Win32::Networking::WinSock::{ | ||
AF_INET, AF_INET6, AF_UNSPEC, SOCKADDR_IN, SOCKADDR_IN6, | ||
}; | ||
|
||
impl AdapterFamily for AfInet { | ||
const VALUE: u16 = AF_INET.0; | ||
} | ||
impl SockAddrFamily for AfInet { | ||
type Inner = SOCKADDR_IN; | ||
} | ||
|
||
impl AdapterFamily for AfInet6 { | ||
const VALUE: u16 = AF_INET6.0; | ||
} | ||
|
||
impl SockAddrFamily for AfInet6 { | ||
type Inner = SOCKADDR_IN6; | ||
} | ||
|
||
impl AdapterFamily for AfUnspec { | ||
const VALUE: u16 = AF_UNSPEC.0; | ||
} | ||
} |
Empty file.
42 changes: 42 additions & 0 deletions
42
Payload_Type/thanatos/agent/ffiwrappers/src/windows/interfaces/socket.rs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,42 @@ | ||
use std::ptr::NonNull; | ||
|
||
use windows::Win32::Networking::WinSock::{ | ||
ADDRESS_FAMILY, AF_INET, AF_INET6, IN_ADDR, SOCKADDR, SOCKADDR_IN, SOCKADDR_IN6, | ||
}; | ||
|
||
use crate::socket::{AfInet, AfInet6, SockAddr, SockAddrIn}; | ||
|
||
impl<'a> SockAddr<'a> { | ||
pub(crate) fn from_raw(addr: NonNull<SOCKADDR>) -> Option<SockAddr<'a>> { | ||
match unsafe { addr.as_ref().sa_family } { | ||
AF_INET6 => { | ||
let addr: NonNull<SOCKADDR_IN6> = addr.cast(); | ||
Some(SockAddr::AfInet6(unsafe { | ||
SockAddrIn::<AfInet6>::from_raw(addr) | ||
})) | ||
} | ||
AF_INET => { | ||
let addr: NonNull<SOCKADDR_IN> = addr.cast(); | ||
|
||
Some(SockAddr::AfInet(unsafe { | ||
SockAddrIn::<AfInet>::from_raw(addr) | ||
})) | ||
} | ||
_ => None, | ||
} | ||
} | ||
} | ||
|
||
impl<'a> SockAddrIn<'a, AfInet> { | ||
pub const fn sin_family(&self) -> ADDRESS_FAMILY { | ||
unsafe { self.addr.as_ref() }.sin_family | ||
} | ||
|
||
pub const fn sin_port(&self) -> u16 { | ||
unsafe { self.addr.as_ref() }.sin_port | ||
} | ||
|
||
pub const fn sin_addr(&self) -> IN_ADDR { | ||
unsafe { self.addr.as_ref() }.sin_addr | ||
} | ||
} |
Oops, something went wrong.