mirror of
https://github.com/EFForg/rayhunter.git
synced 2026-04-26 15:39:59 -07:00
track packet num in analysis harness
This commit is contained in:
committed by
Cooper Quintin
parent
7475cd5cd9
commit
87d6d1691a
@@ -124,7 +124,11 @@ pub trait Analyzer {
|
||||
/// heuristic deems it relevant. Again, be mindful of any state your
|
||||
/// [Analyzer] updates per message, since it may be run over hundreds or
|
||||
/// thousands of them alongside many other [Analyzers](Analyzer).
|
||||
fn analyze_information_element(&mut self, ie: &InformationElement) -> Option<Event>;
|
||||
fn analyze_information_element(
|
||||
&mut self,
|
||||
ie: &InformationElement,
|
||||
packet_num: usize,
|
||||
) -> Option<Event>;
|
||||
|
||||
/// Returns a version number for this Analyzer. This should only ever
|
||||
/// increase in value, and do so whenever substantial changes are made to
|
||||
@@ -296,6 +300,7 @@ impl<'de> Deserialize<'de> for AnalysisRow {
|
||||
|
||||
pub struct Harness {
|
||||
analyzers: Vec<Box<dyn Analyzer + Send>>,
|
||||
packet_num: usize,
|
||||
}
|
||||
|
||||
impl Default for Harness {
|
||||
@@ -308,6 +313,7 @@ impl Harness {
|
||||
pub fn new() -> Self {
|
||||
Self {
|
||||
analyzers: Vec::new(),
|
||||
packet_num: 0,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -328,15 +334,15 @@ impl Harness {
|
||||
}
|
||||
|
||||
if analyzer_config.nas_null_cipher {
|
||||
harness.add_analyzer(Box::new(NasNullCipherAnalyzer::new()))
|
||||
harness.add_analyzer(Box::new(NasNullCipherAnalyzer {}))
|
||||
}
|
||||
|
||||
if analyzer_config.incomplete_sib {
|
||||
harness.add_analyzer(Box::new(IncompleteSibAnalyzer::new()))
|
||||
harness.add_analyzer(Box::new(IncompleteSibAnalyzer {}))
|
||||
}
|
||||
|
||||
if analyzer_config.test_analyzer {
|
||||
harness.add_analyzer(Box::new(TestAnalyzer::new()))
|
||||
harness.add_analyzer(Box::new(TestAnalyzer {}))
|
||||
}
|
||||
|
||||
harness
|
||||
@@ -425,9 +431,11 @@ impl Harness {
|
||||
}
|
||||
|
||||
pub fn analyze_information_element(&mut self, ie: &InformationElement) -> Vec<Option<Event>> {
|
||||
self.packet_num += 1;
|
||||
|
||||
self.analyzers
|
||||
.iter_mut()
|
||||
.map(|analyzer| analyzer.analyze_information_element(ie))
|
||||
.map(|analyzer| analyzer.analyze_information_element(ie, self.packet_num))
|
||||
.collect()
|
||||
}
|
||||
|
||||
|
||||
@@ -25,7 +25,11 @@ impl Analyzer for ConnectionRedirect2GDowngradeAnalyzer {
|
||||
1
|
||||
}
|
||||
|
||||
fn analyze_information_element(&mut self, ie: &InformationElement) -> Option<Event> {
|
||||
fn analyze_information_element(
|
||||
&mut self,
|
||||
ie: &InformationElement,
|
||||
packet_num: usize,
|
||||
) -> Option<Event> {
|
||||
if let InformationElement::LTE(lte_ie) = ie
|
||||
&& let LteInformationElement::DlDcch(msg_cont) = &**lte_ie
|
||||
&& let DL_DCCH_MessageType::C1(c1) = &msg_cont.message
|
||||
@@ -37,7 +41,7 @@ impl Analyzer for ConnectionRedirect2GDowngradeAnalyzer {
|
||||
match carrier_info {
|
||||
RedirectedCarrierInfo::Geran(_carrier_freqs_geran) => Some(Event {
|
||||
event_type: EventType::High,
|
||||
message: "Detected 2G downgrade".to_owned(),
|
||||
message: format!("Detected 2G downgrade (packet {})", packet_num),
|
||||
}),
|
||||
_ => Some(Event {
|
||||
event_type: EventType::Informational,
|
||||
|
||||
@@ -23,7 +23,6 @@ pub enum State {
|
||||
}
|
||||
|
||||
pub struct ImsiRequestedAnalyzer {
|
||||
packet_num: usize,
|
||||
state: State,
|
||||
timeout_counter: usize,
|
||||
flag: Option<Event>,
|
||||
@@ -38,20 +37,19 @@ impl Default for ImsiRequestedAnalyzer {
|
||||
impl ImsiRequestedAnalyzer {
|
||||
pub fn new() -> Self {
|
||||
Self {
|
||||
packet_num: 0,
|
||||
state: State::Unattached,
|
||||
timeout_counter: 0,
|
||||
flag: None,
|
||||
}
|
||||
}
|
||||
|
||||
fn transition(&mut self, next_state: State) {
|
||||
fn transition(&mut self, next_state: State, packet_num: usize) {
|
||||
match (&self.state, &next_state) {
|
||||
// Reset timeout on successful auth
|
||||
(_, State::AuthAccept) => {
|
||||
debug!(
|
||||
"reset timeout counter at {} due to auth accept (frame {})",
|
||||
self.timeout_counter, self.packet_num
|
||||
self.timeout_counter, packet_num
|
||||
);
|
||||
self.timeout_counter = 0;
|
||||
}
|
||||
@@ -62,7 +60,7 @@ impl ImsiRequestedAnalyzer {
|
||||
event_type: EventType::High,
|
||||
message: format!(
|
||||
"Identity requested after auth request (frame {})",
|
||||
self.packet_num
|
||||
packet_num
|
||||
),
|
||||
});
|
||||
}
|
||||
@@ -73,7 +71,7 @@ impl ImsiRequestedAnalyzer {
|
||||
event_type: EventType::High,
|
||||
message: format!(
|
||||
"Identity requested without Attach Request (frame {})",
|
||||
self.packet_num
|
||||
packet_num
|
||||
),
|
||||
});
|
||||
}
|
||||
@@ -84,7 +82,7 @@ impl ImsiRequestedAnalyzer {
|
||||
event_type: EventType::High,
|
||||
message: format!(
|
||||
"Disconnected after Identity Request without Auth Accept (frame {})",
|
||||
self.packet_num
|
||||
packet_num
|
||||
),
|
||||
});
|
||||
}
|
||||
@@ -95,7 +93,7 @@ impl ImsiRequestedAnalyzer {
|
||||
event_type: EventType::Informational,
|
||||
message: format!(
|
||||
"Identity Request happened but its not suspicious yet. (frame {})",
|
||||
self.packet_num
|
||||
packet_num
|
||||
)
|
||||
.to_string(),
|
||||
});
|
||||
@@ -106,7 +104,7 @@ impl ImsiRequestedAnalyzer {
|
||||
_ => {
|
||||
debug!(
|
||||
"Transition from {:?} to {:?} at {}",
|
||||
self.state, next_state, self.packet_num
|
||||
self.state, next_state, packet_num
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -129,29 +127,31 @@ impl Analyzer for ImsiRequestedAnalyzer {
|
||||
3
|
||||
}
|
||||
|
||||
fn analyze_information_element(&mut self, ie: &InformationElement) -> Option<Event> {
|
||||
self.packet_num += 1;
|
||||
|
||||
fn analyze_information_element(
|
||||
&mut self,
|
||||
ie: &InformationElement,
|
||||
packet_num: usize,
|
||||
) -> Option<Event> {
|
||||
if let InformationElement::LTE(inner) = ie {
|
||||
match &**inner {
|
||||
LteInformationElement::NAS(payload) => match payload {
|
||||
NASMessage::EMMMessage(EMMMessage::EMMExtServiceRequest(_))
|
||||
| NASMessage::EMMMessage(EMMMessage::EMMAttachRequest(_)) => {
|
||||
self.transition(State::AttachRequest);
|
||||
self.transition(State::AttachRequest, packet_num);
|
||||
}
|
||||
NASMessage::EMMMessage(EMMMessage::EMMIdentityRequest(_)) => {
|
||||
self.transition(State::IdentityRequest);
|
||||
self.transition(State::IdentityRequest, packet_num);
|
||||
}
|
||||
NASMessage::EMMMessage(EMMMessage::EMMAttachComplete(_))
|
||||
| NASMessage::EMMMessage(EMMMessage::EMMAuthenticationResponse(_)) => {
|
||||
self.transition(State::AuthAccept);
|
||||
self.transition(State::AuthAccept, packet_num);
|
||||
}
|
||||
NASMessage::EMMMessage(EMMMessage::EMMServiceReject(_))
|
||||
| NASMessage::EMMMessage(EMMMessage::EMMAttachReject(_))
|
||||
| NASMessage::EMMMessage(EMMMessage::EMMDetachRequestMO(_))
|
||||
| NASMessage::EMMMessage(EMMMessage::EMMDetachRequestMT(_))
|
||||
| NASMessage::EMMMessage(EMMMessage::EMMTrackingAreaUpdateReject(_)) => {
|
||||
self.transition(State::Disconnect);
|
||||
self.transition(State::Disconnect, packet_num);
|
||||
}
|
||||
_ => {}
|
||||
},
|
||||
@@ -161,7 +161,7 @@ impl Analyzer for ImsiRequestedAnalyzer {
|
||||
| UL_CCCH_MessageType::C1(
|
||||
UL_CCCH_MessageType_c1::RrcConnectionReestablishmentRequest(_),
|
||||
) => {
|
||||
self.transition(State::AttachRequest);
|
||||
self.transition(State::AttachRequest, packet_num);
|
||||
}
|
||||
_ => {}
|
||||
},
|
||||
@@ -171,7 +171,7 @@ impl Analyzer for ImsiRequestedAnalyzer {
|
||||
_,
|
||||
)) = rrc_payload.message
|
||||
{
|
||||
self.transition(State::Disconnect)
|
||||
self.transition(State::Disconnect, packet_num)
|
||||
}
|
||||
}
|
||||
_ => {}
|
||||
@@ -182,14 +182,14 @@ impl Analyzer for ImsiRequestedAnalyzer {
|
||||
self.timeout_counter += 1;
|
||||
debug!(
|
||||
"timeout: counter {}, packet: {}",
|
||||
self.timeout_counter, self.packet_num
|
||||
self.timeout_counter, packet_num
|
||||
);
|
||||
if self.timeout_counter >= TIMEOUT_THRESHHOLD {
|
||||
self.flag = Some(Event {
|
||||
event_type: EventType::Informational {},
|
||||
message: format!(
|
||||
"Identity request happened without auth request followup (frame {})",
|
||||
self.packet_num
|
||||
packet_num
|
||||
)
|
||||
.to_string(),
|
||||
});
|
||||
|
||||
@@ -5,21 +5,7 @@ use telcom_parser::lte_rrc::{BCCH_DL_SCH_MessageType, BCCH_DL_SCH_MessageType_c1
|
||||
use super::analyzer::{Analyzer, Event, EventType};
|
||||
use super::information_element::{InformationElement, LteInformationElement};
|
||||
|
||||
pub struct IncompleteSibAnalyzer {
|
||||
packet_num: usize,
|
||||
}
|
||||
|
||||
impl Default for IncompleteSibAnalyzer {
|
||||
fn default() -> Self {
|
||||
Self::new()
|
||||
}
|
||||
}
|
||||
|
||||
impl IncompleteSibAnalyzer {
|
||||
pub fn new() -> Self {
|
||||
Self { packet_num: 0 }
|
||||
}
|
||||
}
|
||||
pub struct IncompleteSibAnalyzer {}
|
||||
|
||||
impl Analyzer for IncompleteSibAnalyzer {
|
||||
fn get_name(&self) -> Cow<'_, str> {
|
||||
@@ -34,9 +20,11 @@ impl Analyzer for IncompleteSibAnalyzer {
|
||||
1
|
||||
}
|
||||
|
||||
fn analyze_information_element(&mut self, ie: &InformationElement) -> Option<Event> {
|
||||
self.packet_num += 1;
|
||||
|
||||
fn analyze_information_element(
|
||||
&mut self,
|
||||
ie: &InformationElement,
|
||||
packet_num: usize,
|
||||
) -> Option<Event> {
|
||||
if let InformationElement::LTE(lte_ie) = ie
|
||||
&& let LteInformationElement::BcchDlSch(sch_msg) = &**lte_ie
|
||||
&& let BCCH_DL_SCH_MessageType::C1(c1) = &sch_msg.message
|
||||
@@ -47,7 +35,7 @@ impl Analyzer for IncompleteSibAnalyzer {
|
||||
event_type: EventType::Medium,
|
||||
message: format!(
|
||||
"SIB1 scheduling info list was malformed (packet {})",
|
||||
self.packet_num
|
||||
packet_num
|
||||
),
|
||||
});
|
||||
}
|
||||
|
||||
@@ -7,21 +7,7 @@ use pycrate_rs::nas::generated::emm::emm_security_mode_command::NASSecAlgoCiphAl
|
||||
use super::analyzer::{Analyzer, Event, EventType};
|
||||
use super::information_element::{InformationElement, LteInformationElement};
|
||||
|
||||
pub struct NasNullCipherAnalyzer {
|
||||
packet_num: usize,
|
||||
}
|
||||
|
||||
impl Default for NasNullCipherAnalyzer {
|
||||
fn default() -> Self {
|
||||
Self::new()
|
||||
}
|
||||
}
|
||||
|
||||
impl NasNullCipherAnalyzer {
|
||||
pub fn new() -> Self {
|
||||
Self { packet_num: 0 }
|
||||
}
|
||||
}
|
||||
pub struct NasNullCipherAnalyzer {}
|
||||
|
||||
impl Analyzer for NasNullCipherAnalyzer {
|
||||
fn get_name(&self) -> Cow<'_, str> {
|
||||
@@ -38,8 +24,11 @@ impl Analyzer for NasNullCipherAnalyzer {
|
||||
1
|
||||
}
|
||||
|
||||
fn analyze_information_element(&mut self, ie: &InformationElement) -> Option<Event> {
|
||||
self.packet_num += 1;
|
||||
fn analyze_information_element(
|
||||
&mut self,
|
||||
ie: &InformationElement,
|
||||
packet_num: usize,
|
||||
) -> Option<Event> {
|
||||
let payload = match ie {
|
||||
InformationElement::LTE(inner) => match &**inner {
|
||||
LteInformationElement::NAS(payload) => payload,
|
||||
@@ -55,7 +44,7 @@ impl Analyzer for NasNullCipherAnalyzer {
|
||||
event_type: EventType::High,
|
||||
message: format!(
|
||||
"NAS Security mode command requested null cipher(packet {})",
|
||||
self.packet_num
|
||||
packet_num
|
||||
),
|
||||
});
|
||||
}
|
||||
|
||||
@@ -131,7 +131,11 @@ impl Analyzer for NullCipherAnalyzer {
|
||||
1
|
||||
}
|
||||
|
||||
fn analyze_information_element(&mut self, ie: &InformationElement) -> Option<Event> {
|
||||
fn analyze_information_element(
|
||||
&mut self,
|
||||
ie: &InformationElement,
|
||||
packet_num: usize,
|
||||
) -> Option<Event> {
|
||||
let dcch_msg = match ie {
|
||||
InformationElement::LTE(lte_ie) => match &**lte_ie {
|
||||
LteInformationElement::DlDcch(dcch_msg) => dcch_msg,
|
||||
@@ -154,7 +158,7 @@ impl Analyzer for NullCipherAnalyzer {
|
||||
if null_cipher_detected {
|
||||
return Some(Event {
|
||||
event_type: EventType::High,
|
||||
message: "Cell suggested use of null cipher".to_string(),
|
||||
message: format!("Cell suggested use of null cipher (packet {})", packet_num),
|
||||
});
|
||||
}
|
||||
None
|
||||
|
||||
@@ -49,6 +49,7 @@ impl Analyzer for LteSib6And7DowngradeAnalyzer {
|
||||
fn analyze_information_element(
|
||||
&mut self,
|
||||
ie: &InformationElement,
|
||||
packet_num: usize,
|
||||
) -> Option<super::analyzer::Event> {
|
||||
let sibs = &self.unpack_system_information(ie)?.0;
|
||||
for sib in sibs {
|
||||
@@ -62,9 +63,10 @@ impl Analyzer for LteSib6And7DowngradeAnalyzer {
|
||||
{
|
||||
return Some(Event {
|
||||
event_type: EventType::High,
|
||||
message:
|
||||
"LTE cell advertised a 3G cell for priority 0 reselection"
|
||||
.to_string(),
|
||||
message: format!(
|
||||
"LTE cell advertised a 3G cell for priority 0 reselection (packet {})",
|
||||
packet_num
|
||||
),
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -77,9 +79,10 @@ impl Analyzer for LteSib6And7DowngradeAnalyzer {
|
||||
{
|
||||
return Some(Event {
|
||||
event_type: EventType::High,
|
||||
message:
|
||||
"LTE cell advertised a 3G cell for priority 0 reselection"
|
||||
.to_string(),
|
||||
message: format!(
|
||||
"LTE cell advertised a 3G cell for priority 0 reselection (packet {})",
|
||||
packet_num
|
||||
),
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,21 +6,7 @@ use super::analyzer::{Analyzer, Event, EventType};
|
||||
use super::information_element::{InformationElement, LteInformationElement};
|
||||
use deku::bitvec::*;
|
||||
|
||||
pub struct TestAnalyzer {
|
||||
packet_num: usize,
|
||||
}
|
||||
|
||||
impl Default for TestAnalyzer {
|
||||
fn default() -> Self {
|
||||
Self::new()
|
||||
}
|
||||
}
|
||||
|
||||
impl TestAnalyzer {
|
||||
pub fn new() -> Self {
|
||||
Self { packet_num: 0 }
|
||||
}
|
||||
}
|
||||
pub struct TestAnalyzer {}
|
||||
|
||||
impl Analyzer for TestAnalyzer {
|
||||
fn get_name(&self) -> Cow<'_, str> {
|
||||
@@ -37,9 +23,11 @@ impl Analyzer for TestAnalyzer {
|
||||
1
|
||||
}
|
||||
|
||||
fn analyze_information_element(&mut self, ie: &InformationElement) -> Option<Event> {
|
||||
self.packet_num += 1;
|
||||
|
||||
fn analyze_information_element(
|
||||
&mut self,
|
||||
ie: &InformationElement,
|
||||
packet_num: usize,
|
||||
) -> Option<Event> {
|
||||
if let InformationElement::LTE(lte_ie) = ie
|
||||
&& let LteInformationElement::BcchDlSch(sch_msg) = &**lte_ie
|
||||
&& let BCCH_DL_SCH_MessageType::C1(c1) = &sch_msg.message
|
||||
@@ -66,7 +54,7 @@ impl Analyzer for TestAnalyzer {
|
||||
event_type: EventType::Low,
|
||||
message: format!(
|
||||
"SIB1 received (packet {}) CID: {}, PLMN: {}-{}",
|
||||
self.packet_num, cid, mcc_string, mnc_string
|
||||
packet_num, cid, mcc_string, mnc_string
|
||||
),
|
||||
});
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user