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
## header.
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;
info$ts = network_time();
info$analyzer = analyzer_name;
info$protocol_id = fmt("0x%x", protocol);
info$first_bytes = bytestring_to_hexstr(first_bytes);
info$analyzer_history = analyzer_history;
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.
##
## 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
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
## 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(),
identifier);
packet_mgr->TrackAnalyzer(inner_analyzer);
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;
}
packet_mgr->TrackAnalyzer(inner_analyzer);
return inner_analyzer->AnalyzePacket(len, data, packet);
}

View file

@ -113,6 +113,7 @@ void Manager::ProcessPacket(Packet* packet) {
}
// Start packet analysis
analyzer_stack.clear();
root_analyzer->ForwardPacket(packet->cap_len, packet->data, packet, packet->link_type);
if ( ! packet->processed ) {
@ -227,13 +228,24 @@ bool Manager::PermitUnknownProtocol(const std::string& analyzer, uint32_t protoc
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) {
if ( unknown_protocol ) {
if ( PermitUnknownProtocol(analyzer, protocol) ) {
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),
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; }
/**
* 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:
/**
* Instantiates a new analyzer instance.
@ -197,6 +204,14 @@ private:
*/
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);
std::map<std::string, AnalyzerPtr> analyzers;
@ -216,6 +231,8 @@ private:
uint64_t total_not_processed = 0;
iosource::PktDumper* unprocessed_dumper = nullptr;
std::vector<AnalyzerPtr> analyzer_stack;
};
} // namespace packet_analysis