Skip to content

Commit

Permalink
Changes
Browse files Browse the repository at this point in the history
  • Loading branch information
MEhrn00 committed Mar 20, 2024
1 parent a7a56ad commit 7f0dc4b
Show file tree
Hide file tree
Showing 15 changed files with 359 additions and 41 deletions.
5 changes: 5 additions & 0 deletions Payload_Type/thanatos/agent/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,11 @@ features = [
"Win32_System_Threading",
"Win32_System_SystemServices",
"Win32_Security_Cryptography",
"Win32_Networking_WinSock",
"Win32_NetworkManagement_IpHelper",
"Win32_NetworkManagement_Ndis",
"Wdk",
"Wdk_System",
"Wdk_System_SystemServices",
"Wdk_System_SystemInformation",
]
Expand Down
1 change: 1 addition & 0 deletions Payload_Type/thanatos/agent/ffiwrappers/src/lib.rs
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;
Expand Down
39 changes: 0 additions & 39 deletions Payload_Type/thanatos/agent/ffiwrappers/src/linux/socket.rs
Original file line number Diff line number Diff line change
Expand Up @@ -72,45 +72,6 @@ impl SockAddrFamily for AfInet6 {
type Inner = libc::sockaddr_in6;
}

pub enum SockAddr<'a> {
AfInet(SockAddrIn<'a, AfInet>),
AfInet6(SockAddrIn<'a, AfInet6>),
}

impl<'a> SockAddr<'a> {
/// # Safety
///
/// The pointer is not validated to ensure that it is of the correct type
pub unsafe fn from_ptr(ptr: *mut libc::sockaddr) -> Option<SockAddr<'a>> {
if ptr.is_null() {
return None;
}

match unsafe { (*ptr).sa_family } as i32 {
libc::AF_INET6 => {
let addr: NonNull<libc::sockaddr_in6> = NonNull::new(ptr.cast())?;
Some(SockAddr::AfInet6(unsafe {
SockAddrIn::<AfInet6>::from_raw(addr)
}))
}
libc::AF_INET => {
let addr: NonNull<libc::sockaddr_in> = NonNull::new(ptr.cast())?;

Some(SockAddr::AfInet(unsafe {
SockAddrIn::<AfInet>::from_raw(addr)
}))
}
_ => None,
}
}
}

#[repr(transparent)]
pub struct SockAddrIn<'a, T: SockAddrFamily> {
addr: NonNull<T::Inner>,
_marker: PhantomData<&'a T::Inner>,
}

impl<'a> SockAddrIn<'a, AfInet> {
/// # Safety
///
Expand Down
36 changes: 36 additions & 0 deletions Payload_Type/thanatos/agent/ffiwrappers/src/socket.rs
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,
}
}
}
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.
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.
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
}
}
Loading

0 comments on commit 7f0dc4b

Please sign in to comment.