lib: add IMSI requested heuristic

This commit is contained in:
Will Greenberg
2025-01-08 14:32:56 -08:00
committed by Cooper Quintin
parent 10592bbd9d
commit fa612241a5
4 changed files with 75 additions and 4 deletions

View File

@@ -4,7 +4,12 @@ use serde::Serialize;
use crate::{diag::MessagesContainer, gsmtap_parser};
use super::{/*imsi_provided::ImsiProvidedAnalyzer,*/ information_element::InformationElement, lte_downgrade::LteSib6And7DowngradeAnalyzer, null_cipher::NullCipherAnalyzer};
use super::{
imsi_requested::ImsiRequestedAnalyzer,
information_element::InformationElement,
lte_downgrade::LteSib6And7DowngradeAnalyzer,
null_cipher::NullCipherAnalyzer,
};
/// Qualitative measure of how severe a Warning event type is.
/// The levels should break down like this:
@@ -18,7 +23,7 @@ pub enum Severity {
High,
}
/// [QualitativeWarning] events will always be shown to the user in some manner,
/// `QualitativeWarning` events will always be shown to the user in some manner,
/// while `Informational` ones may be hidden based on user settings.
#[derive(Serialize, Debug, Clone)]
#[serde(tag = "type")]
@@ -113,7 +118,7 @@ impl Harness {
pub fn new_with_all_analyzers() -> Self {
let mut harness = Harness::new();
harness.add_analyzer(Box::new(LteSib6And7DowngradeAnalyzer{}));
//harness.add_analyzer(Box::new(ImsiProvidedAnalyzer{}));
harness.add_analyzer(Box::new(ImsiRequestedAnalyzer::new()));
harness.add_analyzer(Box::new(NullCipherAnalyzer{}));
harness

View File

@@ -0,0 +1,59 @@
use std::borrow::Cow;
use super::analyzer::{Analyzer, Event, EventType, Severity};
use super::information_element::{InformationElement, LteInformationElement};
const PACKET_THRESHHOLD: usize = 150;
pub struct ImsiRequestedAnalyzer {
packet_num: usize,
}
impl ImsiRequestedAnalyzer {
pub fn new() -> Self {
Self { packet_num: 0 }
}
}
impl Analyzer for ImsiRequestedAnalyzer {
fn get_name(&self) -> Cow<str> {
Cow::from("IMSI Requested")
}
fn get_description(&self) -> Cow<str> {
Cow::from("Tests whether the ME sends an IMSI Identity Request NAS message")
}
fn analyze_information_element(&mut self, ie: &InformationElement) -> Option<Event> {
self.packet_num += 1;
let InformationElement::LTE(LteInformationElement::NAS(payload)) = ie else {
return None;
};
// NAS identity request
if payload == &[0x07, 0x55, 0x01] {
if self.packet_num < PACKET_THRESHHOLD {
return Some(Event {
event_type: EventType::QualitativeWarning {
severity: Severity::Low
},
message: format!(
"NAS identity request detected, however it was within \
the first {} packets of this analysis. If you just \
turned your device on, this is likely a \
false-positive.",
PACKET_THRESHHOLD
)
})
} else {
return Some(Event {
event_type: EventType::QualitativeWarning {
severity: Severity::High
},
message: format!("NAS identity request detected"),
})
}
}
None
}
}

View File

@@ -5,7 +5,7 @@
use telcom_parser::{decode, lte_rrc};
use thiserror::Error;
use crate::gsmtap::{GsmtapType, LteRrcSubtype, GsmtapMessage};
use crate::gsmtap::{GsmtapMessage, GsmtapType, LteNasSubtype, LteRrcSubtype};
#[derive(Error, Debug)]
pub enum InformationElementError {
@@ -40,6 +40,9 @@ pub enum LteInformationElement {
SbcchSlBch(lte_rrc::SBCCH_SL_BCH_Message),
SbcchSlBchV2x(lte_rrc::SBCCH_SL_BCH_Message_V2X_r14),
// FIXME: actually parse NAS messages
NAS(Vec<u8>),
// FIXME: unclear which message these "NB" types map to
//DlCcchNb(),
//DlDcchNb(),
@@ -79,6 +82,9 @@ impl TryFrom<&GsmtapMessage> for InformationElement {
};
Ok(InformationElement::LTE(lte))
},
GsmtapType::LteNas(LteNasSubtype::Plain) => {
Ok(InformationElement::LTE(LteInformationElement::NAS(gsmtap_msg.payload.clone())))
},
_ => Err(InformationElementError::UnsupportedGsmtapType(gsmtap_msg.header.gsmtap_type)),
}
}

View File

@@ -2,4 +2,5 @@ pub mod analyzer;
pub mod information_element;
pub mod lte_downgrade;
pub mod imsi_provided;
pub mod imsi_requested;
pub mod null_cipher;