lib: Use pycrate-rs NAS parser

This commit is contained in:
Will Greenberg
2025-06-24 12:15:04 -07:00
committed by Cooper Quintin
parent deeab1f1b0
commit 2e4de4a2df
4 changed files with 58 additions and 33 deletions

View File

@@ -1,5 +1,10 @@
use std::any::Any;
use std::borrow::Cow;
use pycrate_rs::nas::emm::EMMMessage;
use pycrate_rs::nas::generated::emm::emm_identity_request::{EMMIdentityRequest, IDTypeV};
use pycrate_rs::nas::NASMessage;
use super::analyzer::{Analyzer, Event, EventType, Severity};
use super::information_element::{InformationElement, LteInformationElement};
@@ -41,30 +46,32 @@ impl Analyzer for ImsiRequestedAnalyzer {
};
// NAS identity request, ID type IMSI
if payload == &[0x07, 0x55, 0x01] {
if self.packet_num < PACKET_THRESHHOLD {
return Some(Event {
event_type: EventType::QualitativeWarning {
severity: Severity::Medium,
},
message: format!(
"NAS IMSI 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 IMSI identity request detected (packet {})",
self.packet_num
),
});
if let NASMessage::EMMMessage(EMMMessage::EMMIdentityRequest(req)) = payload {
if req.id_type.inner == IDTypeV::IMSI {
if self.packet_num < PACKET_THRESHHOLD {
return Some(Event {
event_type: EventType::QualitativeWarning {
severity: Severity::Medium,
},
message: format!(
"NAS IMSI 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 IMSI identity request detected (packet {})",
self.packet_num
),
});
}
}
}
None

View File

@@ -5,17 +5,20 @@
use crate::gsmtap::{GsmtapMessage, GsmtapType, LteNasSubtype, LteRrcSubtype};
use telcom_parser::{decode, lte_rrc};
use pycrate_rs::nas::NASMessage;
use thiserror::Error;
#[derive(Error, Debug)]
pub enum InformationElementError {
#[error("Failed decoding")]
DecodingError(#[from] telcom_parser::ParsingError),
#[error("Failed decoding RRC message")]
RRCDecodingError(#[from] telcom_parser::ParsingError),
#[error("Failed decoding NAS message")]
NASDecodingError(#[from] pycrate_rs::nas::ParseError),
#[error("Unsupported LTE RRC subtype {0:?}")]
UnsupportedGsmtapType(GsmtapType),
}
#[derive(Debug, Clone, PartialEq)]
#[derive(Debug, Clone)]
pub enum InformationElement {
GSM,
UMTS,
@@ -25,7 +28,7 @@ pub enum InformationElement {
FiveG,
}
#[derive(Debug, Clone, PartialEq)]
#[derive(Debug, Clone)]
pub enum LteInformationElement {
DlCcch(lte_rrc::DL_CCCH_Message),
// This element of the enum is substantially larger than the others,
@@ -44,8 +47,7 @@ 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>),
NAS(NASMessage),
// FIXME: unclear which message these "NB" types map to
//DlCcchNb(),
//DlDcchNb(),
@@ -89,9 +91,10 @@ impl TryFrom<&GsmtapMessage> for InformationElement {
};
Ok(InformationElement::LTE(Box::new(lte)))
}
GsmtapType::LteNas(LteNasSubtype::Plain) => Ok(InformationElement::LTE(Box::new(
LteInformationElement::NAS(gsmtap_msg.payload.clone()),
))),
GsmtapType::LteNas(LteNasSubtype::Plain) => {
let msg = NASMessage::parse(&gsmtap_msg.payload)?;
Ok(InformationElement::LTE(Box::new(LteInformationElement::NAS(msg))))
}
_ => Err(InformationElementError::UnsupportedGsmtapType(
gsmtap_msg.header.gsmtap_type,
)),