├── CMakeLists.txt ├── Plugin.cc ├── README.md ├── broyara.cc ├── broyara.h └── events.bif /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | include(BroPlugin) 2 | 3 | include_directories(BEFORE ${CMAKE_CURRENT_SOURCE_DIR} 4 | ${CMAKE_CURRENT_BINARY_DIR} 5 | "/yara-3.2.0/libyara/include" 6 | ) 7 | 8 | 9 | 10 | 11 | 12 | 13 | bro_plugin_begin(Bro FileYara) 14 | bro_plugin_cc(broyara.cc Plugin.cc ../../Analyzer.cc) 15 | bro_plugin_bif(events.bif) 16 | bro_plugin_end() 17 | -------------------------------------------------------------------------------- /Plugin.cc: -------------------------------------------------------------------------------- 1 | // See the file in the main distribution directory for copyright. 2 | 3 | #include "plugin/Plugin.h" 4 | #include 5 | #include "broyara.h" 6 | 7 | namespace plugin { 8 | namespace Bro_FileYara { 9 | 10 | class Plugin : public plugin::Plugin { 11 | public: 12 | plugin::Configuration Configure() 13 | { 14 | 15 | AddComponent(new ::file_analysis::Component("YARA", ::file_analysis::Yara::Instantiate)); 16 | plugin::Configuration config; 17 | config.name = "Bro::FileYara"; 18 | config.description = "Yara file content scanner"; 19 | return config; 20 | 21 | 22 | } 23 | 24 | } plugin; 25 | 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | broyara 2 | ======= 3 | 4 | integrating bro into yara 5 | 6 | I assume yara as been installed into `/usr/local/lib/`. 7 | 8 | From the default bro source code (git cloned) add the following to `src/file_analysis/CMakeLists.txt` 9 | 10 | ``` 11 | add_subdirectory(data_event) 12 | add_subdirectory(extract) 13 | add_subdirectory(hash) 14 | add_subdirectory(yara) 15 | add_subdirectory(unified2) 16 | add_subdirectory(x509) 17 | ``` 18 | 19 | I've also amended src/CMakeLists file 20 | 21 | ``` 22 | if ( bro_HAVE_OBJECT_LIBRARIES ) 23 | add_executable(bro ${bro_SRCS} ${bro_HEADERS} ${bro_SUBDIRS}) 24 | target_link_libraries(bro ${brodeps} ${CMAKE_THREAD_LIBS_INIT} ${CMAKE_DL_LIBS} yara) 25 | else () 26 | add_executable(bro ${bro_SRCS} ${bro_HEADERS}) 27 | target_link_libraries(bro ${bro_SUBDIRS} ${brodeps} ${CMAKE_THREAD_LIBS_INIT} ${CMAKE_DL_LIBS} yara) 28 | endif () 29 | ``` 30 | You can run the yara rule analyser with a bro file like such - we assume the rule file is compiled: 31 | ``` 32 | redef record Files::AnalyzerArgs += 33 | { 34 | yara_rules_file: string &optional; 35 | }; 36 | 37 | event file_new(f: fa_file) 38 | { 39 | Files::add_analyzer(f, Files::ANALYZER_YARA,[$yara_rules_file="/path/to/test.rule_c"]); 40 | } 41 | 42 | 43 | 44 | event file_yaraalert(f: fa_file, rule_name: string) 45 | { 46 | print "file_yara_alert ", f$id," ", rule_name; 47 | } 48 | 49 | ``` 50 | gives the output: 51 | ``` 52 | $ bro -r ~/data/pcap/intel.pcap broscipts/yara_tst.bro 53 | file_yara_alert , FqIk1M1mN4bdnsNK46, , silent_banker 54 | file_yara_alert , FxxvP43nXcYzL16gS6, , silent_banker 55 | file_yara_alert , FhKaLp4VGYlFgz0cj, , silent_banker 56 | file_yara_alert , FYWSmEkdLooAtsOd9, , silent_banker 57 | file_yara_alert , FC58QqHDkh3Z5ZCw, , silent_banker 58 | file_yara_alert , FFoGa51pLHJCHF68B, , silent_banker 59 | file_yara_alert , FfArYal4ANngQl0de, , silent_banker 60 | file_yara_alert , FGyLsu3kMoquT6RZda, , silent_banker 61 | 1417869923.470556 warning in /usr/local/bro/share/bro/base/misc/find-checksum-offloading.bro, line 54: Your trace file likely has invalid TCP checksums, most likely from NIC checksum offloading. 62 | file_yara_alert , F2PvdW1d2ZwYk6B0q9, , silent_banker 63 | file_yara_alert , FDWZJXmIc88eUN91i, , silent_banker 64 | file_yara_alert , F2PvdW1d2ZwYk6B0q9, , silent_banker 65 | file_yara_alert , FtULZK1hRBg008up1f, , silent_banker 66 | file_yara_alert , FJX6Dk435K8Xe05kp5, , silent_banker 67 | ``` 68 | 69 | 70 | 71 | -------------------------------------------------------------------------------- /broyara.cc: -------------------------------------------------------------------------------- 1 | // See the file "COPYING" in the main distribution directory for copyright. 2 | 3 | #include 4 | #include 5 | 6 | #include "broyara.h" 7 | #include "util.h" 8 | #include "Event.h" 9 | #include "file_analysis/Manager.h" 10 | 11 | using namespace file_analysis; 12 | 13 | 14 | int callback_function( 15 | int message, 16 | void* message_data, 17 | void* user_data) { 18 | 19 | if (0 == user_data) { 20 | return 1; 21 | } 22 | 23 | Yara* yara_callback_obj = static_cast(user_data); 24 | yara_callback_obj->raiseEvent(message,message_data); 25 | 26 | return ERROR_SUCCESS; // what are you meant to return from a callback function?? 27 | 28 | } 29 | 30 | Yara::Yara(RecordVal* args, File* file, const char* arg_kind) 31 | : file_analysis::Analyzer( 32 | file_mgr->GetComponentTag(to_upper(arg_kind).c_str()), 33 | args, 34 | file), 35 | fed(false), 36 | yr_rules_(0) 37 | { 38 | if (ERROR_SUCCESS != yr_initialize()) { 39 | throw "unable to initialize yara"; 40 | } 41 | 42 | const u_char* str1 = args->Lookup("yara_rules_file")->AsStringVal()->Bytes(); 43 | const char* rules_file_name = (const char*) str1;//" 44 | 45 | 46 | if (ERROR_SUCCESS != yr_rules_load(rules_file_name,&yr_rules_)) { 47 | throw "unable to load yara rules"; 48 | } 49 | 50 | 51 | } 52 | 53 | Yara::~Yara() 54 | { 55 | if (0 != yr_rules_) { 56 | yr_rules_destroy(yr_rules_); 57 | } 58 | yr_finalize(); 59 | } 60 | 61 | bool Yara::DeliverStream(const u_char* data, uint64 len) 62 | { 63 | ostream_.write((const char *) data,len); 64 | return true; 65 | } 66 | 67 | bool Yara::EndOfFile() 68 | { 69 | Finalize(); 70 | } 71 | 72 | bool Yara::Undelivered(uint64 offset, uint64 len) 73 | { 74 | return false; 75 | } 76 | 77 | void Yara::Finalize() 78 | { 79 | 80 | if (!ostream_) { 81 | return; 82 | } 83 | 84 | std::string result_file = ostream_.str(); 85 | 86 | if (0 == result_file.size()) { 87 | return; 88 | } 89 | 90 | 91 | int res = yr_rules_scan_mem( 92 | yr_rules_, 93 | (uint8_t *) result_file.c_str(), 94 | result_file.size(), 95 | SCAN_FLAGS_FAST_MODE, 96 | callback_function, 97 | this, 98 | 0 // flags 99 | ); 100 | 101 | if (ERROR_SUCCESS != res) { 102 | //TODO: bro event?? 103 | return; 104 | } 105 | 106 | 107 | } 108 | 109 | 110 | void Yara::raiseEvent( 111 | int message, 112 | void* message_data) 113 | { 114 | 115 | 116 | if (CALLBACK_MSG_RULE_MATCHING != message) { 117 | return; 118 | } 119 | 120 | if (0 == message_data) { 121 | return; 122 | } 123 | 124 | if (0 != file_yaraalert) { 125 | 126 | val_list* vl = new val_list(); 127 | vl->append(GetFile()->GetVal()->Ref()); 128 | 129 | YR_RULE* yrrule = static_cast(message_data); 130 | vl->append(new StringVal(yrrule->identifier)); 131 | mgr.QueueEvent(file_yaraalert, vl); 132 | 133 | } 134 | 135 | 136 | 137 | 138 | } 139 | 140 | -------------------------------------------------------------------------------- /broyara.h: -------------------------------------------------------------------------------- 1 | // See the file "COPYING" in the main distribution directory for copyright. 2 | 3 | #ifndef FILE_ANALYSIS_HASH_H 4 | #define FILE_ANALYSIS_HASH_H 5 | 6 | #include 7 | #include 8 | #include "Val.h" 9 | #include "OpaqueVal.h" 10 | #include "File.h" 11 | #include "Analyzer.h" 12 | 13 | #include "events.bif.h" 14 | 15 | #include 16 | 17 | namespace file_analysis { 18 | 19 | /** 20 | * An analyzer to produce a hash of file contents. 21 | */ 22 | class Yara : public file_analysis::Analyzer { 23 | public: 24 | 25 | /** 26 | * Destructor. 27 | */ 28 | virtual ~Yara(); 29 | 30 | /** 31 | * Incrementally hash next chunk of file contents. 32 | * @param data pointer to start of a chunk of a file data. 33 | * @param len number of bytes in the data chunk. 34 | * @return false if the digest is in an invalid state, else true. 35 | */ 36 | virtual bool DeliverStream(const u_char* data, uint64 len); 37 | 38 | /** 39 | * Finalizes the hash and raises a "file_hash" event. 40 | * @return always false so analyze will be deteched from file. 41 | */ 42 | virtual bool EndOfFile(); 43 | 44 | /** 45 | * Missing data can't be handled, so just indicate the this analyzer should 46 | * be removed from receiving further data. The hash will not be finalized. 47 | * @param offset byte offset in file at which missing chunk starts. 48 | * @param len number of missing bytes. 49 | * @return always false so analyzer will detach from file. 50 | */ 51 | virtual bool Undelivered(uint64 offset, uint64 len); 52 | 53 | static file_analysis::Analyzer* Instantiate(RecordVal* args, File* file) 54 | { 55 | return new Yara(args,file,"yara"); 56 | // return file_yarahash ? new YARA(args, file) : 0; 57 | } 58 | 59 | 60 | void raiseEvent(int message,void* message_data); 61 | 62 | 63 | protected: 64 | 65 | /** 66 | * Constructor. 67 | * @param args the \c AnalyzerArgs value which represents the analyzer. 68 | * @param file the file to which the analyzer will be attached. 69 | * @param hv specific hash calculator object. 70 | * @param kind human readable name of the hash algorithm to use. 71 | */ 72 | Yara(RecordVal* args, File* file, const char* kind); 73 | 74 | /** 75 | * If some file contents have been seen, finalizes the hash of them and 76 | * raises the "file_hash" event with the results. 77 | */ 78 | void Finalize(); 79 | 80 | private: 81 | YR_RULES* yr_rules_; 82 | std::ostringstream ostream_; 83 | bool fed; 84 | const char* kind; 85 | }; 86 | 87 | 88 | 89 | 90 | 91 | } // namespace file_analysis 92 | 93 | #endif 94 | -------------------------------------------------------------------------------- /events.bif: -------------------------------------------------------------------------------- 1 | 2 | event file_yaraalert%(f: fa_file, rule_name: string%); 3 | --------------------------------------------------------------------------------