Skip to content

Commit

Permalink
upgrade etherparse to 0.14
Browse files Browse the repository at this point in the history
  • Loading branch information
WebFreak001 committed Mar 11, 2024
1 parent 049ccf0 commit 6da0c11
Show file tree
Hide file tree
Showing 6 changed files with 89 additions and 78 deletions.
4 changes: 2 additions & 2 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions leech/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -86,8 +86,8 @@ tokio-native-tls = { version = "~0.3" }

# raw sockets
socket2 = { version = "~0.5" }
etherparse = { version = "~0.13" }
nix = { version = "~0.28", features = ["net"] }
etherparse = { version = "~0.14" }
nix = { version = "~0.28", features = ["net"] }
strum = { version = "~0.26" }
strum_macros = { version = "~0.26" }

Expand Down
8 changes: 5 additions & 3 deletions leech/src/modules/os_detection/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
use std::io;

use etherparse::ReadError;
use etherparse::err::ip::LaxHeaderSliceError;
use etherparse::TcpOptionReadError;
use thiserror::Error;
use tokio::task::JoinError;
Expand Down Expand Up @@ -47,8 +47,10 @@ pub enum RawTcpError {
/// Regular I/O errors
#[error("I/O error: {0}")]
IoError(#[from] io::Error),
#[error("Failed parsing IP/TCP packet: {0}")]
PacketParseError(#[from] ReadError),
#[error("Failed parsing IP packet: {0}")]
IpParseError(#[from] etherparse::err::ip::SliceError),
#[error("Failed parsing packet: {0}")]
PacketParseError(#[from] LaxHeaderSliceError),
#[error("Failed parsing TCP option: {0}")]
TcpOptionParseError(#[from] TcpOptionReadError),
#[error("Socket was created in IPv4/v6 domain, but local_addr didn't match the domain")]
Expand Down
105 changes: 52 additions & 53 deletions leech/src/modules/os_detection/syn_scan.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,18 +3,19 @@ use std::net::IpAddr;
use std::net::SocketAddr;
use std::time::Duration;

use etherparse::packet_filter::ElementFilter;
use etherparse::InternetSlice;
use etherparse::IpHeader;
use etherparse::IpHeaders;
use etherparse::IpNumber;
use etherparse::Ipv4Extensions;
use etherparse::Ipv4Header;
use etherparse::Ipv6ExtensionSlice;
use etherparse::Ipv6Extensions;
use etherparse::Ipv6ExtensionsSlice;
use etherparse::Ipv6FlowLabel;
use etherparse::Ipv6Header;
use etherparse::Ipv6RoutingExtensions;
use etherparse::LaxNetSlice;
use etherparse::LaxSlicedPacket;
use etherparse::PacketBuilder;
use etherparse::SlicedPacket;
use etherparse::TcpHeader;
use etherparse::TcpOptionElement;
use etherparse::TransportSlice;
Expand Down Expand Up @@ -68,61 +69,52 @@ pub async fn tcp_get_syn_ack(
address: SocketAddr,
recv_port: u16,
syn: &[u8],
) -> Result<(IpHeader, TcpHeader), RawTcpError> {
let recv_tcp_filter = etherparse::packet_filter::TransportFilter::Tcp {
source_port: Some(address.port()),
destination_port: Some(recv_port),
};
let recv_ip_filter = match address.ip() {
IpAddr::V4(v4) => etherparse::packet_filter::IpFilter::Ipv4 {
source: Some(v4.octets()),
destination: None,
},
IpAddr::V6(v6) => etherparse::packet_filter::IpFilter::Ipv6 {
source: Some(v6.octets()),
destination: None,
},
};
let recv_filter = etherparse::packet_filter::Filter {
ip: ElementFilter::Some(recv_ip_filter),
transport: ElementFilter::Some(recv_tcp_filter),
link: ElementFilter::Any,
vlan: ElementFilter::Any,
};

) -> Result<(IpHeaders, TcpHeader), RawTcpError> {
socket.send_to(syn, address).await?;

let mut buf = [0u8; 256];

loop {
let (len, _) = socket.recv_from(&mut buf).await?;

let packet = SlicedPacket::from_ip(&buf[0..len])?;
if !recv_filter.applies_to_slice(&packet) {
let packet = LaxSlicedPacket::from_ip(&buf[0..len])?;
let Some(net) = packet.net else {
continue;
};

let Some(TransportSlice::Tcp(tcp)) = packet.transport else {
continue;
};
if tcp.source_port() != address.port()
|| tcp.destination_port() != recv_port
|| !(tcp.syn() && tcp.ack())
{
continue;
}

if let Some(transport_slice) = packet.transport {
return Ok(match transport_slice {
TransportSlice::Tcp(tcp) => {
if !(tcp.syn() && tcp.ack()) {
return Ok((
match (net, address.ip()) {
(LaxNetSlice::Ipv4(in_v4), IpAddr::V4(expect_v4)) => {
if in_v4.header().source_addr() != expect_v4 {
continue;
}

(match packet.ip.expect("must have ip since we decoded from ip") {
InternetSlice::Ipv4(ip, ext) => IpHeader::Version4(
ip.to_header(),
ext.to_header()
),
InternetSlice::Ipv6(ip, ext) => IpHeader::Version6(
ip.to_header(),
make_ipv6_headers(&ext)
)
}, tcp.to_header())
},
_ => panic!("should never reach this since the TransportFilter::Tcp (recv_filter) matched on this")
});
}
IpHeaders::Ipv4(in_v4.header().to_header(), in_v4.extensions().to_header())
}
(LaxNetSlice::Ipv6(in_v6), IpAddr::V6(expect_v6)) => {
if in_v6.header().source_addr() != expect_v6 {
continue;
}

IpHeaders::Ipv6(
in_v6.header().to_header(),
make_ipv6_headers(in_v6.extensions()),
)
}
(_, _) => continue,
},
tcp.to_header(),
));
}
}

Expand All @@ -141,20 +133,27 @@ pub async fn check_syn_ack(address: SocketAddr, timeout: Duration) -> Result<boo

let syn = PacketBuilder::ip(match (address, source_ip) {
(SocketAddr::V4(addr), IpAddr::V4(local_addr)) => {
let mut ip = Ipv4Header::new(0, 42, 6, local_addr.octets(), addr.ip().octets());
let mut ip = Ipv4Header::new(
0,
42,
IpNumber::TCP,
local_addr.octets(),
addr.ip().octets(),
)
.expect("failed creating Ipv4Header with static values?!");
ip.identification = rand::random();

IpHeader::Version4(ip, Ipv4Extensions { auth: None })
IpHeaders::Ipv4(ip, Ipv4Extensions { auth: None })
}
(SocketAddr::V6(addr), IpAddr::V6(local_addr)) => IpHeader::Version6(
(SocketAddr::V6(addr), IpAddr::V6(local_addr)) => IpHeaders::Ipv6(
Ipv6Header {
traffic_class: 0, // TODO: sane values?
source: local_addr.octets(),
destination: addr.ip().octets(),
flow_label: 0, // TODO: sane values?
hop_limit: 0, // TODO: sane values?
next_header: 0, // TODO: sane values?
payload_length: 0, // filled in by OS
flow_label: Ipv6FlowLabel::ZERO, // TODO: sane values?
hop_limit: 0, // TODO: sane values?
next_header: IpNumber(0), // TODO: sane values?
payload_length: 0, // filled in by OS
},
Ipv6Extensions {
auth: None,
Expand Down
41 changes: 25 additions & 16 deletions leech/src/modules/os_detection/tcp_fingerprint.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,12 @@ use std::net::IpAddr;
use std::net::SocketAddr;
use std::time::Duration;

use etherparse::IpHeader;
use etherparse::IpHeaders;
use etherparse::IpNumber;
use etherparse::Ipv4Extensions;
use etherparse::Ipv4Header;
use etherparse::Ipv6Extensions;
use etherparse::Ipv6FlowLabel;
use etherparse::Ipv6Header;
use etherparse::PacketBuilder;
use etherparse::TcpOptionElement;
Expand Down Expand Up @@ -101,20 +103,27 @@ async fn fingerprint_tcp_impl(address: SocketAddr) -> Result<TcpFingerprint, Raw

let syn = PacketBuilder::ip(match (address, source_ip) {
(SocketAddr::V4(addr), IpAddr::V4(local_addr)) => {
let mut ip = Ipv4Header::new(0, 42, 6, local_addr.octets(), addr.ip().octets());
let mut ip = Ipv4Header::new(
0,
42,
IpNumber::TCP,
local_addr.octets(),
addr.ip().octets(),
)
.expect("failed creating Ipv4Header from static values?!");
ip.identification = rand::random();

IpHeader::Version4(ip, Ipv4Extensions { auth: None })
IpHeaders::Ipv4(ip, Ipv4Extensions { auth: None })
}
(SocketAddr::V6(addr), IpAddr::V6(local_addr)) => IpHeader::Version6(
(SocketAddr::V6(addr), IpAddr::V6(local_addr)) => IpHeaders::Ipv6(
Ipv6Header {
traffic_class: 0, // TODO: sane values?
source: local_addr.octets(),
destination: addr.ip().octets(),
flow_label: 0, // TODO: sane values?
hop_limit: 0, // TODO: sane values?
next_header: 0, // TODO: sane values?
payload_length: 0, // filled in by OS
flow_label: Ipv6FlowLabel::ZERO, // TODO: sane values?
hop_limit: 0, // TODO: sane values?
next_header: IpNumber(0), // TODO: sane values?
payload_length: 0, // filled in by OS
},
Ipv6Extensions {
auth: None,
Expand Down Expand Up @@ -176,23 +185,23 @@ async fn fingerprint_tcp_impl(address: SocketAddr) -> Result<TcpFingerprint, Raw

Ok(TcpFingerprint {
is_ipv4: match &ip {
IpHeader::Version4(_, _) => true,
IpHeader::Version6(_, _) => false,
IpHeaders::Ipv4(_, _) => true,
IpHeaders::Ipv6(_, _) => false,
},
payload_len: min(
match &ip {
IpHeader::Version4(header, _) => header.payload_len,
IpHeader::Version6(header, _) => header.payload_length,
IpHeaders::Ipv4(header, _) => header.payload_len().unwrap_or(255),
IpHeaders::Ipv6(header, _) => header.payload_length,
},
255u16,
) as u8,
has_identification: match &ip {
IpHeader::Version4(header, _) => header.identification != 0,
IpHeader::Version6(_, _) => false,
IpHeaders::Ipv4(header, _) => header.identification != 0,
IpHeaders::Ipv6(_, _) => false,
},
ttl: match &ip {
IpHeader::Version4(header, _) => header.time_to_live,
IpHeader::Version6(header, _) => header.hop_limit,
IpHeaders::Ipv4(header, _) => header.time_to_live,
IpHeaders::Ipv6(header, _) => header.hop_limit,
},
window_size: tcp.window_size,
window_scale,
Expand Down
5 changes: 3 additions & 2 deletions tools/ssh-os-headers/results/test-os-android-lineage.txt
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
SSH: debug1: Remote protocol version 2.0, remote software version OpenSSH_7.2p2 Ubuntu-4ubuntu2.10
Address: 192.168.121.105:22
TCP fingerprint: Fingerprint: 8:2:28:1:7120:7:5b4:31642
TCP fingerprint: Fingerprint: 8:2:28:1:7120:7:5b4:31642
TCP fingerprint: Fingerprint: 8:2:28:1:7120:7:5b4:31642
TCP fingerprint: Fingerprint: 8:2:28:1:7120:7:5b4:31642

0 comments on commit 6da0c11

Please sign in to comment.