mirror of
https://github.com/EFForg/rayhunter.git
synced 2026-05-27 10:04:47 -07:00
Merge pull request #9 from EFForg/failsafe
Debug logging, rename to Wave Hunter
This commit is contained in:
30
Cargo.lock
generated
30
Cargo.lock
generated
@@ -197,21 +197,6 @@ dependencies = [
|
||||
"syn 1.0.109",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "diag"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"bytes",
|
||||
"chrono",
|
||||
"crc",
|
||||
"deku",
|
||||
"env_logger",
|
||||
"libc",
|
||||
"log",
|
||||
"pcap-file",
|
||||
"thiserror",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "env_logger"
|
||||
version = "0.10.1"
|
||||
@@ -596,6 +581,21 @@ version = "0.2.89"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7ab9b36309365056cd639da3134bf87fa8f3d86008abf99e612384a6eecd459f"
|
||||
|
||||
[[package]]
|
||||
name = "wavehunter"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"bytes",
|
||||
"chrono",
|
||||
"crc",
|
||||
"deku",
|
||||
"env_logger",
|
||||
"libc",
|
||||
"log",
|
||||
"pcap-file",
|
||||
"thiserror",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "winapi"
|
||||
version = "0.3.9"
|
||||
|
||||
14
Cargo.toml
14
Cargo.toml
@@ -1,10 +1,22 @@
|
||||
[package]
|
||||
name = "diag"
|
||||
name = "wavehunter"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[lib]
|
||||
name = "wavehunter"
|
||||
path = "src/lib.rs"
|
||||
|
||||
[[bin]]
|
||||
name = "wavehunter-reader"
|
||||
path = "src/bin/wavehunter_reader.rs"
|
||||
|
||||
[[bin]]
|
||||
name = "wavehunter"
|
||||
path = "src/bin/wavehunter.rs"
|
||||
|
||||
[dependencies]
|
||||
bytes = "1.5.0"
|
||||
chrono = "0.4.31"
|
||||
|
||||
26
README.md
26
README.md
@@ -1 +1,27 @@
|
||||
# Wave Hunter
|
||||
|
||||
```
|
||||
@@@ @@@ @@@ @@@@@@ @@@ @@@ @@@@@@@@ @@@ @@@ @@@ @@@ @@@ @@@ @@@@@@@ @@@@@@@@ @@@@@@@
|
||||
@@! @@! @@! @@! @@@ @@! @@@ @@! @@! @@@ @@! @@@ @@!@!@@@ @!! @@! @@! @@@
|
||||
@!! !!@ @!@ @!@!@!@! @!@ !@! @!!!:! @!@!@!@! @!@ !@! @!@@!!@! @!! @!!!:! @!@!!@!
|
||||
!: !!: !! !!: !!! !: .:! !!: !!: !!! !!: !!! !!: !!! !!: !!: !!: :!!
|
||||
::.: ::: : : : :: : :: :: : : : :.:: : :: : : : :: :: : : :
|
||||
|
||||
_ _ _ _ _ _ _ _
|
||||
)`'-.,_)`'-.,_)`'-.,_)`'-.,_)`'-.,_)`'-.,_)`'-.,_)`'-.,_
|
||||
|
||||
O .
|
||||
O ' '
|
||||
o ' .
|
||||
o .'
|
||||
__________.-' '...___
|
||||
.-' ### '''...__
|
||||
/ a### ## ''--.._ ______
|
||||
'. # ######## ' .-'
|
||||
'-._ ..**********#### ___...---'''\ '
|
||||
'-._ __________...---''' \ l
|
||||
\ | apc '._|
|
||||
\__;
|
||||
```
|
||||
|
||||
diag helper binary for the Orbic mobile hotspot. Based on code from [QCSuper](https://github.com/P1sec/QCSuper)
|
||||
|
||||
@@ -1,11 +1,7 @@
|
||||
mod hdlc;
|
||||
mod diag;
|
||||
mod diag_device;
|
||||
mod log_codes;
|
||||
use wavehunter::diag_device::{DiagDevice, DiagResult};
|
||||
use wavehunter::diag_reader::DiagReader;
|
||||
|
||||
use crate::diag_device::DiagDevice;
|
||||
|
||||
fn main() -> diag_device::DiagResult<()> {
|
||||
fn main() -> DiagResult<()> {
|
||||
// this should eventually be removed for prod
|
||||
env_logger::init();
|
||||
|
||||
@@ -14,6 +10,7 @@ fn main() -> diag_device::DiagResult<()> {
|
||||
.write(true)
|
||||
.open("/dev/diag")?;
|
||||
let mut dev = DiagDevice::new(&file)?;
|
||||
dev.enable_debug_mode("/data/wavehunter-debug")?;
|
||||
dev.config_logs()?;
|
||||
|
||||
loop {
|
||||
20
src/bin/wavehunter_reader.rs
Normal file
20
src/bin/wavehunter_reader.rs
Normal file
@@ -0,0 +1,20 @@
|
||||
use wavehunter::debug_file::DebugFileReader;
|
||||
use wavehunter::diag_reader::DiagReader;
|
||||
use wavehunter::diag_device::DiagResult;
|
||||
|
||||
fn main() -> DiagResult<()> {
|
||||
// this should eventually be removed for prod
|
||||
env_logger::init();
|
||||
let args: Vec<String> = std::env::args().collect();
|
||||
if args.len() != 2 {
|
||||
println!("Usage: {} /path/to/debug/file", args[0]);
|
||||
std::process::exit(1);
|
||||
}
|
||||
let mut debug_reader = DebugFileReader::new(&args[1])?;
|
||||
|
||||
loop {
|
||||
for msg in debug_reader.read_response()? {
|
||||
println!("msg: {:?}", msg);
|
||||
}
|
||||
}
|
||||
}
|
||||
50
src/debug_file.rs
Normal file
50
src/debug_file.rs
Normal file
@@ -0,0 +1,50 @@
|
||||
use crate::diag_reader::DiagReader;
|
||||
use crate::diag_device::DiagResult;
|
||||
use crate::diag::*;
|
||||
|
||||
use deku::prelude::*;
|
||||
use std::fs::File;
|
||||
use std::io::Read;
|
||||
|
||||
#[derive(Debug, DekuRead, DekuWrite)]
|
||||
#[deku(endian = "little")]
|
||||
pub struct DebugFileBlock<'a> {
|
||||
pub size: u32,
|
||||
#[deku(count = "size")]
|
||||
pub data: &'a [u8],
|
||||
}
|
||||
|
||||
pub struct DebugFileReader {
|
||||
file: File,
|
||||
}
|
||||
|
||||
impl DebugFileReader {
|
||||
pub fn new<P>(path: P) -> DiagResult<Self> where P: AsRef<std::path::Path> {
|
||||
let file = std::fs::File::options()
|
||||
.read(true)
|
||||
.open(path)?;
|
||||
Ok(DebugFileReader { file })
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
impl DiagReader for DebugFileReader {
|
||||
fn get_next_messages_container(&mut self) -> DiagResult<MessagesContainer> {
|
||||
let mut bytes_read_buf = [0; 4];
|
||||
if let Err(e) = self.file.read_exact(&mut bytes_read_buf) {
|
||||
if e.kind() == std::io::ErrorKind::UnexpectedEof {
|
||||
println!("reached end of debug file, exiting...");
|
||||
std::process::exit(0);
|
||||
}
|
||||
return Err(e.into());
|
||||
}
|
||||
let bytes_read = u32::from_le_bytes(bytes_read_buf) as usize;
|
||||
let mut data = vec![0; bytes_read as usize];
|
||||
self.file.read_exact(&mut data)?;
|
||||
let ((leftover_bytes, _), container) = MessagesContainer::from_bytes((&data, 0))?;
|
||||
if leftover_bytes.len() > 0 {
|
||||
println!("warning: {} leftover bytes when parsing MessagesContainer", leftover_bytes.len());
|
||||
}
|
||||
Ok(container)
|
||||
}
|
||||
}
|
||||
@@ -391,11 +391,4 @@ mod test {
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_fuck() {
|
||||
env_logger::init();
|
||||
let data = vec![32, 0, 0, 0, 1, 0, 0, 0, 122, 1, 0, 0, 16, 0, 38, 0, 38, 0, 192, 176, 153, 128, 249, 211, 218, 62, 2, 1, 20, 14, 48, 0, 160, 0, 14, 6, 1, 0, 217, 39, 5, 0, 0, 0, 0, 7, 0, 64, 2, 14, 213, 72, 153, 192, 168, 216, 126];
|
||||
dbg!(MessagesContainer::from_bytes((&data, 0)).unwrap());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,12 +1,13 @@
|
||||
use crate::hdlc::{hdlc_encapsulate, hdlc_decapsulate, HdlcError};
|
||||
use crate::hdlc::{hdlc_encapsulate, HdlcError};
|
||||
use crate::diag::{Message, ResponsePayload, Request, LogConfigRequest, LogConfigResponse, build_log_mask_request, RequestContainer, DataType, MessagesContainer};
|
||||
use crate::diag_reader::{DiagReader, CRC_CCITT};
|
||||
use crate::debug_file::DebugFileBlock;
|
||||
use crate::log_codes;
|
||||
|
||||
use std::fs::File;
|
||||
use std::io::Read;
|
||||
use std::io::{Read, Write};
|
||||
use std::os::fd::AsRawFd;
|
||||
use thiserror::Error;
|
||||
use crc::{Crc, Algorithm};
|
||||
use deku::prelude::*;
|
||||
|
||||
pub type DiagResult<T> = Result<T, DiagDeviceError>;
|
||||
@@ -29,19 +30,6 @@ pub enum DiagDeviceError {
|
||||
DekuError(#[from] DekuError),
|
||||
}
|
||||
|
||||
// this is sorta based on the params qcsuper uses, plus what seems to be used in
|
||||
// https://github.com/fgsect/scat/blob/f1538b397721df3ab8ba12acd26716abcf21f78b/util.py#L47
|
||||
pub const CRC_CCITT_ALG: Algorithm<u16> = Algorithm {
|
||||
poly: 0x1021,
|
||||
init: 0xffff,
|
||||
refin: true,
|
||||
refout: true,
|
||||
width: 16,
|
||||
xorout: 0xffff,
|
||||
check: 0x2189,
|
||||
residue: 0x0000,
|
||||
};
|
||||
|
||||
pub const LOG_CODES_FOR_RAW_PACKET_LOGGING: [u32; 11] = [
|
||||
// Layer 2:
|
||||
log_codes::LOG_GPRS_MAC_SIGNALLING_MESSAGE_C, // 0x5226
|
||||
@@ -70,9 +58,30 @@ const DIAG_IOCTL_SWITCH_LOGGING: u32 = 7;
|
||||
|
||||
pub struct DiagDevice<'a> {
|
||||
file: &'a File,
|
||||
debug_file: Option<File>,
|
||||
read_buf: Vec<u8>,
|
||||
use_mdm: i32,
|
||||
crc: Crc<u16>,
|
||||
}
|
||||
|
||||
|
||||
|
||||
impl<'a> DiagReader for DiagDevice<'a> {
|
||||
fn get_next_messages_container(&mut self) -> DiagResult<MessagesContainer> {
|
||||
let bytes_read = self.file.read(&mut self.read_buf).unwrap();
|
||||
if let Some(debug_file) = self.debug_file.as_mut() {
|
||||
let debug_block = DebugFileBlock {
|
||||
size: bytes_read as u32,
|
||||
data: &self.read_buf[0..bytes_read],
|
||||
};
|
||||
let debug_block_bytes = debug_block.to_bytes().unwrap();
|
||||
debug_file.write_all(&debug_block_bytes).unwrap();
|
||||
}
|
||||
let ((leftover_bytes, _), container) = MessagesContainer::from_bytes((&self.read_buf[0..bytes_read], 0))?;
|
||||
if leftover_bytes.len() > 0 {
|
||||
println!("warning: {} leftover bytes when parsing MessagesContainer", leftover_bytes.len());
|
||||
}
|
||||
Ok(container)
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> DiagDevice<'a> {
|
||||
@@ -85,51 +94,21 @@ impl<'a> DiagDevice<'a> {
|
||||
Ok(DiagDevice {
|
||||
read_buf: vec![0; BUFFER_LEN],
|
||||
file,
|
||||
crc: Crc::<u16>::new(&CRC_CCITT_ALG),
|
||||
debug_file: None,
|
||||
use_mdm,
|
||||
})
|
||||
}
|
||||
|
||||
fn parse_response_container(&self, container: MessagesContainer) -> DiagResult<Vec<Message>> {
|
||||
let mut result = Vec::new();
|
||||
for msg in container.messages {
|
||||
for sub_msg in msg.data.split_inclusive(|&b| b == 0x7e) {
|
||||
match hdlc_decapsulate(&sub_msg, &self.crc) {
|
||||
Ok(data) => match Message::from_bytes((&data, 0)) {
|
||||
Ok(((leftover_bytes, _), res)) => {
|
||||
if leftover_bytes.len() > 0 {
|
||||
println!("warning: {} leftover bytes when parsing Message", leftover_bytes.len());
|
||||
}
|
||||
result.push(res);
|
||||
},
|
||||
Err(e) => {
|
||||
println!("error parsing response: {:?}", e);
|
||||
println!("{:?}", data);
|
||||
},
|
||||
},
|
||||
Err(err) => {
|
||||
println!("error decapsulating response: {:?}", err);
|
||||
println!("{:?}", &sub_msg);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Ok(result)
|
||||
}
|
||||
|
||||
pub fn read_response(&mut self) -> DiagResult<Vec<Message>> {
|
||||
loop {
|
||||
let bytes_read = self.file.read(&mut self.read_buf).unwrap();
|
||||
let ((leftover_bytes, _), res_container) = MessagesContainer::from_bytes((&self.read_buf[0..bytes_read], 0))?;
|
||||
if leftover_bytes.len() > 0 {
|
||||
println!("warning: {} leftover bytes when parsing MessagesContainer", leftover_bytes.len());
|
||||
}
|
||||
if res_container.data_type == DataType::UserSpace {
|
||||
return self.parse_response_container(res_container);
|
||||
} else {
|
||||
println!("skipping non-userspace message...")
|
||||
}
|
||||
}
|
||||
// Creates a file at the given path where all binary output from /dev/diag
|
||||
// will be recorded.
|
||||
pub fn enable_debug_mode<P>(&mut self, path: P) -> DiagResult<()> where P: AsRef<std::path::Path> {
|
||||
let debug_file = std::fs::File::options()
|
||||
.create(true)
|
||||
.write(true)
|
||||
.open(path)?;
|
||||
println!("enabling debug mode, writing debug output to {:?}", debug_file);
|
||||
self.debug_file = Some(debug_file);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn write_request(&mut self, req: &Request) -> DiagResult<()> {
|
||||
@@ -137,7 +116,7 @@ impl<'a> DiagDevice<'a> {
|
||||
data_type: DataType::UserSpace,
|
||||
use_mdm: self.use_mdm > 0,
|
||||
mdm_field: -1,
|
||||
hdlc_encapsulated_request: hdlc_encapsulate(&req.to_bytes().unwrap(), &self.crc),
|
||||
hdlc_encapsulated_request: hdlc_encapsulate(&req.to_bytes().unwrap(), &CRC_CCITT),
|
||||
}.to_bytes().unwrap();
|
||||
unsafe {
|
||||
let fd = self.file.as_raw_fd();
|
||||
|
||||
61
src/diag_reader.rs
Normal file
61
src/diag_reader.rs
Normal file
@@ -0,0 +1,61 @@
|
||||
use crate::{diag::*, hdlc::hdlc_decapsulate};
|
||||
use crate::diag_device::DiagResult;
|
||||
|
||||
use crc::{Crc, Algorithm};
|
||||
use deku::prelude::*;
|
||||
|
||||
// this is sorta based on the params qcsuper uses, plus what seems to be used in
|
||||
// https://github.com/fgsect/scat/blob/f1538b397721df3ab8ba12acd26716abcf21f78b/util.py#L47
|
||||
pub const CRC_CCITT_ALG: Algorithm<u16> = Algorithm {
|
||||
poly: 0x1021,
|
||||
init: 0xffff,
|
||||
refin: true,
|
||||
refout: true,
|
||||
width: 16,
|
||||
xorout: 0xffff,
|
||||
check: 0x2189,
|
||||
residue: 0x0000,
|
||||
};
|
||||
pub const CRC_CCITT: Crc<u16> = Crc::<u16>::new(&CRC_CCITT_ALG);
|
||||
|
||||
pub trait DiagReader {
|
||||
fn get_next_messages_container(&mut self) -> DiagResult<MessagesContainer>;
|
||||
|
||||
fn read_response(&mut self) -> DiagResult<Vec<Message>> {
|
||||
loop {
|
||||
let container = self.get_next_messages_container()?;
|
||||
if container.data_type == DataType::UserSpace {
|
||||
return self.parse_response_container(container);
|
||||
} else {
|
||||
println!("skipping non-userspace message...")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn parse_response_container(&self, container: MessagesContainer) -> DiagResult<Vec<Message>> {
|
||||
let mut result = Vec::new();
|
||||
for msg in container.messages {
|
||||
for sub_msg in msg.data.split_inclusive(|&b| b == 0x7e) {
|
||||
match hdlc_decapsulate(&sub_msg, &CRC_CCITT) {
|
||||
Ok(data) => match Message::from_bytes((&data, 0)) {
|
||||
Ok(((leftover_bytes, _), res)) => {
|
||||
if leftover_bytes.len() > 0 {
|
||||
println!("warning: {} leftover bytes when parsing Message", leftover_bytes.len());
|
||||
}
|
||||
result.push(res);
|
||||
},
|
||||
Err(e) => {
|
||||
println!("error parsing response: {:?}", e);
|
||||
println!("{:?}", data);
|
||||
},
|
||||
},
|
||||
Err(err) => {
|
||||
println!("error decapsulating response: {:?}", err);
|
||||
println!("{:?}", &sub_msg);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Ok(result)
|
||||
}
|
||||
}
|
||||
@@ -87,7 +87,7 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn test_hdlc_encapsulate() {
|
||||
let crc = Crc::<u16>::new(&crate::diag_device::CRC_CCITT_ALG);
|
||||
let crc = Crc::<u16>::new(&crate::diag_reader::CRC_CCITT_ALG);
|
||||
let data = vec![0x01, 0x02, 0x03, 0x04];
|
||||
let expected = vec![1, 2, 3, 4, 145, 57, 126];
|
||||
let encapsulated = hdlc_encapsulate(&data, &crc);
|
||||
|
||||
6
src/lib.rs
Normal file
6
src/lib.rs
Normal file
@@ -0,0 +1,6 @@
|
||||
pub mod hdlc;
|
||||
pub mod diag;
|
||||
pub mod diag_device;
|
||||
pub mod diag_reader;
|
||||
pub mod debug_file;
|
||||
pub mod log_codes;
|
||||
Reference in New Issue
Block a user