From b7877792c98c22f072f26ed5ef4870e598fcf672 Mon Sep 17 00:00:00 2001 From: Seth Hall Date: Mon, 5 Aug 2013 00:02:48 -0400 Subject: [PATCH 01/13] First commit of file entropy analyzer. - Code comments need cleaned up still. --- scripts/policy/frameworks/files/entropy.bro | 19 +++++ src/file_analysis/analyzer/CMakeLists.txt | 1 + .../analyzer/entropy/CMakeLists.txt | 9 ++ src/file_analysis/analyzer/entropy/Entropy.cc | 71 ++++++++++++++++ src/file_analysis/analyzer/entropy/Entropy.h | 84 +++++++++++++++++++ src/file_analysis/analyzer/entropy/Plugin.cc | 29 +++++++ src/file_analysis/analyzer/entropy/events.bif | 8 ++ 7 files changed, 221 insertions(+) create mode 100644 scripts/policy/frameworks/files/entropy.bro create mode 100644 src/file_analysis/analyzer/entropy/CMakeLists.txt create mode 100644 src/file_analysis/analyzer/entropy/Entropy.cc create mode 100644 src/file_analysis/analyzer/entropy/Entropy.h create mode 100644 src/file_analysis/analyzer/entropy/Plugin.cc create mode 100644 src/file_analysis/analyzer/entropy/events.bif diff --git a/scripts/policy/frameworks/files/entropy.bro b/scripts/policy/frameworks/files/entropy.bro new file mode 100644 index 0000000000..89dcead7d6 --- /dev/null +++ b/scripts/policy/frameworks/files/entropy.bro @@ -0,0 +1,19 @@ + +module Files; + +export { + redef record Files::Info += { + ## The information density of the contents of the file, expressed as a number of bits per character. + entropy: double &log &optional; + }; +} + +event file_new(f: fa_file) + { + Files::add_analyzer(f, Files::ANALYZER_ENTROPY); + } + +event file_entropy(f: fa_file, ent: entropy_test_result) + { + f$info$entropy = ent$entropy; + } \ No newline at end of file diff --git a/src/file_analysis/analyzer/CMakeLists.txt b/src/file_analysis/analyzer/CMakeLists.txt index bfafcd2894..ca93c4512c 100644 --- a/src/file_analysis/analyzer/CMakeLists.txt +++ b/src/file_analysis/analyzer/CMakeLists.txt @@ -1,3 +1,4 @@ add_subdirectory(data_event) +add_subdirectory(entropy) add_subdirectory(extract) add_subdirectory(hash) diff --git a/src/file_analysis/analyzer/entropy/CMakeLists.txt b/src/file_analysis/analyzer/entropy/CMakeLists.txt new file mode 100644 index 0000000000..38db5e726a --- /dev/null +++ b/src/file_analysis/analyzer/entropy/CMakeLists.txt @@ -0,0 +1,9 @@ +include(BroPlugin) + +include_directories(BEFORE ${CMAKE_CURRENT_SOURCE_DIR} + ${CMAKE_CURRENT_BINARY_DIR}) + +bro_plugin_begin(Bro FileEntropy) +bro_plugin_cc(Entropy.cc Plugin.cc ../../Analyzer.cc) +bro_plugin_bif(events.bif) +bro_plugin_end() diff --git a/src/file_analysis/analyzer/entropy/Entropy.cc b/src/file_analysis/analyzer/entropy/Entropy.cc new file mode 100644 index 0000000000..2a1bc72723 --- /dev/null +++ b/src/file_analysis/analyzer/entropy/Entropy.cc @@ -0,0 +1,71 @@ +// See the file "COPYING" in the main distribution directory for copyright. + +#include + +#include "Entropy.h" +#include "util.h" +#include "Event.h" +#include "file_analysis/Manager.h" + +using namespace file_analysis; + +Entropy::Entropy(RecordVal* args, File* file) + : file_analysis::Analyzer(file_mgr->GetComponentTag("ENTROPY"), args, file) + { + //entropy->Init(); + entropy = new EntropyVal; + } + +Entropy::~Entropy() + { + Unref(entropy); + } + +file_analysis::Analyzer* Entropy::Instantiate(RecordVal* args, File* file) + { + return new Entropy(args, file); + } + +bool Entropy::DeliverStream(const u_char* data, uint64 len) + { + if ( ! fed ) + fed = len > 0; + + entropy->Feed(data, len); + return true; + } + +bool Entropy::EndOfFile() + { + Finalize(); + return false; + } + +bool Entropy::Undelivered(uint64 offset, uint64 len) + { + return false; + } + +void Entropy::Finalize() + { + //if ( ! entropy->IsValid() || ! fed ) + if ( ! fed ) + return; + + val_list* vl = new val_list(); + vl->append(GetFile()->GetVal()->Ref()); + + double montepi, scc, ent, mean, chisq; + montepi = scc = ent = mean = chisq = 0.0; + entropy->Get(&ent, &chisq, &mean, &montepi, &scc); + + RecordVal* ent_result = new RecordVal(entropy_test_result); + ent_result->Assign(0, new Val(ent, TYPE_DOUBLE)); + ent_result->Assign(1, new Val(chisq, TYPE_DOUBLE)); + ent_result->Assign(2, new Val(mean, TYPE_DOUBLE)); + ent_result->Assign(3, new Val(montepi, TYPE_DOUBLE)); + ent_result->Assign(4, new Val(scc, TYPE_DOUBLE)); + + vl->append(ent_result); + mgr.QueueEvent(file_entropy, vl); + } diff --git a/src/file_analysis/analyzer/entropy/Entropy.h b/src/file_analysis/analyzer/entropy/Entropy.h new file mode 100644 index 0000000000..6a5075263c --- /dev/null +++ b/src/file_analysis/analyzer/entropy/Entropy.h @@ -0,0 +1,84 @@ +// See the file "COPYING" in the main distribution directory for copyright. + +#ifndef FILE_ANALYSIS_ENTROPY_H +#define FILE_ANALYSIS_ENTROPY_H + +#include + +#include "Val.h" +#include "OpaqueVal.h" +#include "File.h" +#include "Analyzer.h" + +#include "events.bif.h" + +namespace file_analysis { + +/** + * An analyzer to produce a hash of file contents. + */ +class Entropy : public file_analysis::Analyzer { +public: + + /** + * Destructor. + */ + virtual ~Entropy(); + + /** + * Create a new instance of an Extract analyzer. + * @param args the \c AnalyzerArgs value which represents the analyzer. + * @param file the file to which the analyzer will be attached. + * @return the new Extract analyzer instance or a null pointer if the + * the "extraction_file" field of \a args wasn't set. + */ + static file_analysis::Analyzer* Instantiate(RecordVal* args, File* file); + + /** + * Incrementally hash next chunk of file contents. + * @param data pointer to start of a chunk of a file data. + * @param len number of bytes in the data chunk. + * @return false if the digest is in an invalid state, else true. + */ + virtual bool DeliverStream(const u_char* data, uint64 len); + + /** + * Finalizes the hash and raises a "file_entropy_test" event. + * @return always false so analyze will be deteched from file. + */ + virtual bool EndOfFile(); + + /** + * Missing data can't be handled, so just indicate the this analyzer should + * be removed from receiving further data. The hash will not be finalized. + * @param offset byte offset in file at which missing chunk starts. + * @param len number of missing bytes. + * @return always false so analyzer will detach from file. + */ + virtual bool Undelivered(uint64 offset, uint64 len); + +protected: + + /** + * Constructor. + * @param args the \c AnalyzerArgs value which represents the analyzer. + * @param file the file to which the analyzer will be attached. + * @param hv specific hash calculator object. + * @param kind human readable name of the hash algorithm to use. + */ + Entropy(RecordVal* args, File* file); + + /** + * If some file contents have been seen, finalizes the hash of them and + * raises the "file_hash" event with the results. + */ + void Finalize(); + +private: + EntropyVal* entropy; + bool fed; +}; + +} // namespace file_analysis + +#endif diff --git a/src/file_analysis/analyzer/entropy/Plugin.cc b/src/file_analysis/analyzer/entropy/Plugin.cc new file mode 100644 index 0000000000..3eeae62480 --- /dev/null +++ b/src/file_analysis/analyzer/entropy/Plugin.cc @@ -0,0 +1,29 @@ +#include "plugin/Plugin.h" +#include "file_analysis/Component.h" + +#include "Entropy.h" + +namespace plugin { namespace Bro_FileEntropy { + +class Plugin : public plugin::Plugin { +protected: + void InitPreScript() + { + SetName("Bro::FileEntropy"); + SetVersion(-1); + SetAPIVersion(BRO_PLUGIN_API_VERSION); + SetDynamicPlugin(false); + + SetDescription("Entropy test file content"); + + AddComponent(new ::file_analysis::Component("ENTROPY", + ::file_analysis::Entropy::Instantiate)); + + extern std::list > __bif_events_init(); + AddBifInitFunction(&__bif_events_init); + } +}; + +Plugin __plugin; + +} } diff --git a/src/file_analysis/analyzer/entropy/events.bif b/src/file_analysis/analyzer/entropy/events.bif new file mode 100644 index 0000000000..a51bb3d39b --- /dev/null +++ b/src/file_analysis/analyzer/entropy/events.bif @@ -0,0 +1,8 @@ +## This event is generated each time file analysis performs +## entropy testing on a file. +## +## f: The file. +## +## ent: The results of the entropy testing. +## +event file_entropy%(f: fa_file, ent: entropy_test_result%); \ No newline at end of file From 9c692bad39c7d207b7682a87773806b9916fc9d8 Mon Sep 17 00:00:00 2001 From: Seth Hall Date: Tue, 3 Feb 2015 15:04:36 -0500 Subject: [PATCH 02/13] Update and clean up to file entropy measurement. - Updated to newer file analyzer api. --- ...entropy.bro => entropy-test-all-files.bro} | 3 +- src/file_analysis/analyzer/entropy/Plugin.cc | 33 ++++++++----------- 2 files changed, 16 insertions(+), 20 deletions(-) rename scripts/policy/frameworks/files/{entropy.bro => entropy-test-all-files.bro} (71%) diff --git a/scripts/policy/frameworks/files/entropy.bro b/scripts/policy/frameworks/files/entropy-test-all-files.bro similarity index 71% rename from scripts/policy/frameworks/files/entropy.bro rename to scripts/policy/frameworks/files/entropy-test-all-files.bro index 89dcead7d6..fd02b9ecaa 100644 --- a/scripts/policy/frameworks/files/entropy.bro +++ b/scripts/policy/frameworks/files/entropy-test-all-files.bro @@ -3,7 +3,8 @@ module Files; export { redef record Files::Info += { - ## The information density of the contents of the file, expressed as a number of bits per character. + ## The information density of the contents of the file, + ## expressed as a number of bits per character. entropy: double &log &optional; }; } diff --git a/src/file_analysis/analyzer/entropy/Plugin.cc b/src/file_analysis/analyzer/entropy/Plugin.cc index 3eeae62480..f1dd954cba 100644 --- a/src/file_analysis/analyzer/entropy/Plugin.cc +++ b/src/file_analysis/analyzer/entropy/Plugin.cc @@ -1,29 +1,24 @@ +// See the file in the main distribution directory for copyright. + #include "plugin/Plugin.h" -#include "file_analysis/Component.h" #include "Entropy.h" -namespace plugin { namespace Bro_FileEntropy { +namespace plugin { +namespace Bro_FileEntropy { class Plugin : public plugin::Plugin { -protected: - void InitPreScript() +public: + plugin::Configuration Configure() { - SetName("Bro::FileEntropy"); - SetVersion(-1); - SetAPIVersion(BRO_PLUGIN_API_VERSION); - SetDynamicPlugin(false); + AddComponent(new ::file_analysis::Component("ENTROPY", ::file_analysis::Entropy::Instantiate)); - SetDescription("Entropy test file content"); - - AddComponent(new ::file_analysis::Component("ENTROPY", - ::file_analysis::Entropy::Instantiate)); - - extern std::list > __bif_events_init(); - AddBifInitFunction(&__bif_events_init); + plugin::Configuration config; + config.name = "Bro::FileEntropy"; + config.description = "Entropy test file content"; + return config; } -}; +} plugin; -Plugin __plugin; - -} } +} +} From 39ebf8df791076f0c3b7e2f9ed83a833f11fe96d Mon Sep 17 00:00:00 2001 From: Seth Hall Date: Thu, 26 Feb 2015 09:17:55 -0500 Subject: [PATCH 03/13] Updated tests for file entropy analyzer. --- scripts/test-all-policy.bro | 1 + .../canonified_loaded_scripts.log | 5 +++-- testing/btest/Baseline/plugins.hooks/output | 20 ++++++++++--------- 3 files changed, 15 insertions(+), 11 deletions(-) diff --git a/scripts/test-all-policy.bro b/scripts/test-all-policy.bro index 0fb74f91cf..79641be788 100644 --- a/scripts/test-all-policy.bro +++ b/scripts/test-all-policy.bro @@ -28,6 +28,7 @@ @load frameworks/intel/seen/where-locations.bro @load frameworks/intel/seen/x509.bro @load frameworks/files/detect-MHR.bro +@load frameworks/files/entropy-test-all-files.bro @load frameworks/files/hash-all-files.bro @load frameworks/packet-filter/shunt.bro @load frameworks/software/version-changes.bro diff --git a/testing/btest/Baseline/coverage.default-load-baseline/canonified_loaded_scripts.log b/testing/btest/Baseline/coverage.default-load-baseline/canonified_loaded_scripts.log index 67de0fc1dc..c3031cbb2d 100644 --- a/testing/btest/Baseline/coverage.default-load-baseline/canonified_loaded_scripts.log +++ b/testing/btest/Baseline/coverage.default-load-baseline/canonified_loaded_scripts.log @@ -3,7 +3,7 @@ #empty_field (empty) #unset_field - #path loaded_scripts -#open 2014-10-31-20-38-48 +#open 2015-02-26-14-14-34 #fields name #types string scripts/base/init-bare.bro @@ -97,6 +97,7 @@ scripts/base/init-bare.bro build/scripts/base/bif/plugins/Bro_Teredo.events.bif.bro build/scripts/base/bif/plugins/Bro_UDP.events.bif.bro build/scripts/base/bif/plugins/Bro_ZIP.events.bif.bro + build/scripts/base/bif/plugins/Bro_FileEntropy.events.bif.bro build/scripts/base/bif/plugins/Bro_FileExtract.events.bif.bro build/scripts/base/bif/plugins/Bro_FileExtract.functions.bif.bro build/scripts/base/bif/plugins/Bro_FileHash.events.bif.bro @@ -247,4 +248,4 @@ scripts/base/init-default.bro scripts/base/misc/find-checksum-offloading.bro scripts/base/misc/find-filtered-trace.bro scripts/policy/misc/loaded-scripts.bro -#close 2014-10-31-20-38-48 +#close 2015-02-26-14-14-34 diff --git a/testing/btest/Baseline/plugins.hooks/output b/testing/btest/Baseline/plugins.hooks/output index 927a64692f..d9a87ec6ed 100644 --- a/testing/btest/Baseline/plugins.hooks/output +++ b/testing/btest/Baseline/plugins.hooks/output @@ -191,7 +191,7 @@ 0.000000 MetaHookPost CallFunction(Log::__create_stream, (Weird::LOG, [columns=, ev=Weird::log_weird])) -> 0.000000 MetaHookPost CallFunction(Log::__create_stream, (X509::LOG, [columns=, ev=X509::log_x509])) -> 0.000000 MetaHookPost CallFunction(Log::__create_stream, (mysql::LOG, [columns=, ev=MySQL::log_mysql])) -> -0.000000 MetaHookPost CallFunction(Log::__write, (PacketFilter::LOG, [ts=1421870896.278622, node=bro, filter=ip or not ip, init=T, success=T])) -> +0.000000 MetaHookPost CallFunction(Log::__write, (PacketFilter::LOG, [ts=1424960167.277735, node=bro, filter=ip or not ip, init=T, success=T])) -> 0.000000 MetaHookPost CallFunction(Log::add_default_filter, (Cluster::LOG)) -> 0.000000 MetaHookPost CallFunction(Log::add_default_filter, (Communication::LOG)) -> 0.000000 MetaHookPost CallFunction(Log::add_default_filter, (Conn::LOG)) -> @@ -285,8 +285,8 @@ 0.000000 MetaHookPost CallFunction(Log::create_stream, (Weird::LOG, [columns=, ev=Weird::log_weird])) -> 0.000000 MetaHookPost CallFunction(Log::create_stream, (X509::LOG, [columns=, ev=X509::log_x509])) -> 0.000000 MetaHookPost CallFunction(Log::create_stream, (mysql::LOG, [columns=, ev=MySQL::log_mysql])) -> -0.000000 MetaHookPost CallFunction(Log::default_path_func, (PacketFilter::LOG, , [ts=1421870896.278622, node=bro, filter=ip or not ip, init=T, success=T])) -> -0.000000 MetaHookPost CallFunction(Log::write, (PacketFilter::LOG, [ts=1421870896.278622, node=bro, filter=ip or not ip, init=T, success=T])) -> +0.000000 MetaHookPost CallFunction(Log::default_path_func, (PacketFilter::LOG, , [ts=1424960167.277735, node=bro, filter=ip or not ip, init=T, success=T])) -> +0.000000 MetaHookPost CallFunction(Log::write, (PacketFilter::LOG, [ts=1424960167.277735, node=bro, filter=ip or not ip, init=T, success=T])) -> 0.000000 MetaHookPost CallFunction(Notice::want_pp, ()) -> 0.000000 MetaHookPost CallFunction(PacketFilter::build, ()) -> 0.000000 MetaHookPost CallFunction(PacketFilter::combine_filters, (ip or not ip, and, )) -> @@ -344,6 +344,7 @@ 0.000000 MetaHookPost LoadFile(./Bro_FTP.events.bif.bro) -> -1 0.000000 MetaHookPost LoadFile(./Bro_FTP.functions.bif.bro) -> -1 0.000000 MetaHookPost LoadFile(./Bro_File.events.bif.bro) -> -1 +0.000000 MetaHookPost LoadFile(./Bro_FileEntropy.events.bif.bro) -> -1 0.000000 MetaHookPost LoadFile(./Bro_FileExtract.events.bif.bro) -> -1 0.000000 MetaHookPost LoadFile(./Bro_FileExtract.functions.bif.bro) -> -1 0.000000 MetaHookPost LoadFile(./Bro_FileHash.events.bif.bro) -> -1 @@ -730,7 +731,7 @@ 0.000000 MetaHookPre CallFunction(Log::__create_stream, (Weird::LOG, [columns=, ev=Weird::log_weird])) 0.000000 MetaHookPre CallFunction(Log::__create_stream, (X509::LOG, [columns=, ev=X509::log_x509])) 0.000000 MetaHookPre CallFunction(Log::__create_stream, (mysql::LOG, [columns=, ev=MySQL::log_mysql])) -0.000000 MetaHookPre CallFunction(Log::__write, (PacketFilter::LOG, [ts=1421870896.278622, node=bro, filter=ip or not ip, init=T, success=T])) +0.000000 MetaHookPre CallFunction(Log::__write, (PacketFilter::LOG, [ts=1424960167.277735, node=bro, filter=ip or not ip, init=T, success=T])) 0.000000 MetaHookPre CallFunction(Log::add_default_filter, (Cluster::LOG)) 0.000000 MetaHookPre CallFunction(Log::add_default_filter, (Communication::LOG)) 0.000000 MetaHookPre CallFunction(Log::add_default_filter, (Conn::LOG)) @@ -824,8 +825,8 @@ 0.000000 MetaHookPre CallFunction(Log::create_stream, (Weird::LOG, [columns=, ev=Weird::log_weird])) 0.000000 MetaHookPre CallFunction(Log::create_stream, (X509::LOG, [columns=, ev=X509::log_x509])) 0.000000 MetaHookPre CallFunction(Log::create_stream, (mysql::LOG, [columns=, ev=MySQL::log_mysql])) -0.000000 MetaHookPre CallFunction(Log::default_path_func, (PacketFilter::LOG, , [ts=1421870896.278622, node=bro, filter=ip or not ip, init=T, success=T])) -0.000000 MetaHookPre CallFunction(Log::write, (PacketFilter::LOG, [ts=1421870896.278622, node=bro, filter=ip or not ip, init=T, success=T])) +0.000000 MetaHookPre CallFunction(Log::default_path_func, (PacketFilter::LOG, , [ts=1424960167.277735, node=bro, filter=ip or not ip, init=T, success=T])) +0.000000 MetaHookPre CallFunction(Log::write, (PacketFilter::LOG, [ts=1424960167.277735, node=bro, filter=ip or not ip, init=T, success=T])) 0.000000 MetaHookPre CallFunction(Notice::want_pp, ()) 0.000000 MetaHookPre CallFunction(PacketFilter::build, ()) 0.000000 MetaHookPre CallFunction(PacketFilter::combine_filters, (ip or not ip, and, )) @@ -883,6 +884,7 @@ 0.000000 MetaHookPre LoadFile(./Bro_FTP.events.bif.bro) 0.000000 MetaHookPre LoadFile(./Bro_FTP.functions.bif.bro) 0.000000 MetaHookPre LoadFile(./Bro_File.events.bif.bro) +0.000000 MetaHookPre LoadFile(./Bro_FileEntropy.events.bif.bro) 0.000000 MetaHookPre LoadFile(./Bro_FileExtract.events.bif.bro) 0.000000 MetaHookPre LoadFile(./Bro_FileExtract.functions.bif.bro) 0.000000 MetaHookPre LoadFile(./Bro_FileHash.events.bif.bro) @@ -1269,7 +1271,7 @@ 0.000000 | HookCallFunction Log::__create_stream(Weird::LOG, [columns=, ev=Weird::log_weird]) 0.000000 | HookCallFunction Log::__create_stream(X509::LOG, [columns=, ev=X509::log_x509]) 0.000000 | HookCallFunction Log::__create_stream(mysql::LOG, [columns=, ev=MySQL::log_mysql]) -0.000000 | HookCallFunction Log::__write(PacketFilter::LOG, [ts=1421870896.278622, node=bro, filter=ip or not ip, init=T, success=T]) +0.000000 | HookCallFunction Log::__write(PacketFilter::LOG, [ts=1424960167.277735, node=bro, filter=ip or not ip, init=T, success=T]) 0.000000 | HookCallFunction Log::add_default_filter(Cluster::LOG) 0.000000 | HookCallFunction Log::add_default_filter(Communication::LOG) 0.000000 | HookCallFunction Log::add_default_filter(Conn::LOG) @@ -1363,8 +1365,8 @@ 0.000000 | HookCallFunction Log::create_stream(Weird::LOG, [columns=, ev=Weird::log_weird]) 0.000000 | HookCallFunction Log::create_stream(X509::LOG, [columns=, ev=X509::log_x509]) 0.000000 | HookCallFunction Log::create_stream(mysql::LOG, [columns=, ev=MySQL::log_mysql]) -0.000000 | HookCallFunction Log::default_path_func(PacketFilter::LOG, , [ts=1421870896.278622, node=bro, filter=ip or not ip, init=T, success=T]) -0.000000 | HookCallFunction Log::write(PacketFilter::LOG, [ts=1421870896.278622, node=bro, filter=ip or not ip, init=T, success=T]) +0.000000 | HookCallFunction Log::default_path_func(PacketFilter::LOG, , [ts=1424960167.277735, node=bro, filter=ip or not ip, init=T, success=T]) +0.000000 | HookCallFunction Log::write(PacketFilter::LOG, [ts=1424960167.277735, node=bro, filter=ip or not ip, init=T, success=T]) 0.000000 | HookCallFunction Notice::want_pp() 0.000000 | HookCallFunction PacketFilter::build() 0.000000 | HookCallFunction PacketFilter::combine_filters(ip or not ip, and, ) From f4141bde6d20d66a0c705d7109fb80f918f41049 Mon Sep 17 00:00:00 2001 From: Vlad Grigorescu Date: Thu, 17 Mar 2016 14:23:18 -0500 Subject: [PATCH 04/13] Call ProtocolConfirmation in SIP only if we saw a response SIP packet --- src/analyzer/protocol/sip/sip-analyzer.pac | 1 - 1 file changed, 1 deletion(-) diff --git a/src/analyzer/protocol/sip/sip-analyzer.pac b/src/analyzer/protocol/sip/sip-analyzer.pac index 36a1dae7e2..829904aa3a 100644 --- a/src/analyzer/protocol/sip/sip-analyzer.pac +++ b/src/analyzer/protocol/sip/sip-analyzer.pac @@ -18,7 +18,6 @@ refine flow SIP_Flow += { function proc_sip_request(method: bytestring, uri: bytestring, vers: SIP_Version): bool %{ - connection()->bro_analyzer()->ProtocolConfirmation(); if ( sip_request ) { BifEvent::generate_sip_request(connection()->bro_analyzer(), connection()->bro_analyzer()->Conn(), From d731cb9a18d9304e5150b490970cfbe99d52bdfc Mon Sep 17 00:00:00 2001 From: Vlad Grigorescu Date: Thu, 17 Mar 2016 14:25:15 -0500 Subject: [PATCH 05/13] Call ProtocolConfirmation in SNMP only if we saw a response SNMP packet --- src/analyzer/protocol/snmp/snmp-analyzer.pac | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/analyzer/protocol/snmp/snmp-analyzer.pac b/src/analyzer/protocol/snmp/snmp-analyzer.pac index 891531b292..44dce4dbf5 100644 --- a/src/analyzer/protocol/snmp/snmp-analyzer.pac +++ b/src/analyzer/protocol/snmp/snmp-analyzer.pac @@ -373,10 +373,12 @@ refine connection SNMP_Conn += { function proc_header(rec: Header): bool %{ + if ( ! ${rec.is_orig} ) + bro_analyzer()->ProtocolConfirmation(); + if ( rec->unknown() ) return false; - bro_analyzer()->ProtocolConfirmation(); return true; %} From 095e6c27876ebc467513af328417705e61100ca2 Mon Sep 17 00:00:00 2001 From: Seth Hall Date: Mon, 21 Mar 2016 12:08:02 -0400 Subject: [PATCH 06/13] Fixing a test. --- .../canonified_loaded_scripts.log | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/testing/btest/Baseline/coverage.bare-load-baseline/canonified_loaded_scripts.log b/testing/btest/Baseline/coverage.bare-load-baseline/canonified_loaded_scripts.log index 4d1f2037a4..a010a4fd3e 100644 --- a/testing/btest/Baseline/coverage.bare-load-baseline/canonified_loaded_scripts.log +++ b/testing/btest/Baseline/coverage.bare-load-baseline/canonified_loaded_scripts.log @@ -3,7 +3,7 @@ #empty_field (empty) #unset_field - #path loaded_scripts -#open 2015-08-31-04-50-43 +#open 2016-03-21-16-06-31 #fields name #types string scripts/base/init-bare.bro @@ -109,6 +109,7 @@ scripts/base/init-bare.bro build/scripts/base/bif/plugins/Bro_Teredo.events.bif.bro build/scripts/base/bif/plugins/Bro_UDP.events.bif.bro build/scripts/base/bif/plugins/Bro_ZIP.events.bif.bro + build/scripts/base/bif/plugins/Bro_FileEntropy.events.bif.bro build/scripts/base/bif/plugins/Bro_FileExtract.events.bif.bro build/scripts/base/bif/plugins/Bro_FileExtract.functions.bif.bro build/scripts/base/bif/plugins/Bro_FileHash.events.bif.bro @@ -128,4 +129,4 @@ scripts/base/init-bare.bro build/scripts/base/bif/plugins/Bro_SQLiteWriter.sqlite.bif.bro scripts/policy/misc/loaded-scripts.bro scripts/base/utils/paths.bro -#close 2015-08-31-04-50-43 +#close 2016-03-21-16-06-31 From 35a4e428cfe4964bd6bbdff80ad0fff42c4ffa8f Mon Sep 17 00:00:00 2001 From: william Date: Sat, 26 Mar 2016 01:54:51 -0700 Subject: [PATCH 07/13] Wrong regex literal in scripting doc --- doc/scripting/index.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/scripting/index.rst b/doc/scripting/index.rst index 2b5cfbb49c..a776fc0ad3 100644 --- a/doc/scripting/index.rst +++ b/doc/scripting/index.rst @@ -776,7 +776,7 @@ string against which it will be tested to be on the right. In the sample above, two local variables are declared to hold our sample sentence and regular expression. Our regular expression in this case will return true if the string contains either the word -``quick`` or the word ``fox``. The ``if`` statement in the script uses +``quick`` or the word ``lazy``. The ``if`` statement in the script uses embedded matching and the ``in`` operator to check for the existence of the pattern within the string. If the statement resolves to true, :bro:id:`split` is called to break the string into separate pieces. From b5f1fb33fac78d305653feb799bd936a16083e3b Mon Sep 17 00:00:00 2001 From: Robin Sommer Date: Thu, 7 Apr 2016 13:40:31 -0700 Subject: [PATCH 08/13] Updating submodule(s). [nomail] --- aux/broccoli | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/aux/broccoli b/aux/broccoli index 6ded82da49..f83038b17f 160000 --- a/aux/broccoli +++ b/aux/broccoli @@ -1 +1 @@ -Subproject commit 6ded82da498d805def6aa129cd7691d3b7287c37 +Subproject commit f83038b17fc83788415a58d77f75ad182ca6a9b7 From 849875e8be73d0e0b5a6ebca74ed56fdabba464b Mon Sep 17 00:00:00 2001 From: Martin van Hensbergen Date: Mon, 11 Apr 2016 10:35:00 +0200 Subject: [PATCH 09/13] Analyzer and bro script for RFB protocol (VNC) This analyzer parses the Remote Frame Buffer protocol, usually referred to as the 'VNC protocol'. It supports several dialects (3.3, 3.7, 3.8) and also handles the Apple Remote Desktop variant. It will log such facts as client/server versions, authentication method used, authentication result, height, width and name of the shared screen. It also includes two testcases. Todo: Apple Remote Desktop seems to have some bytes prepended to the screen name. This is not interepreted correctly. --- scripts/base/init-default.bro | 1 + scripts/base/protocols/rfb/__load__.bro | 3 + scripts/base/protocols/rfb/dpd.sig | 12 ++ scripts/base/protocols/rfb/main.bro | 143 +++++++++++++ src/analyzer/protocol/CMakeLists.txt | 1 + src/analyzer/protocol/rfb/CMakeLists.txt | 11 + src/analyzer/protocol/rfb/Plugin.cc | 25 +++ src/analyzer/protocol/rfb/RFB.cc | 69 +++++++ src/analyzer/protocol/rfb/RFB.h | 45 ++++ src/analyzer/protocol/rfb/events.bif | 50 +++++ src/analyzer/protocol/rfb/rfb-analyzer.pac | 193 ++++++++++++++++++ src/analyzer/protocol/rfb/rfb-protocol.pac | 139 +++++++++++++ src/analyzer/protocol/rfb/rfb.pac | 42 ++++ .../rfb.log | 12 ++ .../rfb.log | 12 ++ .../btest/Traces/rfb/vnc-mac-to-linux.pcap | Bin 0 -> 40255 bytes testing/btest/Traces/rfb/vncmac.pcap | Bin 0 -> 8848 bytes .../rfb/rfb-apple-remote-desktop.test | 4 + .../base/protocols/rfb/vnc-mac-to-linux.test | 4 + 19 files changed, 766 insertions(+) create mode 100644 scripts/base/protocols/rfb/__load__.bro create mode 100644 scripts/base/protocols/rfb/dpd.sig create mode 100644 scripts/base/protocols/rfb/main.bro create mode 100644 src/analyzer/protocol/rfb/CMakeLists.txt create mode 100644 src/analyzer/protocol/rfb/Plugin.cc create mode 100644 src/analyzer/protocol/rfb/RFB.cc create mode 100644 src/analyzer/protocol/rfb/RFB.h create mode 100644 src/analyzer/protocol/rfb/events.bif create mode 100644 src/analyzer/protocol/rfb/rfb-analyzer.pac create mode 100644 src/analyzer/protocol/rfb/rfb-protocol.pac create mode 100644 src/analyzer/protocol/rfb/rfb.pac create mode 100644 testing/btest/Baseline/scripts.base.protocols.rfb.rfb-apple-remote-desktop/rfb.log create mode 100644 testing/btest/Baseline/scripts.base.protocols.rfb.vnc-mac-to-linux/rfb.log create mode 100644 testing/btest/Traces/rfb/vnc-mac-to-linux.pcap create mode 100644 testing/btest/Traces/rfb/vncmac.pcap create mode 100644 testing/btest/scripts/base/protocols/rfb/rfb-apple-remote-desktop.test create mode 100644 testing/btest/scripts/base/protocols/rfb/vnc-mac-to-linux.test diff --git a/scripts/base/init-default.bro b/scripts/base/init-default.bro index 609ed7200c..418ccbb43e 100644 --- a/scripts/base/init-default.bro +++ b/scripts/base/init-default.bro @@ -55,6 +55,7 @@ @load base/protocols/pop3 @load base/protocols/radius @load base/protocols/rdp +@load base/protocols/rfb @load base/protocols/sip @load base/protocols/snmp @load base/protocols/smtp diff --git a/scripts/base/protocols/rfb/__load__.bro b/scripts/base/protocols/rfb/__load__.bro new file mode 100644 index 0000000000..9e43682d13 --- /dev/null +++ b/scripts/base/protocols/rfb/__load__.bro @@ -0,0 +1,3 @@ +# Generated by binpac_quickstart +@load ./main +@load-sigs ./dpd.sig \ No newline at end of file diff --git a/scripts/base/protocols/rfb/dpd.sig b/scripts/base/protocols/rfb/dpd.sig new file mode 100644 index 0000000000..40793ad590 --- /dev/null +++ b/scripts/base/protocols/rfb/dpd.sig @@ -0,0 +1,12 @@ +signature dpd_rfb_server { + ip-proto == tcp + payload /^RFB/ + requires-reverse-signature dpd_rfb_client + enable "rfb" +} + +signature dpd_rfb_client { + ip-proto == tcp + payload /^RFB/ + tcp-state originator +} \ No newline at end of file diff --git a/scripts/base/protocols/rfb/main.bro b/scripts/base/protocols/rfb/main.bro new file mode 100644 index 0000000000..97f194b789 --- /dev/null +++ b/scripts/base/protocols/rfb/main.bro @@ -0,0 +1,143 @@ +module Rfb; + +export { + redef enum Log::ID += { LOG }; + + type Info: record { + ## Timestamp for when the event happened. + ts: time &log; + ## Unique ID for the connection. + uid: string &log; + ## The connection's 4-tuple of endpoint addresses/ports. + id: conn_id &log; + + client_major_version: string &log &optional; + client_minor_version: string &log &optional; + server_major_version: string &log &optional; + server_minor_version: string &log &optional; + + authentication_method: string &log &optional; + auth: bool &log &optional; + + share_flag: bool &log &optional; + desktop_name: string &log &optional; + width: count &log &optional; + height: count &log &optional; + + done: bool &default=F; + }; + + global log_rfb: event(rec: Info); +} + +function friendly_auth_name(auth: count): string { + switch (auth) { + case 0: + return "Invalid"; + case 1: + return "None"; + case 2: + return "VNC"; + case 16: + return "Tight"; + case 17: + return "Ultra"; + case 18: + return "TLS"; + case 19: + return "VeNCrypt"; + case 20: + return "GTK-VNC SASL"; + case 21: + return "MD5 hash authentication"; + case 22: + return "Colin Dean xvp"; + case 30: + return "Apple Remote Desktop"; + } + return "RealVNC"; + +} + + +redef record connection += { + rfb_state: Info &optional; +}; + +event bro_init() &priority=5 + { + Log::create_stream(Rfb::LOG, [$columns=Info, $ev=log_rfb, $path="rfb"]); + } + +function write_log(c:connection) { + local state = c$rfb_state; + if ( state?$done && state$done == T) { + return; + } + Log::write(Rfb::LOG, c$rfb_state); + c$rfb_state$done = T; +} + +function set_session(c: connection) { + if ( ! c?$rfb_state ) { + local info: Info; + info$ts = network_time(); + info$uid = c$uid; + info$id = c$id; + + c$rfb_state = info; + } + } + +event rfb_event(c: connection) + { + set_session(c); + } + +event rfb_client_version(c: connection, major_version: string, minor_version: string) + { + set_session(c); + c$rfb_state$client_major_version = major_version; + c$rfb_state$client_minor_version = minor_version; + } + +event rfb_server_version(c: connection, major_version: string, minor_version: string) + { + set_session(c); + c$rfb_state$server_major_version = major_version; + c$rfb_state$server_minor_version = minor_version; + add c$service["rfb"]; + } + +event rfb_authentication_type(c: connection, authtype: count) + { + c$rfb_state$authentication_method = friendly_auth_name(authtype); + } + +event rfb_server_parameters(c: connection, name: string, width: count, height: count) + { + c$rfb_state$desktop_name = name; + c$rfb_state$width = width; + c$rfb_state$height = height; + write_log(c); + } + +event rfb_auth_result(c: connection, result: count) + { + if ( result ==0 ) { + c$rfb_state$auth = T; + } else { + c$rfb_state$auth = F; + } + } + +event rfb_share_flag(c: connection, flag: bool) + { + c$rfb_state$share_flag = flag; + } + +event connection_state_remove(c: connection) { + if ( c?$rfb_state ) { + write_log(c); + } +} diff --git a/src/analyzer/protocol/CMakeLists.txt b/src/analyzer/protocol/CMakeLists.txt index 467fce83ee..8c7a3f002e 100644 --- a/src/analyzer/protocol/CMakeLists.txt +++ b/src/analyzer/protocol/CMakeLists.txt @@ -30,6 +30,7 @@ add_subdirectory(pia) add_subdirectory(pop3) add_subdirectory(radius) add_subdirectory(rdp) +add_subdirectory(rfb) add_subdirectory(rpc) add_subdirectory(sip) add_subdirectory(snmp) diff --git a/src/analyzer/protocol/rfb/CMakeLists.txt b/src/analyzer/protocol/rfb/CMakeLists.txt new file mode 100644 index 0000000000..8131ca7362 --- /dev/null +++ b/src/analyzer/protocol/rfb/CMakeLists.txt @@ -0,0 +1,11 @@ +# Generated by binpac_quickstart + +include(BroPlugin) + +include_directories(BEFORE ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DIR}) + +bro_plugin_begin(Bro RFB) + bro_plugin_cc(RFB.cc Plugin.cc) + bro_plugin_bif(events.bif) + bro_plugin_pac(rfb.pac rfb-analyzer.pac rfb-protocol.pac) +bro_plugin_end() \ No newline at end of file diff --git a/src/analyzer/protocol/rfb/Plugin.cc b/src/analyzer/protocol/rfb/Plugin.cc new file mode 100644 index 0000000000..55704497e9 --- /dev/null +++ b/src/analyzer/protocol/rfb/Plugin.cc @@ -0,0 +1,25 @@ +// Generated by binpac_quickstart + +#include "plugin/Plugin.h" + +#include "RFB.h" + +namespace plugin { +namespace Bro_RFB { + +class Plugin : public plugin::Plugin { +public: + plugin::Configuration Configure() + { + AddComponent(new ::analyzer::Component("RFB", + ::analyzer::rfb::RFB_Analyzer::InstantiateAnalyzer)); + + plugin::Configuration config; + config.name = "Bro::RFB"; + config.description = "Parser for rfb (VNC) analyzer"; + return config; + } +} plugin; + +} +} \ No newline at end of file diff --git a/src/analyzer/protocol/rfb/RFB.cc b/src/analyzer/protocol/rfb/RFB.cc new file mode 100644 index 0000000000..c761d0bf0f --- /dev/null +++ b/src/analyzer/protocol/rfb/RFB.cc @@ -0,0 +1,69 @@ +// Generated by binpac_quickstart + +#include "RFB.h" + +#include "analyzer/protocol/tcp/TCP_Reassembler.h" + +#include "Reporter.h" + +#include "events.bif.h" + +using namespace analyzer::rfb; + +RFB_Analyzer::RFB_Analyzer(Connection* c) + +: tcp::TCP_ApplicationAnalyzer("RFB", c) + + { + interp = new binpac::RFB::RFB_Conn(this); + had_gap = false; + } + +RFB_Analyzer::~RFB_Analyzer() + { + delete interp; + } + +void RFB_Analyzer::Done() + { + tcp::TCP_ApplicationAnalyzer::Done(); + + interp->FlowEOF(true); + interp->FlowEOF(false); + + } + +void RFB_Analyzer::EndpointEOF(bool is_orig) + { + tcp::TCP_ApplicationAnalyzer::EndpointEOF(is_orig); + interp->FlowEOF(is_orig); + } + +void RFB_Analyzer::DeliverStream(int len, const u_char* data, bool orig) + { + tcp::TCP_ApplicationAnalyzer::DeliverStream(len, data, orig); + assert(TCP()); + if ( TCP()->IsPartial() ) + return; + + if ( had_gap ) + // If only one side had a content gap, we could still try to + // deliver data to the other side if the script layer can handle this. + return; + + try + { + interp->NewData(orig, data, data + len); + } + catch ( const binpac::Exception& e ) + { + ProtocolViolation(fmt("Binpac exception: %s", e.c_msg())); + } + } + +void RFB_Analyzer::Undelivered(uint64 seq, int len, bool orig) + { + tcp::TCP_ApplicationAnalyzer::Undelivered(seq, len, orig); + had_gap = true; + interp->NewGap(orig, len); + } diff --git a/src/analyzer/protocol/rfb/RFB.h b/src/analyzer/protocol/rfb/RFB.h new file mode 100644 index 0000000000..cd6e7348d0 --- /dev/null +++ b/src/analyzer/protocol/rfb/RFB.h @@ -0,0 +1,45 @@ +// Generated by binpac_quickstart + +#ifndef ANALYZER_PROTOCOL_RFB_RFB_H +#define ANALYZER_PROTOCOL_RFB_RFB_H + +#include "events.bif.h" + + +#include "analyzer/protocol/tcp/TCP.h" + +#include "rfb_pac.h" + +namespace analyzer { namespace rfb { + +class RFB_Analyzer + +: public tcp::TCP_ApplicationAnalyzer { + +public: + RFB_Analyzer(Connection* conn); + virtual ~RFB_Analyzer(); + + // Overriden from Analyzer. + virtual void Done(); + + virtual void DeliverStream(int len, const u_char* data, bool orig); + virtual void Undelivered(uint64 seq, int len, bool orig); + + // Overriden from tcp::TCP_ApplicationAnalyzer. + virtual void EndpointEOF(bool is_orig); + + + static analyzer::Analyzer* InstantiateAnalyzer(Connection* conn) + { return new RFB_Analyzer(conn); } + +protected: + binpac::RFB::RFB_Conn* interp; + + bool had_gap; + +}; + +} } // namespace analyzer::* + +#endif diff --git a/src/analyzer/protocol/rfb/events.bif b/src/analyzer/protocol/rfb/events.bif new file mode 100644 index 0000000000..a3cf5f7ad8 --- /dev/null +++ b/src/analyzer/protocol/rfb/events.bif @@ -0,0 +1,50 @@ +## Generated for RFB event +## +## c: The connection record for the underlying transport-layer session/flow. +event rfb_event%(c: connection%); + +## Generated for RFB event authentication mechanism selection +## +## c: The connection record for the underlying transport-layer session/flow. +## +## authtype: the value of the chosen authentication mechanism +event rfb_authentication_type%(c: connection, authtype: count%); + +## Generated for RFB event authentication result message +## +## c: The connection record for the underlying transport-layer session/flow. +## +## result: whether or not authentication was succesful +event rfb_auth_result%(c: connection, result: count%); + +## Generated for RFB event share flag messages +## +## c: The connection record for the underlying transport-layer session/flow. +## +## flag: whether or not the share flag was set +event rfb_share_flag%(c: connection, flag: bool%); + +## Generated for RFB event client banner message +## +## c: The connection record for the underlying transport-layer session/flow. +## +## version: of the client's rfb library +event rfb_client_version%(c: connection, major_version: string, minor_version: string%); + +## Generated for RFB event server banner message +## +## c: The connection record for the underlying transport-layer session/flow. +## +## version: of the server's rfb library +event rfb_server_version%(c: connection, major_version: string, minor_version: string%); + +## Generated for RFB event server parameter message +## +## c: The connection record for the underlying transport-layer session/flow. +## +## name: name of the shared screen +## +## width: width of the shared screen +## +## height: height of the shared screen +event rfb_server_parameters%(c: connection, name: string, width: count, height: count%); \ No newline at end of file diff --git a/src/analyzer/protocol/rfb/rfb-analyzer.pac b/src/analyzer/protocol/rfb/rfb-analyzer.pac new file mode 100644 index 0000000000..4233a423f7 --- /dev/null +++ b/src/analyzer/protocol/rfb/rfb-analyzer.pac @@ -0,0 +1,193 @@ +# Generated by binpac_quickstart + +refine flow RFB_Flow += { + function proc_rfb_message(msg: RFB_PDU): bool + %{ + BifEvent::generate_rfb_event(connection()->bro_analyzer(), connection()->bro_analyzer()->Conn()); + return true; + %} + + function proc_rfb_client_version(major: bytestring, minor: bytestring) : bool + %{ + BifEvent::generate_rfb_client_version(connection()->bro_analyzer(), connection()->bro_analyzer()->Conn(), bytestring_to_val(major), bytestring_to_val(minor)); + return true; + %} + + function proc_rfb_version(client: bool, major: bytestring, minor: bytestring) : bool + %{ + if (client) { + BifEvent::generate_rfb_client_version(connection()->bro_analyzer(), connection()->bro_analyzer()->Conn(), bytestring_to_val(major), bytestring_to_val(minor)); + } else { + BifEvent::generate_rfb_server_version(connection()->bro_analyzer(), connection()->bro_analyzer()->Conn(), bytestring_to_val(major), bytestring_to_val(minor)); + } + return true; + %} + + function proc_rfb_share_flag(shared: bool) : bool + %{ + BifEvent::generate_rfb_share_flag(connection()->bro_analyzer(), connection()->bro_analyzer()->Conn(), shared); + return true; + %} + + function proc_security_types(msg: RFBSecurityTypes) : bool + %{ + BifEvent::generate_rfb_authentication_type(connection()->bro_analyzer(), connection()->bro_analyzer()->Conn(), ${msg.sectype}); + return true; + %} + + function proc_security_types37(msg: RFBAuthTypeSelected) : bool + %{ + BifEvent::generate_rfb_authentication_type(connection()->bro_analyzer(), connection()->bro_analyzer()->Conn(), ${msg.type}); + return true; + %} + + function proc_handle_server_params(msg:RFBServerInit) : bool + %{ + BifEvent::generate_rfb_server_parameters(connection()->bro_analyzer(), connection()->bro_analyzer()->Conn(), bytestring_to_val(${msg.name}), ${msg.width}, ${msg.height}); + return true; + %} + + function proc_handle_security_result(result : uint32) : bool + %{ + BifEvent::generate_rfb_auth_result(connection()->bro_analyzer(), connection()->bro_analyzer()->Conn(), result); + return true; + %} +}; + +refine connection RFB_Conn += { + %member{ + enum states { + AWAITING_SERVER_BANNER = 0, + AWAITING_CLIENT_BANNER = 1, + AWAITING_SERVER_AUTH_TYPES = 2, + AWAITING_SERVER_CHALLENGE = 3, + AWAITING_CLIENT_RESPONSE = 4, + AWAITING_SERVER_AUTH_RESULT = 5, + AWAITING_CLIENT_SHARE_FLAG = 6, + AWAITING_SERVER_PARAMS = 7, + AWAITING_CLIENT_AUTH_METHOD = 8, + AWAITING_SERVER_ARD_CHALLENGE = 9, + AWAITING_CLIENT_ARD_RESPONSE = 10, + AWAITING_SERVER_AUTH_TYPES37 = 11, + AWAITING_CLIENT_AUTH_TYPE_SELECTED37 = 12, + RFB_MESSAGE = 13 + }; + %} + + function get_state(client: bool) : int + %{ + return state; + %} + + function handle_banners(client: bool, msg: RFBProtocolVersion) : bool + %{ + if ( client ) { + // Set protocol version on client's version + int minor_version = bytestring_to_int(${msg.minor},10); + + // Apple specifies minor version "889" but talks v37 + if ( minor_version >= 7 ) { + state = AWAITING_SERVER_AUTH_TYPES37; + } else { + state = AWAITING_SERVER_AUTH_TYPES; + } + } else { + if ( !client ) { + state = AWAITING_CLIENT_BANNER; + } + } + return true; + %} + + function handle_ard_challenge() : bool + %{ + state = AWAITING_CLIENT_ARD_RESPONSE; + return true; + %} + + function handle_ard_response() : bool + %{ + state = AWAITING_SERVER_AUTH_RESULT; + return true; + %} + + function handle_auth_request() : bool + %{ + state = AWAITING_CLIENT_RESPONSE; + return true; + %} + + function handle_auth_response() : bool + %{ + state = AWAITING_SERVER_AUTH_RESULT; + return true; + %} + + function handle_security_result(msg: RFBSecurityResult) : bool + %{ + if ( ${msg.result} == 0 ) //FIXME + { + state = AWAITING_CLIENT_SHARE_FLAG; + } + return true; + %} + + function handle_client_init(msg: RFBClientInit) : bool + %{ + state = AWAITING_SERVER_PARAMS; + + return true; + %} + + function handle_server_init(msg: RFBServerInit) : bool + %{ + state = RFB_MESSAGE; + return true; + %} + + function handle_security_types(msg: RFBSecurityTypes): bool + %{ + if ( msg->sectype() == 0 ) { // No auth + state = AWAITING_CLIENT_SHARE_FLAG; + return true; + } + if ( msg->sectype() == 2 ) { //VNC + state = AWAITING_SERVER_CHALLENGE; + } + return false; + %} + + function handle_security_types37(msg: RFBSecurityTypes37): bool + %{ + if ( ${msg.count} == 0 ) { // No auth + state = AWAITING_CLIENT_SHARE_FLAG; + return true; + } + state = AWAITING_CLIENT_AUTH_TYPE_SELECTED37; + return true; + %} + + function handle_auth_type_selected(msg: RFBAuthTypeSelected): bool + %{ + if ( ${msg.type} == 30 ) { // Apple Remote Desktop + state = AWAITING_SERVER_ARD_CHALLENGE; + return true; + } + + if ( ${msg.type} == 1 ) { // No Auth + state = AWAITING_SERVER_AUTH_RESULT; + } else { + // Assume VNC + state = AWAITING_SERVER_CHALLENGE; + } + return true; + %} + + %member{ + uint8 state = AWAITING_SERVER_BANNER; + %} +}; + +refine typeattr RFB_PDU += &let { + proc: bool = $context.flow.proc_rfb_message(this); +}; diff --git a/src/analyzer/protocol/rfb/rfb-protocol.pac b/src/analyzer/protocol/rfb/rfb-protocol.pac new file mode 100644 index 0000000000..0eb5542001 --- /dev/null +++ b/src/analyzer/protocol/rfb/rfb-protocol.pac @@ -0,0 +1,139 @@ +enum states { + AWAITING_SERVER_BANNER = 0, + AWAITING_CLIENT_BANNER = 1, + AWAITING_SERVER_AUTH_TYPES = 2, + AWAITING_SERVER_CHALLENGE = 3, + AWAITING_CLIENT_RESPONSE = 4, + AWAITING_SERVER_AUTH_RESULT = 5, + AWAITING_CLIENT_SHARE_FLAG = 6, + AWAITING_SERVER_PARAMS = 7, + AWAITING_CLIENT_AUTH_METHOD = 8, + AWAITING_SERVER_ARD_CHALLENGE = 9, + AWAITING_CLIENT_ARD_RESPONSE = 10, + AWAITING_SERVER_AUTH_TYPES37 = 11, + AWAITING_CLIENT_AUTH_TYPE_SELECTED37 = 12, + RFB_MESSAGE = 13 + }; + +type RFBProtocolVersion (client: bool) = record { + header : "RFB "; + major :bytestring &length=3; + dot: "."; + minor: bytestring &length=3; + pad: uint8; +} &let { + proc: bool = $context.connection.handle_banners(client, this); + proc2: bool = $context.flow.proc_rfb_version(client, major, minor); +} + +type RFBSecurityTypes = record { + sectype: uint32; +} &let { + proc: bool = $context.connection.handle_security_types(this); + proc2: bool = $context.flow.proc_security_types(this); +}; + +type RFBSecurityTypes37 = record { + count: uint8; + types: uint8[count]; +} &let { + proc: bool = $context.connection.handle_security_types37(this); +}; + +type RFBAuthTypeSelected = record { + type: uint8; +} &let { + proc: bool = $context.connection.handle_auth_type_selected(this); + proc2: bool = $context.flow.proc_security_types37(this); +}; + +type RFBSecurityResult = record { + result: uint32; +} &let { + proc: bool = $context.connection.handle_security_result(this); + proc2: bool = $context.flow.proc_handle_security_result(result); +}; + +type RFBSecurityResultReason = record { + len: uint32; + reason: bytestring &length=len; +}; + +type RFBVNCAuthenticationRequest = record { + challenge: bytestring &length=16; +} &let { + proc: bool = $context.connection.handle_auth_request(); +}; + +type RFBVNCAuthenticationResponse = record { + response: bytestring &length= 16; +} &let { + proc: bool = $context.connection.handle_auth_response(); +}; + +type RFBSecurityARDChallenge = record { + challenge: bytestring &restofdata; +} &let { + proc: bool = $context.connection.handle_ard_challenge(); +} + +type RFBSecurityARDResponse = record { + response: bytestring &restofdata; +} &let { + proc: bool = $context.connection.handle_ard_response(); +} + +type RFBClientInit = record { + shared_flag: uint8; +} &let { + proc: bool = $context.connection.handle_client_init(this); + proc2: bool = $context.flow.proc_rfb_share_flag(shared_flag); +} + +type RFBServerInit = record { + width: uint16; + height: uint16; + pixel_format: bytestring &length= 16; + len : uint32; + name: bytestring &length = len; +} &let { + proc: bool = $context.connection.handle_server_init(this); + proc2: bool = $context.flow.proc_handle_server_params(this); +}; + +type RFB_PDU_request = record { + request: case state of { + AWAITING_CLIENT_BANNER -> version: RFBProtocolVersion(true); + AWAITING_CLIENT_RESPONSE -> response: RFBVNCAuthenticationResponse; + AWAITING_CLIENT_SHARE_FLAG -> shareflag: RFBClientInit; + AWAITING_CLIENT_AUTH_TYPE_SELECTED37 -> authtype: RFBAuthTypeSelected; + AWAITING_CLIENT_ARD_RESPONSE -> ard_response: RFBSecurityARDResponse; + RFB_MESSAGE -> ignore: bytestring &restofdata; + default -> data: bytestring &restofdata; + } &requires(state); + } &let { + state: uint8 = $context.connection.get_state(true); +}; + +type RFB_PDU_response = record { + request: case rstate of { + AWAITING_SERVER_BANNER -> version: RFBProtocolVersion(false); + AWAITING_SERVER_AUTH_TYPES -> auth_types: RFBSecurityTypes; + AWAITING_SERVER_AUTH_TYPES37 -> auth_types37: RFBSecurityTypes37; + AWAITING_SERVER_CHALLENGE -> challenge: RFBVNCAuthenticationRequest; + AWAITING_SERVER_AUTH_RESULT -> authresult : RFBSecurityResult; + AWAITING_SERVER_ARD_CHALLENGE -> ard_challenge: RFBSecurityARDChallenge; + AWAITING_SERVER_PARAMS -> serverinit: RFBServerInit; + RFB_MESSAGE -> ignore: bytestring &restofdata; + default -> data: bytestring &restofdata; + } &requires(rstate); + } &let { + rstate: uint8 = $context.connection.get_state(false); +}; + +type RFB_PDU(is_orig: bool) = record { + payload: case is_orig of { + true -> request: RFB_PDU_request; + false -> response: RFB_PDU_response; + }; +} &byteorder = bigendian; diff --git a/src/analyzer/protocol/rfb/rfb.pac b/src/analyzer/protocol/rfb/rfb.pac new file mode 100644 index 0000000000..310ad38893 --- /dev/null +++ b/src/analyzer/protocol/rfb/rfb.pac @@ -0,0 +1,42 @@ +# Generated by binpac_quickstart + +# Analyzer for Parser for rfb (VNC) +# - rfb-protocol.pac: describes the rfb protocol messages +# - rfb-analyzer.pac: describes the rfb analyzer code + +%include binpac.pac +%include bro.pac + +%extern{ + #include "events.bif.h" +%} + +analyzer RFB withcontext { + connection: RFB_Conn; + flow: RFB_Flow; +}; + +# Our connection consists of two flows, one in each direction. +connection RFB_Conn(bro_analyzer: BroAnalyzer) { + upflow = RFB_Flow(true); + downflow = RFB_Flow(false); +}; + +%include rfb-protocol.pac + +# Now we define the flow: +flow RFB_Flow(is_orig: bool) { + + # ## TODO: Determine if you want flowunit or datagram parsing: + + # Using flowunit will cause the anlayzer to buffer incremental input. + # This is needed for &oneline and &length. If you don't need this, you'll + # get better performance with datagram. + + # flowunit = RFB_PDU(is_orig) withcontext(connection, this); + + datagram = RFB_PDU(is_orig) withcontext(connection, this); + +}; + +%include rfb-analyzer.pac \ No newline at end of file diff --git a/testing/btest/Baseline/scripts.base.protocols.rfb.rfb-apple-remote-desktop/rfb.log b/testing/btest/Baseline/scripts.base.protocols.rfb.rfb-apple-remote-desktop/rfb.log new file mode 100644 index 0000000000..6f8a2e987d --- /dev/null +++ b/testing/btest/Baseline/scripts.base.protocols.rfb.rfb-apple-remote-desktop/rfb.log @@ -0,0 +1,12 @@ +#separator \x09 +#set_separator , +#empty_field (empty) +#unset_field - +#path rfb +#open 2016-04-11-08-25-48 +#fields ts uid id.orig_h id.orig_p id.resp_h id.resp_p client_major_version client_minor_version server_major_version server_minor_version authentication_method auth share_flag desktop_name width height +#types time string addr port addr port string string string string string bool bool string count count +1459148054.031382 CCvvfg3TEfuqmmG4bh 192.168.2.115 52353 192.168.2.16 5900 003 889 003 889 Apple Remote Desktop T T \x00\x00\x00\x00\x00\x02\xbf\xfe\xe7\x03\xe0\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00MacMini SSD 1920 1080 +1459148050.685932 CjhGID4nQcgTWjvg4c 192.168.2.115 52352 192.168.2.16 5900 003 889 003 889 Apple Remote Desktop F - - - - +1459148047.738043 CXWv6p3arKYeMETxOg 192.168.2.115 52351 192.168.2.16 5900 003 889 003 889 - - - - - - +#close 2016-04-11-08-25-48 diff --git a/testing/btest/Baseline/scripts.base.protocols.rfb.vnc-mac-to-linux/rfb.log b/testing/btest/Baseline/scripts.base.protocols.rfb.vnc-mac-to-linux/rfb.log new file mode 100644 index 0000000000..de1d70ec63 --- /dev/null +++ b/testing/btest/Baseline/scripts.base.protocols.rfb.vnc-mac-to-linux/rfb.log @@ -0,0 +1,12 @@ +#separator \x09 +#set_separator , +#empty_field (empty) +#unset_field - +#path rfb +#open 2016-04-06-13-48-56 +#fields ts uid id.orig_h id.orig_p id.resp_h id.resp_p client_major_version client_minor_version server_major_version server_minor_version authentication_method auth share_flag desktop_name width height +#types time string addr port addr port string string string string string bool bool string count count +1459093553.334734 CsRx2w45OKnoww6xl4 192.168.2.115 49259 192.168.2.125 5901 003 003 003 008 VNC T T root's X desktop (martin-VirtualBox:1) 1024 768 +1459093548.745805 CjhGID4nQcgTWjvg4c 192.168.2.115 49256 192.168.2.125 5901 003 003 003 008 VNC - - - - - +1459093551.559391 CCvvfg3TEfuqmmG4bh 192.168.2.115 49257 192.168.2.125 5901 003 003 003 008 VNC F - - - - +#close 2016-04-06-13-48-56 diff --git a/testing/btest/Traces/rfb/vnc-mac-to-linux.pcap b/testing/btest/Traces/rfb/vnc-mac-to-linux.pcap new file mode 100644 index 0000000000000000000000000000000000000000..3856b94caebf0764b7f7eab92fea8a8e24caffa9 GIT binary patch literal 40255 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 G-~R*9_Hix% literal 0 HcmV?d00001 diff --git a/testing/btest/Traces/rfb/vncmac.pcap b/testing/btest/Traces/rfb/vncmac.pcap new file mode 100644 index 0000000000000000000000000000000000000000..026078185de32f2f9651a6f265dc966e06795324 GIT binary patch literal 8848 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 Date: Mon, 11 Apr 2016 11:28:22 +0200 Subject: [PATCH 10/13] Implement protocol confirmation Do not set the service field in the bro script but use the protocol confirmation paradigm. Protocol is considered confirmed if both a succesful client and server banner have been parsed. --- scripts/base/protocols/rfb/main.bro | 1 - src/analyzer/protocol/rfb/rfb-analyzer.pac | 11 +++-------- 2 files changed, 3 insertions(+), 9 deletions(-) diff --git a/scripts/base/protocols/rfb/main.bro b/scripts/base/protocols/rfb/main.bro index 97f194b789..60dcd17b03 100644 --- a/scripts/base/protocols/rfb/main.bro +++ b/scripts/base/protocols/rfb/main.bro @@ -106,7 +106,6 @@ event rfb_server_version(c: connection, major_version: string, minor_version: st set_session(c); c$rfb_state$server_major_version = major_version; c$rfb_state$server_minor_version = minor_version; - add c$service["rfb"]; } event rfb_authentication_type(c: connection, authtype: count) diff --git a/src/analyzer/protocol/rfb/rfb-analyzer.pac b/src/analyzer/protocol/rfb/rfb-analyzer.pac index 4233a423f7..d357ddee28 100644 --- a/src/analyzer/protocol/rfb/rfb-analyzer.pac +++ b/src/analyzer/protocol/rfb/rfb-analyzer.pac @@ -1,5 +1,3 @@ -# Generated by binpac_quickstart - refine flow RFB_Flow += { function proc_rfb_message(msg: RFB_PDU): bool %{ @@ -7,16 +5,13 @@ refine flow RFB_Flow += { return true; %} - function proc_rfb_client_version(major: bytestring, minor: bytestring) : bool - %{ - BifEvent::generate_rfb_client_version(connection()->bro_analyzer(), connection()->bro_analyzer()->Conn(), bytestring_to_val(major), bytestring_to_val(minor)); - return true; - %} - function proc_rfb_version(client: bool, major: bytestring, minor: bytestring) : bool %{ if (client) { BifEvent::generate_rfb_client_version(connection()->bro_analyzer(), connection()->bro_analyzer()->Conn(), bytestring_to_val(major), bytestring_to_val(minor)); + + connection()->bro_analyzer()->ProtocolConfirmation(); + } else { BifEvent::generate_rfb_server_version(connection()->bro_analyzer(), connection()->bro_analyzer()->Conn(), bytestring_to_val(major), bytestring_to_val(minor)); } From 034f725f3f45bda74dadb86bb977fa0540ffb246 Mon Sep 17 00:00:00 2001 From: Martin van Hensbergen Date: Mon, 11 Apr 2016 11:35:36 +0200 Subject: [PATCH 11/13] Some styling tweaks - used transient declarations where appropriate - fixed brackets - cleaned up some comments --- scripts/base/protocols/rfb/main.bro | 60 ++++++---- src/analyzer/protocol/rfb/CMakeLists.txt | 2 - src/analyzer/protocol/rfb/Plugin.cc | 2 - src/analyzer/protocol/rfb/RFB.cc | 2 - src/analyzer/protocol/rfb/RFB.h | 2 - src/analyzer/protocol/rfb/events.bif | 2 +- src/analyzer/protocol/rfb/rfb-analyzer.pac | 128 +++++++++++---------- src/analyzer/protocol/rfb/rfb-protocol.pac | 12 +- src/analyzer/protocol/rfb/rfb.pac | 12 -- 9 files changed, 109 insertions(+), 113 deletions(-) diff --git a/scripts/base/protocols/rfb/main.bro b/scripts/base/protocols/rfb/main.bro index 60dcd17b03..50673d6514 100644 --- a/scripts/base/protocols/rfb/main.bro +++ b/scripts/base/protocols/rfb/main.bro @@ -1,4 +1,4 @@ -module Rfb; +module RFB; export { redef enum Log::ID += { LOG }; @@ -11,17 +11,27 @@ export { ## The connection's 4-tuple of endpoint addresses/ports. id: conn_id &log; + ## Major version of the client. client_major_version: string &log &optional; + ## Minor version of the client. client_minor_version: string &log &optional; + ## Major version of the server. server_major_version: string &log &optional; + ## Major version of the client. server_minor_version: string &log &optional; + ## Identifier of authentication method used. authentication_method: string &log &optional; + ## Whether or not authentication was succesful. auth: bool &log &optional; + ## Whether the client has an exclusive or a shared session. share_flag: bool &log &optional; + ## Name of the screen that is being shared. desktop_name: string &log &optional; + ## Width of the screen that is being shared. width: count &log &optional; + ## Height of the screen that is being shared. height: count &log &optional; done: bool &default=F; @@ -30,7 +40,8 @@ export { global log_rfb: event(rec: Info); } -function friendly_auth_name(auth: count): string { +function friendly_auth_name(auth: count): string + { switch (auth) { case 0: return "Invalid"; @@ -56,37 +67,40 @@ function friendly_auth_name(auth: count): string { return "Apple Remote Desktop"; } return "RealVNC"; - } - redef record connection += { rfb_state: Info &optional; }; event bro_init() &priority=5 { - Log::create_stream(Rfb::LOG, [$columns=Info, $ev=log_rfb, $path="rfb"]); + Log::create_stream(RFB::LOG, [$columns=Info, $ev=log_rfb, $path="rfb"]); } -function write_log(c:connection) { +function write_log(c:connection) + { local state = c$rfb_state; - if ( state?$done && state$done == T) { + if ( state?$done && state$done == T ) + { return; - } - Log::write(Rfb::LOG, c$rfb_state); - c$rfb_state$done = T; -} + } -function set_session(c: connection) { - if ( ! c?$rfb_state ) { + Log::write(RFB::LOG, c$rfb_state); + c$rfb_state$done = T; + } + +function set_session(c: connection) + { + if ( ! c?$rfb_state ) + { local info: Info; info$ts = network_time(); info$uid = c$uid; info$id = c$id; c$rfb_state = info; - } + } } event rfb_event(c: connection) @@ -121,13 +135,9 @@ event rfb_server_parameters(c: connection, name: string, width: count, height: c write_log(c); } -event rfb_auth_result(c: connection, result: count) +event rfb_auth_result(c: connection, result: bool) { - if ( result ==0 ) { - c$rfb_state$auth = T; - } else { - c$rfb_state$auth = F; - } + c$rfb_state$auth = !result; } event rfb_share_flag(c: connection, flag: bool) @@ -135,8 +145,10 @@ event rfb_share_flag(c: connection, flag: bool) c$rfb_state$share_flag = flag; } -event connection_state_remove(c: connection) { - if ( c?$rfb_state ) { - write_log(c); +event connection_state_remove(c: connection) + { + if ( c?$rfb_state ) + { + write_log(c); + } } -} diff --git a/src/analyzer/protocol/rfb/CMakeLists.txt b/src/analyzer/protocol/rfb/CMakeLists.txt index 8131ca7362..28523bfe2d 100644 --- a/src/analyzer/protocol/rfb/CMakeLists.txt +++ b/src/analyzer/protocol/rfb/CMakeLists.txt @@ -1,5 +1,3 @@ -# Generated by binpac_quickstart - include(BroPlugin) include_directories(BEFORE ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DIR}) diff --git a/src/analyzer/protocol/rfb/Plugin.cc b/src/analyzer/protocol/rfb/Plugin.cc index 55704497e9..b3bed0f093 100644 --- a/src/analyzer/protocol/rfb/Plugin.cc +++ b/src/analyzer/protocol/rfb/Plugin.cc @@ -1,5 +1,3 @@ -// Generated by binpac_quickstart - #include "plugin/Plugin.h" #include "RFB.h" diff --git a/src/analyzer/protocol/rfb/RFB.cc b/src/analyzer/protocol/rfb/RFB.cc index c761d0bf0f..2669d6ed56 100644 --- a/src/analyzer/protocol/rfb/RFB.cc +++ b/src/analyzer/protocol/rfb/RFB.cc @@ -1,5 +1,3 @@ -// Generated by binpac_quickstart - #include "RFB.h" #include "analyzer/protocol/tcp/TCP_Reassembler.h" diff --git a/src/analyzer/protocol/rfb/RFB.h b/src/analyzer/protocol/rfb/RFB.h index cd6e7348d0..88a17eea5a 100644 --- a/src/analyzer/protocol/rfb/RFB.h +++ b/src/analyzer/protocol/rfb/RFB.h @@ -1,5 +1,3 @@ -// Generated by binpac_quickstart - #ifndef ANALYZER_PROTOCOL_RFB_RFB_H #define ANALYZER_PROTOCOL_RFB_RFB_H diff --git a/src/analyzer/protocol/rfb/events.bif b/src/analyzer/protocol/rfb/events.bif index a3cf5f7ad8..4a5bb40121 100644 --- a/src/analyzer/protocol/rfb/events.bif +++ b/src/analyzer/protocol/rfb/events.bif @@ -15,7 +15,7 @@ event rfb_authentication_type%(c: connection, authtype: count%); ## c: The connection record for the underlying transport-layer session/flow. ## ## result: whether or not authentication was succesful -event rfb_auth_result%(c: connection, result: count%); +event rfb_auth_result%(c: connection, result: bool%); ## Generated for RFB event share flag messages ## diff --git a/src/analyzer/protocol/rfb/rfb-analyzer.pac b/src/analyzer/protocol/rfb/rfb-analyzer.pac index d357ddee28..69e8e7a99a 100644 --- a/src/analyzer/protocol/rfb/rfb-analyzer.pac +++ b/src/analyzer/protocol/rfb/rfb-analyzer.pac @@ -7,14 +7,16 @@ refine flow RFB_Flow += { function proc_rfb_version(client: bool, major: bytestring, minor: bytestring) : bool %{ - if (client) { + if (client) + { BifEvent::generate_rfb_client_version(connection()->bro_analyzer(), connection()->bro_analyzer()->Conn(), bytestring_to_val(major), bytestring_to_val(minor)); connection()->bro_analyzer()->ProtocolConfirmation(); - - } else { + } + else + { BifEvent::generate_rfb_server_version(connection()->bro_analyzer(), connection()->bro_analyzer()->Conn(), bytestring_to_val(major), bytestring_to_val(minor)); - } + } return true; %} @@ -25,28 +27,28 @@ refine flow RFB_Flow += { %} function proc_security_types(msg: RFBSecurityTypes) : bool - %{ + %{ BifEvent::generate_rfb_authentication_type(connection()->bro_analyzer(), connection()->bro_analyzer()->Conn(), ${msg.sectype}); return true; - %} + %} function proc_security_types37(msg: RFBAuthTypeSelected) : bool - %{ + %{ BifEvent::generate_rfb_authentication_type(connection()->bro_analyzer(), connection()->bro_analyzer()->Conn(), ${msg.type}); return true; - %} + %} function proc_handle_server_params(msg:RFBServerInit) : bool - %{ + %{ BifEvent::generate_rfb_server_parameters(connection()->bro_analyzer(), connection()->bro_analyzer()->Conn(), bytestring_to_val(${msg.name}), ${msg.width}, ${msg.height}); return true; - %} + %} function proc_handle_security_result(result : uint32) : bool - %{ + %{ BifEvent::generate_rfb_auth_result(connection()->bro_analyzer(), connection()->bro_analyzer()->Conn(), result); return true; - %} + %} }; refine connection RFB_Conn += { @@ -70,113 +72,115 @@ refine connection RFB_Conn += { %} function get_state(client: bool) : int - %{ + %{ return state; - %} + %} function handle_banners(client: bool, msg: RFBProtocolVersion) : bool - %{ - if ( client ) { + %{ + if ( client ) + { // Set protocol version on client's version int minor_version = bytestring_to_int(${msg.minor},10); // Apple specifies minor version "889" but talks v37 - if ( minor_version >= 7 ) { + if ( minor_version >= 7 ) state = AWAITING_SERVER_AUTH_TYPES37; - } else { + else state = AWAITING_SERVER_AUTH_TYPES; } - } else { - if ( !client ) { + else state = AWAITING_CLIENT_BANNER; - } - } + return true; - %} + %} function handle_ard_challenge() : bool - %{ + %{ state = AWAITING_CLIENT_ARD_RESPONSE; return true; - %} + %} function handle_ard_response() : bool - %{ + %{ state = AWAITING_SERVER_AUTH_RESULT; return true; - %} + %} function handle_auth_request() : bool - %{ + %{ state = AWAITING_CLIENT_RESPONSE; return true; - %} + %} function handle_auth_response() : bool - %{ + %{ state = AWAITING_SERVER_AUTH_RESULT; return true; - %} + %} function handle_security_result(msg: RFBSecurityResult) : bool - %{ - if ( ${msg.result} == 0 ) //FIXME - { + %{ + if ( ${msg.result} == 0 ) + { state = AWAITING_CLIENT_SHARE_FLAG; - } + } return true; - %} + %} function handle_client_init(msg: RFBClientInit) : bool - %{ + %{ state = AWAITING_SERVER_PARAMS; - return true; - %} + %} function handle_server_init(msg: RFBServerInit) : bool - %{ + %{ state = RFB_MESSAGE; return true; - %} + %} function handle_security_types(msg: RFBSecurityTypes): bool - %{ - if ( msg->sectype() == 0 ) { // No auth + %{ + if ( msg->sectype() == 0 ) + { // No auth state = AWAITING_CLIENT_SHARE_FLAG; return true; - } - if ( msg->sectype() == 2 ) { //VNC + } + + if ( msg->sectype() == 2 ) + { //VNC state = AWAITING_SERVER_CHALLENGE; - } - return false; - %} + } + return true; + %} function handle_security_types37(msg: RFBSecurityTypes37): bool - %{ - if ( ${msg.count} == 0 ) { // No auth + %{ + if ( ${msg.count} == 0 ) + { // No auth state = AWAITING_CLIENT_SHARE_FLAG; return true; - } + } state = AWAITING_CLIENT_AUTH_TYPE_SELECTED37; return true; - %} + %} function handle_auth_type_selected(msg: RFBAuthTypeSelected): bool - %{ - if ( ${msg.type} == 30 ) { // Apple Remote Desktop - state = AWAITING_SERVER_ARD_CHALLENGE; - return true; - } + %{ + if ( ${msg.type} == 30 ) + { // Apple Remote Desktop + state = AWAITING_SERVER_ARD_CHALLENGE; + return true; + } - if ( ${msg.type} == 1 ) { // No Auth + if ( ${msg.type} == 1 ) state = AWAITING_SERVER_AUTH_RESULT; - } else { - // Assume VNC + else state = AWAITING_SERVER_CHALLENGE; - } + return true; - %} + %} %member{ uint8 state = AWAITING_SERVER_BANNER; diff --git a/src/analyzer/protocol/rfb/rfb-protocol.pac b/src/analyzer/protocol/rfb/rfb-protocol.pac index 0eb5542001..764046e747 100644 --- a/src/analyzer/protocol/rfb/rfb-protocol.pac +++ b/src/analyzer/protocol/rfb/rfb-protocol.pac @@ -16,8 +16,8 @@ enum states { }; type RFBProtocolVersion (client: bool) = record { - header : "RFB "; - major :bytestring &length=3; + header: "RFB "; + major: bytestring &length=3; dot: "."; minor: bytestring &length=3; pad: uint8; @@ -108,8 +108,8 @@ type RFB_PDU_request = record { AWAITING_CLIENT_SHARE_FLAG -> shareflag: RFBClientInit; AWAITING_CLIENT_AUTH_TYPE_SELECTED37 -> authtype: RFBAuthTypeSelected; AWAITING_CLIENT_ARD_RESPONSE -> ard_response: RFBSecurityARDResponse; - RFB_MESSAGE -> ignore: bytestring &restofdata; - default -> data: bytestring &restofdata; + RFB_MESSAGE -> ignore: bytestring &restofdata &transient; + default -> data: bytestring &restofdata &transient; } &requires(state); } &let { state: uint8 = $context.connection.get_state(true); @@ -124,8 +124,8 @@ type RFB_PDU_response = record { AWAITING_SERVER_AUTH_RESULT -> authresult : RFBSecurityResult; AWAITING_SERVER_ARD_CHALLENGE -> ard_challenge: RFBSecurityARDChallenge; AWAITING_SERVER_PARAMS -> serverinit: RFBServerInit; - RFB_MESSAGE -> ignore: bytestring &restofdata; - default -> data: bytestring &restofdata; + RFB_MESSAGE -> ignore: bytestring &restofdata &transient; + default -> data: bytestring &restofdata &transient; } &requires(rstate); } &let { rstate: uint8 = $context.connection.get_state(false); diff --git a/src/analyzer/protocol/rfb/rfb.pac b/src/analyzer/protocol/rfb/rfb.pac index 310ad38893..2e88f8e5bb 100644 --- a/src/analyzer/protocol/rfb/rfb.pac +++ b/src/analyzer/protocol/rfb/rfb.pac @@ -1,5 +1,3 @@ -# Generated by binpac_quickstart - # Analyzer for Parser for rfb (VNC) # - rfb-protocol.pac: describes the rfb protocol messages # - rfb-analyzer.pac: describes the rfb analyzer code @@ -26,17 +24,7 @@ connection RFB_Conn(bro_analyzer: BroAnalyzer) { # Now we define the flow: flow RFB_Flow(is_orig: bool) { - - # ## TODO: Determine if you want flowunit or datagram parsing: - - # Using flowunit will cause the anlayzer to buffer incremental input. - # This is needed for &oneline and &length. If you don't need this, you'll - # get better performance with datagram. - - # flowunit = RFB_PDU(is_orig) withcontext(connection, this); - datagram = RFB_PDU(is_orig) withcontext(connection, this); - }; %include rfb-analyzer.pac \ No newline at end of file From 000540645dfc406074d2a2098418711348b98079 Mon Sep 17 00:00:00 2001 From: Martin van Hensbergen Date: Mon, 11 Apr 2016 11:37:50 +0200 Subject: [PATCH 12/13] Fixed issue in state machine There is a slight difference in the message sequence between version 3.7 and 3.8. Version 3.8 will always send a Authentication Result message when authentication type 'None' is selected while 3.7 does not. --- src/analyzer/protocol/rfb/rfb-analyzer.pac | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/analyzer/protocol/rfb/rfb-analyzer.pac b/src/analyzer/protocol/rfb/rfb-analyzer.pac index 69e8e7a99a..b63b9f4085 100644 --- a/src/analyzer/protocol/rfb/rfb-analyzer.pac +++ b/src/analyzer/protocol/rfb/rfb-analyzer.pac @@ -82,6 +82,7 @@ refine connection RFB_Conn += { { // Set protocol version on client's version int minor_version = bytestring_to_int(${msg.minor},10); + version = minor_version; // Apple specifies minor version "889" but talks v37 if ( minor_version >= 7 ) @@ -175,7 +176,12 @@ refine connection RFB_Conn += { } if ( ${msg.type} == 1 ) - state = AWAITING_SERVER_AUTH_RESULT; + { + if ( version > 7 ) + state = AWAITING_SERVER_AUTH_RESULT; + else + state = AWAITING_CLIENT_SHARE_FLAG; + } else state = AWAITING_SERVER_CHALLENGE; @@ -184,6 +190,7 @@ refine connection RFB_Conn += { %member{ uint8 state = AWAITING_SERVER_BANNER; + int version = 0; %} }; From adcc978f14faa1c3a2df555da8ad5ff2c15bf6c8 Mon Sep 17 00:00:00 2001 From: Seth Hall Date: Wed, 13 Apr 2016 00:44:02 -0400 Subject: [PATCH 13/13] Add a file entropy test. --- .../scripts.base.files.entropy.basic/.stdout | 1 + testing/btest/scripts/base/files/entropy/basic.test | 13 +++++++++++++ 2 files changed, 14 insertions(+) create mode 100644 testing/btest/Baseline/scripts.base.files.entropy.basic/.stdout create mode 100644 testing/btest/scripts/base/files/entropy/basic.test diff --git a/testing/btest/Baseline/scripts.base.files.entropy.basic/.stdout b/testing/btest/Baseline/scripts.base.files.entropy.basic/.stdout new file mode 100644 index 0000000000..0682a357e8 --- /dev/null +++ b/testing/btest/Baseline/scripts.base.files.entropy.basic/.stdout @@ -0,0 +1 @@ +[entropy=4.950189, chi_square=63750.814665, mean=80.496493, monte_carlo_pi=4.0, serial_correlation=0.395907] diff --git a/testing/btest/scripts/base/files/entropy/basic.test b/testing/btest/scripts/base/files/entropy/basic.test new file mode 100644 index 0000000000..2b867eb8cb --- /dev/null +++ b/testing/btest/scripts/base/files/entropy/basic.test @@ -0,0 +1,13 @@ +# @TEST-EXEC: bro -r $TRACES/http/get.trace %INPUT +# @TEST-EXEC: btest-diff .stdout + + +event file_new(f: fa_file) + { + Files::add_analyzer(f, Files::ANALYZER_ENTROPY); + } + +event file_entropy(f: fa_file, ent: entropy_test_result) + { + print ent; + } \ No newline at end of file