Add packet analyzer history

This commit is contained in:
Jan Grashoefer 2024-08-12 11:59:30 +02:00
parent f943366e8e
commit 29bc84e1d6
5 changed files with 45 additions and 3 deletions

View file

@ -25,16 +25,23 @@ export {
## A certain number of bytes at the start of the unknown protocol's ## A certain number of bytes at the start of the unknown protocol's
## header. ## header.
first_bytes: string &log; first_bytes: string &log;
## The chain of packet analyzers that processed the packet up to this
## point. This includes the history of encapsulating packets in case
## of tunneling.
analyzer_history: vector of string &log;
}; };
} }
event unknown_protocol(analyzer_name: string, protocol: count, first_bytes: string) event unknown_protocol(analyzer_name: string, protocol: count, first_bytes: string,
analyzer_history: string_vec)
{ {
local info : Info; local info : Info;
info$ts = network_time(); info$ts = network_time();
info$analyzer = analyzer_name; info$analyzer = analyzer_name;
info$protocol_id = fmt("0x%x", protocol); info$protocol_id = fmt("0x%x", protocol);
info$first_bytes = bytestring_to_hexstr(first_bytes); info$first_bytes = bytestring_to_hexstr(first_bytes);
info$analyzer_history = analyzer_history;
Log::write(LOG, info); Log::write(LOG, info);
} }

View file

@ -885,8 +885,12 @@ event Pcap::file_done%(path: string%);
## ##
## first_bytes: A certain number of bytes at the start of the unknown protocol's header. ## first_bytes: A certain number of bytes at the start of the unknown protocol's header.
## ##
## analyzer_history: The chain of packet analyzers that processed the packet up to this
## point. This includes the history of encapsulating packets in case
## of tunneling.
##
## .. zeek:see:: UnknownProtocol::first_bytes_count ## .. zeek:see:: UnknownProtocol::first_bytes_count
event unknown_protocol%(analyzer_name: string, protocol: count, first_bytes: string%); event unknown_protocol%(analyzer_name: string, protocol: count, first_bytes: string, analyzer_history: string_vec%);
## An event for handling packets that reached the end of processing without ## An event for handling packets that reached the end of processing without
## being marked as processed. Note that this event may lead to unpredictable ## being marked as processed. Note that this event may lead to unpredictable

View file

@ -114,6 +114,7 @@ bool Analyzer::ForwardPacket(size_t len, const uint8_t* data, Packet* packet, ui
DBG_LOG(DBG_PACKET_ANALYSIS, "Analysis in %s succeeded, next layer identifier is %#x.", GetAnalyzerName(), DBG_LOG(DBG_PACKET_ANALYSIS, "Analysis in %s succeeded, next layer identifier is %#x.", GetAnalyzerName(),
identifier); identifier);
packet_mgr->TrackAnalyzer(inner_analyzer);
return inner_analyzer->AnalyzePacket(len, data, packet); return inner_analyzer->AnalyzePacket(len, data, packet);
} }
@ -129,6 +130,7 @@ bool Analyzer::ForwardPacket(size_t len, const uint8_t* data, Packet* packet) co
return false; return false;
} }
packet_mgr->TrackAnalyzer(inner_analyzer);
return inner_analyzer->AnalyzePacket(len, data, packet); return inner_analyzer->AnalyzePacket(len, data, packet);
} }

View file

@ -113,6 +113,7 @@ void Manager::ProcessPacket(Packet* packet) {
} }
// Start packet analysis // Start packet analysis
analyzer_stack.clear();
root_analyzer->ForwardPacket(packet->cap_len, packet->data, packet, packet->link_type); root_analyzer->ForwardPacket(packet->cap_len, packet->data, packet, packet->link_type);
if ( ! packet->processed ) { if ( ! packet->processed ) {
@ -227,13 +228,24 @@ bool Manager::PermitUnknownProtocol(const std::string& analyzer, uint32_t protoc
return false; return false;
} }
zeek::VectorValPtr Manager::BuildAnalyzerHistory() const {
auto history = zeek::make_intrusive<zeek::VectorVal>(zeek::id::string_vec);
for ( unsigned int i = 0; i < analyzer_stack.size(); i++ ) {
auto analyzer_name = analyzer_stack[i]->GetAnalyzerName();
history->Assign(i, make_intrusive<StringVal>(analyzer_name));
}
return history;
}
void Manager::ReportUnknownProtocol(const std::string& analyzer, uint32_t protocol, const uint8_t* data, size_t len) { void Manager::ReportUnknownProtocol(const std::string& analyzer, uint32_t protocol, const uint8_t* data, size_t len) {
if ( unknown_protocol ) { if ( unknown_protocol ) {
if ( PermitUnknownProtocol(analyzer, protocol) ) { if ( PermitUnknownProtocol(analyzer, protocol) ) {
int bytes_len = std::min(unknown_first_bytes_count, static_cast<uint64_t>(len)); int bytes_len = std::min(unknown_first_bytes_count, static_cast<uint64_t>(len));
event_mgr.Enqueue(unknown_protocol, make_intrusive<StringVal>(analyzer), val_mgr->Count(protocol), event_mgr.Enqueue(unknown_protocol, make_intrusive<StringVal>(analyzer), val_mgr->Count(protocol),
make_intrusive<StringVal>(bytes_len, (const char*)data)); make_intrusive<StringVal>(bytes_len, (const char*)data), BuildAnalyzerHistory());
} }
} }
} }

View file

@ -176,6 +176,13 @@ public:
*/ */
uint64_t GetUnprocessedCount() const { return total_not_processed; } uint64_t GetUnprocessedCount() const { return total_not_processed; }
/**
* Tracks the given analyzer for the current packet's analyzer history.
* The packet analyzer history is implemented in form of a stack, which is reset on a
* call to ProcessPacket() but maintained throughout calls to ProcessInnerPacket().
*/
void TrackAnalyzer(AnalyzerPtr analyzer) { analyzer_stack.push_back(std::move(analyzer)); }
private: private:
/** /**
* Instantiates a new analyzer instance. * Instantiates a new analyzer instance.
@ -197,6 +204,14 @@ private:
*/ */
AnalyzerPtr InstantiateAnalyzer(const std::string& name); AnalyzerPtr InstantiateAnalyzer(const std::string& name);
/**
* Generates a string vector that represents the analyzer history of the
* current packet based on the analyzers' tags.
*
* @return A vector of strings representing the packet analyzer history.
*/
VectorValPtr BuildAnalyzerHistory() const;
bool PermitUnknownProtocol(const std::string& analyzer, uint32_t protocol); bool PermitUnknownProtocol(const std::string& analyzer, uint32_t protocol);
std::map<std::string, AnalyzerPtr> analyzers; std::map<std::string, AnalyzerPtr> analyzers;
@ -216,6 +231,8 @@ private:
uint64_t total_not_processed = 0; uint64_t total_not_processed = 0;
iosource::PktDumper* unprocessed_dumper = nullptr; iosource::PktDumper* unprocessed_dumper = nullptr;
std::vector<AnalyzerPtr> analyzer_stack;
}; };
} // namespace packet_analysis } // namespace packet_analysis