Skip to content

Commit

Permalink
update manual tavern client to abide by new kyle stuffs (#497)
Browse files Browse the repository at this point in the history
  • Loading branch information
Cictrone authored Jan 23, 2024
1 parent 7fd5b31 commit 30eff2f
Showing 1 changed file with 60 additions and 28 deletions.
88 changes: 60 additions & 28 deletions implants/lib/c2/src/c2_manual.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,10 @@ pub mod c2_manual_client {
use tonic::GrpcMethod;

static CLAIM_TASKS_PATH: &str = "/c2.C2/ClaimTasks";
static REPORT_TASK_OUTPUT_PATH: &str = "/c2.C2/ReportTaskOutput";
static REPORT_PROCESS_LIST_PATH: &str = "/c2.C2/ReportProcessList";
static DOWNLOAD_FILE_PATH: &str = "/c2.C2/DownloadFile";
static REPORT_FILE_PATH: &str = "/c2.C2/ReportFile";
static REPORT_PROCESS_LIST_PATH: &str = "/c2.C2/ReportProcessList";
static REPORT_TASK_OUTPUT_PATH: &str = "/c2.C2/ReportTaskOutput";

#[derive(Debug, Clone)]
pub struct TavernClient {
Expand All @@ -21,6 +22,8 @@ pub mod c2_manual_client {
Ok(Self { grpc })
}

///
/// Contact the server for new tasks to execute.
pub async fn claim_tasks(
&mut self,
request: impl tonic::IntoRequest<super::ClaimTasksRequest>,
Expand All @@ -42,25 +45,61 @@ pub mod c2_manual_client {
self.grpc.unary(req, path, codec).await
}

pub async fn report_task_output(
///
/// Download a file from the server, returning one or more chunks of data.
/// The maximum size of these chunks is determined by the server.
/// The server should reply with two headers:
/// - "sha3-256-checksum": A SHA3-256 digest of the entire file contents.
/// - "file-size": The number of bytes contained by the file.
///
/// If no associated file can be found, a NotFound status error is returned.
pub async fn download_file(
&mut self,
request: impl tonic::IntoRequest<super::ReportTaskOutputRequest>,
) -> std::result::Result<tonic::Response<super::ReportTaskOutputResponse>, tonic::Status>
{
request: impl tonic::IntoRequest<super::DownloadFileRequest>,
) -> std::result::Result<
tonic::Response<tonic::codec::Streaming<super::DownloadFileResponse>>,
tonic::Status,
> {
self.grpc.ready().await.map_err(|e| {
tonic::Status::new(
tonic::Code::Unknown,
format!("Service was not ready: {}", e),
)
})?;
let codec: ProstCodec<super::ReportTaskOutputRequest, super::ReportTaskOutputResponse> =
let codec: ProstCodec<super::DownloadFileRequest, super::DownloadFileResponse> =
tonic::codec::ProstCodec::default();
let path =
tonic::codegen::http::uri::PathAndQuery::from_static(REPORT_TASK_OUTPUT_PATH);
let path = tonic::codegen::http::uri::PathAndQuery::from_static(DOWNLOAD_FILE_PATH);
let mut req = request.into_request();
req.extensions_mut()
.insert(GrpcMethod::new("c2.C2", "ReportTaskOutput"));
self.grpc.unary(req, path, codec).await
.insert(GrpcMethod::new("c2.C2", "DownloadFile"));
self.grpc.server_streaming(req, path, codec).await
}

///
/// Report a file from the host to the server.
/// Providing content of the file is optional. If content is provided:
/// - Hash will automatically be calculated and the provided hash will be ignored.
/// - Size will automatically be calculated and the provided size will be ignored.
/// Content is provided as chunks, the size of which are up to the agent to define (based on memory constraints).
/// Any existing files at the provided path for the host are replaced.
pub async fn report_file(
&mut self,
request: impl tonic::IntoStreamingRequest<Message = super::ReportFileRequest>,
) -> std::result::Result<tonic::Response<super::ReportFileResponse>, tonic::Status>
{
self.grpc.ready().await.map_err(|e| {
tonic::Status::new(
tonic::Code::Unknown,
format!("Service was not ready: {}", e),
)
})?;
let codec: ProstCodec<super::ReportFileRequest, super::ReportFileResponse> =
tonic::codec::ProstCodec::default();
let path = tonic::codegen::http::uri::PathAndQuery::from_static(REPORT_FILE_PATH);
let mut req = request.into_streaming_request();
req.extensions_mut()
.insert(GrpcMethod::new("c2.C2", "ReportFile"));
self.grpc.client_streaming(req, path, codec).await
}

///
Expand Down Expand Up @@ -90,33 +129,26 @@ pub mod c2_manual_client {
}

///
/// Download a file from the server, returning one or more chunks of data.
/// The maximum size of these chunks is determined by the server.
/// The server should reply with two headers:
/// - "sha3-256-checksum": A SHA3-256 digest of the entire file contents.
/// - "file-size": The number of bytes contained by the file.
///
/// If no associated file can be found, a NotFound status error is returned.
pub async fn download_file(
/// Report execution output for a task.
pub async fn report_task_output(
&mut self,
request: impl tonic::IntoRequest<super::DownloadFileRequest>,
) -> std::result::Result<
tonic::Response<tonic::codec::Streaming<super::DownloadFileResponse>>,
tonic::Status,
> {
request: impl tonic::IntoRequest<super::ReportTaskOutputRequest>,
) -> std::result::Result<tonic::Response<super::ReportTaskOutputResponse>, tonic::Status>
{
self.grpc.ready().await.map_err(|e| {
tonic::Status::new(
tonic::Code::Unknown,
format!("Service was not ready: {}", e),
)
})?;
let codec: ProstCodec<super::DownloadFileRequest, super::DownloadFileResponse> =
let codec: ProstCodec<super::ReportTaskOutputRequest, super::ReportTaskOutputResponse> =
tonic::codec::ProstCodec::default();
let path = tonic::codegen::http::uri::PathAndQuery::from_static(DOWNLOAD_FILE_PATH);
let path =
tonic::codegen::http::uri::PathAndQuery::from_static(REPORT_TASK_OUTPUT_PATH);
let mut req = request.into_request();
req.extensions_mut()
.insert(GrpcMethod::new("c2.C2", "DownloadFile"));
self.grpc.server_streaming(req, path, codec).await
.insert(GrpcMethod::new("c2.C2", "ReportTaskOutput"));
self.grpc.unary(req, path, codec).await
}
}
}

0 comments on commit 30eff2f

Please sign in to comment.