From 70c3cb7ebf4ccd22d89a1cc09b9aa79960e72e40 Mon Sep 17 00:00:00 2001 From: osmarks Date: Sat, 17 Apr 2021 21:35:29 +0100 Subject: [PATCH] very basic 802.11 monitoring/parsing --- .gitignore | 2 + Cargo.lock | 336 ++++++++++++++++++++++++++++++++++++++++++++++++++++ Cargo.toml | 14 +++ src/main.rs | 84 +++++++++++++ 4 files changed, 436 insertions(+) create mode 100644 .gitignore create mode 100644 Cargo.lock create mode 100644 Cargo.toml create mode 100644 src/main.rs diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..d81b2f8 --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +/target +NOTE.txt \ No newline at end of file diff --git a/Cargo.lock b/Cargo.lock new file mode 100644 index 0000000..656cc4f --- /dev/null +++ b/Cargo.lock @@ -0,0 +1,336 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +[[package]] +name = "addr2line" +version = "0.14.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a55f82cfe485775d02112886f4169bde0c5894d75e79ead7eafe7e40a25e45f7" +dependencies = [ + "gimli", +] + +[[package]] +name = "adler" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" + +[[package]] +name = "aho-corasick" +version = "0.7.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7404febffaa47dac81aa44dba71523c9d069b1bdc50a77db41195149e17f68e5" +dependencies = [ + "memchr", +] + +[[package]] +name = "antarctic-obscurity" +version = "0.1.0" +dependencies = [ + "eyre", + "int-enum", + "pcap", + "radiotap", + "stable-eyre", +] + +[[package]] +name = "autocfg" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cdb031dd78e28731d87d56cc8ffef4a8f36ca26c38fe2de700543e627f8a464a" + +[[package]] +name = "backtrace" +version = "0.3.56" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d117600f438b1707d4e4ae15d3595657288f8235a0eb593e80ecc98ab34e1bc" +dependencies = [ + "addr2line", + "cfg-if 1.0.0", + "libc", + "miniz_oxide", + "object", + "rustc-demangle", +] + +[[package]] +name = "bitflags" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693" + +[[package]] +name = "cfg-if" +version = "0.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822" + +[[package]] +name = "cfg-if" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" + +[[package]] +name = "eyre" +version = "0.6.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "221239d1d5ea86bf5d6f91c9d6bc3646ffe471b08ff9b0f91c44f115ac969d2b" +dependencies = [ + "indenter", + "once_cell", +] + +[[package]] +name = "frombytes" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1b9d7b325bca9c1ae9c6879450eee21e7374ac37b748f3bcf31b776cee2d072" +dependencies = [ + "thiserror", +] + +[[package]] +name = "gimli" +version = "0.23.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f6503fe142514ca4799d4c26297c4248239fe8838d827db6bd6065c6ed29a6ce" + +[[package]] +name = "indenter" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ce23b50ad8242c51a442f3ff322d56b02f08852c77e4c0b4d3fd684abc89c683" + +[[package]] +name = "int-enum" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b1428b2b1abe959e6eedb0a17d0ab12f6ba20e1106cc29fc4874e3ba393c177" +dependencies = [ + "cfg-if 0.1.10", + "int-enum-impl", +] + +[[package]] +name = "int-enum-impl" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a2c3cecaad8ca1a5020843500c696de2b9a07b63b624ddeef91f85f9bafb3671" +dependencies = [ + "cfg-if 0.1.10", + "proc-macro-crate", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "libc" +version = "0.2.93" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9385f66bf6105b241aa65a61cb923ef20efc665cb9f9bb50ac2f0c4b7f378d41" + +[[package]] +name = "libloading" +version = "0.6.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "351a32417a12d5f7e82c368a66781e307834dae04c6ce0cd4456d52989229883" +dependencies = [ + "cfg-if 1.0.0", + "winapi", +] + +[[package]] +name = "memchr" +version = "2.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ee1c47aaa256ecabcaea351eae4a9b01ef39ed810004e298d2511ed284b1525" + +[[package]] +name = "miniz_oxide" +version = "0.4.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a92518e98c078586bc6c934028adcca4c92a53d6a958196de835170a01d84e4b" +dependencies = [ + "adler", + "autocfg", +] + +[[package]] +name = "object" +version = "0.23.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a9a7ab5d64814df0fe4a4b5ead45ed6c5f181ee3ff04ba344313a6c80446c5d4" + +[[package]] +name = "once_cell" +version = "1.7.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "af8b08b04175473088b46763e51ee54da5f9a164bc162f615b91bc179dbf15a3" + +[[package]] +name = "pcap" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "637123ced9e43bec44bf0bbd024f3de61fbf6dfd31767023f639fc5b8ac92c49" +dependencies = [ + "libc", + "libloading", + "regex", + "widestring", +] + +[[package]] +name = "proc-macro-crate" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d6ea3c4595b96363c13943497db34af4460fb474a95c43f4446ad341b8c9785" +dependencies = [ + "toml", +] + +[[package]] +name = "proc-macro2" +version = "1.0.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a152013215dca273577e18d2bf00fa862b89b24169fb78c4c95aeb07992c9cec" +dependencies = [ + "unicode-xid", +] + +[[package]] +name = "quote" +version = "1.0.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3d0b9745dc2debf507c8422de05d7226cc1f0644216dfdfead988f9b1ab32a7" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "radiotap" +version = "2.0.0-beta.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a6c6c333a15ead1da49b6e079a5b3aa5507b1a8af0010d96602fc8daaad506d" +dependencies = [ + "bitflags", + "frombytes", + "thiserror", +] + +[[package]] +name = "regex" +version = "1.4.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "957056ecddbeba1b26965114e191d2e8589ce74db242b6ea25fc4062427a5c19" +dependencies = [ + "aho-corasick", + "memchr", + "regex-syntax", +] + +[[package]] +name = "regex-syntax" +version = "0.6.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "24d5f089152e60f62d28b835fbff2cd2e8dc0baf1ac13343bef92ab7eed84548" + +[[package]] +name = "rustc-demangle" +version = "0.1.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6e3bad0ee36814ca07d7968269dd4b7ec89ec2da10c4bb613928d3077083c232" + +[[package]] +name = "serde" +version = "1.0.125" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "558dc50e1a5a5fa7112ca2ce4effcb321b0300c0d4ccf0776a9f60cd89031171" + +[[package]] +name = "stable-eyre" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "556fec8c2da34c70b75f16d88df8a8cd7e652e567ff097b7e9df0022c8695cc4" +dependencies = [ + "backtrace", + "eyre", + "indenter", +] + +[[package]] +name = "syn" +version = "1.0.69" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "48fe99c6bd8b1cc636890bcc071842de909d902c81ac7dab53ba33c421ab8ffb" +dependencies = [ + "proc-macro2", + "quote", + "unicode-xid", +] + +[[package]] +name = "thiserror" +version = "1.0.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e0f4a65597094d4483ddaed134f409b2cb7c1beccf25201a9f73c719254fa98e" +dependencies = [ + "thiserror-impl", +] + +[[package]] +name = "thiserror-impl" +version = "1.0.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7765189610d8241a44529806d6fd1f2e0a08734313a35d5b3a556f92b381f3c0" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "toml" +version = "0.5.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a31142970826733df8241ef35dc040ef98c679ab14d7c3e54d827099b3acecaa" +dependencies = [ + "serde", +] + +[[package]] +name = "unicode-xid" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f7fe0bb3479651439c9112f72b6c505038574c9fbb575ed1bf3b797fa39dd564" + +[[package]] +name = "widestring" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7157704c2e12e3d2189c507b7482c52820a16dfa4465ba91add92f266667cadb" + +[[package]] +name = "winapi" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" +dependencies = [ + "winapi-i686-pc-windows-gnu", + "winapi-x86_64-pc-windows-gnu", +] + +[[package]] +name = "winapi-i686-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" + +[[package]] +name = "winapi-x86_64-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" diff --git a/Cargo.toml b/Cargo.toml new file mode 100644 index 0000000..9a96760 --- /dev/null +++ b/Cargo.toml @@ -0,0 +1,14 @@ +[package] +name = "antarctic-obscurity" +version = "0.1.0" +authors = ["osmarks "] +edition = "2018" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +radiotap = "=2.0.0-beta.1" +pcap = "0.8" +eyre = "0.6" +stable-eyre = "0.2" +int-enum = { version = "0.4", default-features = false, features = ["convert"] } \ No newline at end of file diff --git a/src/main.rs b/src/main.rs new file mode 100644 index 0000000..a01b10a --- /dev/null +++ b/src/main.rs @@ -0,0 +1,84 @@ +use pcap::Capture; +use stable_eyre::eyre::{eyre, Result}; + +mod ieee80211 { + use int_enum::IntEnum; + use std::convert::TryFrom; + + // data/extension frames are irrelevant so just ignore their subtype + #[derive(Clone, Copy, Debug, Eq, PartialEq)] + pub enum FrameType { + Management(ManagementSubtype), + Control(ControlSubtype), + Data, + Extension + } + + #[repr(u8)] + #[derive(Clone, Copy, Debug, Eq, PartialEq, IntEnum)] + pub enum ManagementSubtype { + ProbeRequest = 0b0100, + ProbeResponse = 0b0101, + TimingAdvertisement = 0b0110, + Beacon = 0b1000 + } + + #[repr(u8)] + #[derive(Clone, Copy, Debug, Eq, PartialEq, IntEnum)] + pub enum ControlSubtype { + Rts = 0b1011, + Cts = 0b1100, + Ack = 0b1101 + } + + #[derive(Clone, Copy, Debug, Eq, PartialEq)] + pub struct FrameControl { + pub version: u8, + pub ftype: FrameType + } + + pub fn parse_frame_control(version_type_subtype: u8, flags: u8) -> Option { + let subtype = version_type_subtype >> 4 & 0b1111; + let ftype = match version_type_subtype >> 2 & 0b11 { + 0b00 => FrameType::Management(ManagementSubtype::try_from(subtype).ok()?), + 0b01 => FrameType::Control(ControlSubtype::try_from(subtype).ok()?), + 0b10 => FrameType::Data, + 0b11 => FrameType::Extension, + _ => unreachable!() + }; + Some(FrameControl { + version: version_type_subtype & 0b11, + ftype: ftype + }) + } + + pub struct MacAddress([u8; 12]); +} + +fn main() -> Result<()> { + let cap = Capture::from_device("mon0")?.immediate_mode(true); + let mut cap = cap.open()?; + if cap.get_datalink() != pcap::Linktype::IEEE802_11_RADIOTAP { return Err(eyre!("device link type wrong")) } + + while let Ok(packet) = cap.next() { + //println!("{:?}", packet); + match radiotap::parse(packet.data) { + Ok(header) => { + let data = &packet.data[header.length()..]; + match ieee80211::parse_frame_control(data[0], data[1]) { + Some(x) if x.ftype != ieee80211::FrameType::Data => { + println!("RTH={:?} FH={:?} MAC1={:?}", header, x, &data[4..10]); + if data.len() >= 16 { println!("MAC2={:?}", &data[10..16]); } + if data.len() >= 22 { println!("MAC3={:?}", &data[16..22]); } + }, + _ => {} + } + }, + // This happens sometimes. I don't know why, since it really shouldn't (the radiotap headers are applied by the kernel). Thusly, just ignore it and hope it goes away. + Err(e) => { + eprintln!("header decoding failed: {:?}", e); + } + } + } + Ok(()) +}