mirror of
https://github.com/EFForg/rayhunter.git
synced 2026-07-23 07:48:10 -07:00
check: support pcaps
rayhunter-check will now analyze any PCAP files it finds in addition to QMDL
This commit is contained in:
committed by
Cooper Quintin
parent
3ddbaa07ca
commit
c783831e78
@@ -1,7 +1,9 @@
|
||||
use chrono::{DateTime, FixedOffset};
|
||||
use pcap_file_tokio::pcapng::blocks::enhanced_packet::EnhancedPacketBlock;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::borrow::Cow;
|
||||
|
||||
use crate::gsmtap::{GsmtapHeader, GsmtapMessage, GsmtapType};
|
||||
use crate::util::RuntimeMetadata;
|
||||
use crate::{diag::MessagesContainer, gsmtap_parser};
|
||||
|
||||
@@ -167,6 +169,39 @@ impl Harness {
|
||||
self.analyzers.push(analyzer);
|
||||
}
|
||||
|
||||
pub fn analyze_pcap_packet(&mut self, packet: EnhancedPacketBlock) -> AnalysisRow {
|
||||
let epoch = DateTime::parse_from_rfc3339("1980-01-06T00:00:00-00:00").unwrap();
|
||||
let mut row = AnalysisRow {
|
||||
packet_timestamp: Some(epoch + packet.timestamp),
|
||||
skipped_message_reason: None,
|
||||
events: Vec::new(),
|
||||
};
|
||||
let gsmtap_offset = 20 + 8;
|
||||
let gsmtap_data = &packet.data[gsmtap_offset..];
|
||||
// the type and subtype are at byte offsets 3 and 13, respectively
|
||||
let gsmtap_header = match GsmtapType::new(gsmtap_data[2], gsmtap_data[12]) {
|
||||
Ok(gsmtap_type) => GsmtapHeader::new(gsmtap_type),
|
||||
Err(err) => {
|
||||
row.skipped_message_reason = Some(format!("failed to read GsmtapHeader: {err:?}"));
|
||||
return row;
|
||||
},
|
||||
};
|
||||
let packet_offset = gsmtap_offset + 16;
|
||||
let packet_data = &packet.data[packet_offset..];
|
||||
let gsmtap_message = GsmtapMessage {
|
||||
header: gsmtap_header,
|
||||
payload: packet_data.to_vec(),
|
||||
};
|
||||
row.events = match InformationElement::try_from(&gsmtap_message) {
|
||||
Ok(element) => self.analyze_information_element(&element),
|
||||
Err(err) => {
|
||||
row.skipped_message_reason = Some(format!("failed to convert gsmtap message to IE: {err:?}"));
|
||||
return row;
|
||||
},
|
||||
};
|
||||
return row;
|
||||
}
|
||||
|
||||
pub fn analyze_qmdl_messages(&mut self, container: MessagesContainer) -> Vec<AnalysisRow> {
|
||||
let mut rows = Vec::new();
|
||||
for maybe_qmdl_message in container.into_messages() {
|
||||
@@ -211,7 +246,7 @@ impl Harness {
|
||||
rows
|
||||
}
|
||||
|
||||
fn analyze_information_element(&mut self, ie: &InformationElement) -> Vec<Option<Event>> {
|
||||
pub fn analyze_information_element(&mut self, ie: &InformationElement) -> Vec<Option<Event>> {
|
||||
self.analyzers
|
||||
.iter_mut()
|
||||
.map(|analyzer| analyzer.analyze_information_element(ie))
|
||||
|
||||
@@ -293,7 +293,7 @@ impl DiagDevice {
|
||||
// TPLINK M7350 v5 source code can be downloaded at https://www.tp-link.com/de/support/gpl-code/?app=omada
|
||||
#[repr(C)]
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
struct diag_logging_mode_param_t {
|
||||
struct DiagLoggingModeParam {
|
||||
req_mode: u32,
|
||||
peripheral_mask: u32,
|
||||
mode_param: u8,
|
||||
@@ -303,16 +303,16 @@ struct diag_logging_mode_param_t {
|
||||
fn enable_frame_readwrite(fd: i32, mode: u32) -> DiagResult<()> {
|
||||
unsafe {
|
||||
if libc::ioctl(fd, DIAG_IOCTL_SWITCH_LOGGING, mode, 0, 0, 0) < 0 {
|
||||
let try_params: &[diag_logging_mode_param_t] = &[
|
||||
let try_params: &[DiagLoggingModeParam] = &[
|
||||
// tplink M7350 HW revision 3-8 need this mode
|
||||
#[cfg(feature = "tplink")]
|
||||
diag_logging_mode_param_t {
|
||||
DiagLoggingModeParam {
|
||||
req_mode: mode,
|
||||
peripheral_mask: 0,
|
||||
mode_param: 1,
|
||||
},
|
||||
// tplink M7350 HW revision v9 requires the same parameters as orbic
|
||||
diag_logging_mode_param_t {
|
||||
DiagLoggingModeParam {
|
||||
req_mode: mode,
|
||||
peripheral_mask: u32::MAX,
|
||||
mode_param: 0,
|
||||
@@ -326,8 +326,8 @@ fn enable_frame_readwrite(fd: i32, mode: u32) -> DiagResult<()> {
|
||||
ret = libc::ioctl(
|
||||
fd,
|
||||
DIAG_IOCTL_SWITCH_LOGGING,
|
||||
&mut params as *mut diag_logging_mode_param_t,
|
||||
std::mem::size_of::<diag_logging_mode_param_t>(),
|
||||
&mut params as *mut DiagLoggingModeParam,
|
||||
std::mem::size_of::<DiagLoggingModeParam>(),
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
|
||||
+52
-4
@@ -1,6 +1,7 @@
|
||||
//! The spec for GSMTAP is here: https://github.com/osmocom/libosmocore/blob/master/include/osmocom/core/gsmtap.h
|
||||
|
||||
use deku::prelude::*;
|
||||
use num_enum::TryFromPrimitive;
|
||||
|
||||
#[derive(Debug, Copy, Clone, PartialEq)]
|
||||
pub enum GsmtapType {
|
||||
@@ -28,14 +29,14 @@ pub enum GsmtapType {
|
||||
|
||||
// based on https://github.com/fgsect/scat/blob/97442580e628de414c9f7c2a185f4e28d0ee7523/src/scat/parsers/qualcomm/diagltelogparser.py#L1337
|
||||
#[repr(u8)]
|
||||
#[derive(Debug, Copy, Clone, PartialEq)]
|
||||
#[derive(Debug, Copy, Clone, PartialEq, TryFromPrimitive)]
|
||||
pub enum LteNasSubtype {
|
||||
Plain = 0,
|
||||
Secure = 1,
|
||||
}
|
||||
|
||||
#[repr(u8)]
|
||||
#[derive(Debug, Copy, Clone, PartialEq)]
|
||||
#[derive(Debug, Copy, Clone, PartialEq, TryFromPrimitive)]
|
||||
pub enum UmSubtype {
|
||||
Unknown = 0x00,
|
||||
Bcch = 0x01,
|
||||
@@ -56,7 +57,7 @@ pub enum UmSubtype {
|
||||
}
|
||||
|
||||
#[repr(u8)]
|
||||
#[derive(Debug, Copy, Clone, PartialEq)]
|
||||
#[derive(Debug, Copy, Clone, PartialEq, TryFromPrimitive)]
|
||||
pub enum UmtsRrcSubtype {
|
||||
DlDcch = 0,
|
||||
UlDcch = 1,
|
||||
@@ -123,7 +124,7 @@ pub enum UmtsRrcSubtype {
|
||||
}
|
||||
|
||||
#[repr(u8)]
|
||||
#[derive(Debug, Copy, Clone, PartialEq)]
|
||||
#[derive(Debug, Copy, Clone, PartialEq, TryFromPrimitive)]
|
||||
pub enum LteRrcSubtype {
|
||||
DlCcch = 0,
|
||||
DlDcch = 1,
|
||||
@@ -150,7 +151,54 @@ pub enum LteRrcSubtype {
|
||||
ScMcchNb = 22,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum GsmtapTypeError {
|
||||
InvalidTypeSubtypeCombo(u8, u8),
|
||||
}
|
||||
|
||||
impl GsmtapType {
|
||||
pub fn new(gsmtap_type: u8, gsmtap_subtype: u8) -> Result<Self, GsmtapTypeError> {
|
||||
let maybe_result = match gsmtap_type {
|
||||
0x01 => match UmSubtype::try_from(gsmtap_subtype) {
|
||||
Ok(subtype) => Some(GsmtapType::Um(subtype)),
|
||||
_ => None,
|
||||
},
|
||||
0x02 => Some(GsmtapType::Abis),
|
||||
0x03 => Some(GsmtapType::UmBurst),
|
||||
0x04 => Some(GsmtapType::SIM),
|
||||
0x05 => Some(GsmtapType::TetraI1),
|
||||
0x06 => Some(GsmtapType::TetraI1Burst),
|
||||
0x07 => Some(GsmtapType::WmxBurst),
|
||||
0x08 => Some(GsmtapType::GbLlc),
|
||||
0x09 => Some(GsmtapType::GbSndcp),
|
||||
0x0a => Some(GsmtapType::Gmr1Um),
|
||||
0x0b => Some(GsmtapType::UmtsRlcMac),
|
||||
0x0c => match UmtsRrcSubtype::try_from(gsmtap_subtype) {
|
||||
Ok(subtype) => Some(GsmtapType::UmtsRrc(subtype)),
|
||||
_ => None,
|
||||
},
|
||||
0x0d => match LteRrcSubtype::try_from(gsmtap_subtype) {
|
||||
Ok(subtype) => Some(GsmtapType::LteRrc(subtype)),
|
||||
_ => None,
|
||||
},
|
||||
0x0e => Some(GsmtapType::LteMac),
|
||||
0x0f => Some(GsmtapType::LteMacFramed),
|
||||
0x10 => Some(GsmtapType::OsmocoreLog),
|
||||
0x11 => Some(GsmtapType::QcDiag),
|
||||
0x12 => match LteNasSubtype::try_from(gsmtap_subtype) {
|
||||
Ok(subtype) => Some(GsmtapType::LteNas(subtype)),
|
||||
_ => None,
|
||||
},
|
||||
0x13 => Some(GsmtapType::E1T1),
|
||||
0x14 => Some(GsmtapType::GsmRlp),
|
||||
_ => None,
|
||||
};
|
||||
match maybe_result {
|
||||
Some(result) => Ok(result),
|
||||
None => Err(GsmtapTypeError::InvalidTypeSubtypeCombo(gsmtap_type, gsmtap_subtype)),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_type(&self) -> u8 {
|
||||
match self {
|
||||
GsmtapType::Um(_) => 0x01,
|
||||
|
||||
Reference in New Issue
Block a user