├── meterpreter.bro └── smb-ransomware ├── README.md └── smb-ransomware.bro /meterpreter.bro: -------------------------------------------------------------------------------- 1 | ##! meterpreter.bro 2 | ##! 3 | ##! Bro-IDS policy to detect Metasploit's meterpreter payload transfer 4 | ##! Note that it does not detect payload transfers over SSL 5 | ##! 6 | ##! Fox-IT 7 | ##! Security Research Team 8 | ##! 9 | ##! https://github.com/fox-it/bro-scripts 10 | 11 | @load base/frameworks/notice 12 | 13 | export { 14 | redef enum Notice::Type += { 15 | Metasploit::Meterpreter, 16 | }; 17 | 18 | redef record connection += { 19 | meterpreter_payload_size: count &optional; 20 | }; 21 | } 22 | 23 | event tcp_packet(c: connection, is_orig: bool, flags: string, 24 | seq: count, ack: count, len: count, payload: string) 25 | { 26 | if(|payload| == 4 && seq == 1) 27 | { 28 | c$meterpreter_payload_size = bytestring_to_count(payload, T); 29 | } 30 | else if (c?$meterpreter_payload_size && seq == 1 && flags == "AP" && ack > 5) 31 | { 32 | if (c$meterpreter_payload_size == ack-5) 33 | { 34 | #print( fmt("%DT: Possible Meterpreter Payload transfered! %s:%s -> %s:%s", 35 | # c$start_time, c$id$resp_h, c$id$resp_p, c$id$orig_h, c$id$orig_p)); 36 | NOTICE([$note=Metasploit::Meterpreter, $conn=c, $msg=fmt("Possible Meterpreter Payload transfered!")]); 37 | } 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /smb-ransomware/README.md: -------------------------------------------------------------------------------- 1 | # Bro ransomware 2 | Bro policy for ransomware detection over SMB2. 3 | 4 | ## Entropy 5 | By calculating the entropy of the data that is being send in the first write-request, the policy is able to determine if a file has been encrypted. 6 | 7 | ## Detected Ransomware 8 | - Locky 9 | - Cryptowall 10 | - CTBLocker 11 | - Jigsaw 12 | - Mobef 13 | - Shade 14 | - Maktub 15 | - Cerber/Alpha 16 | - Teslacrypt 17 | - Rokku 18 | 19 | 20 | TODO test: 21 | - Wildfire 22 | -------------------------------------------------------------------------------- /smb-ransomware/smb-ransomware.bro: -------------------------------------------------------------------------------- 1 | @load base/frameworks/files 2 | @load base/protocols/smb 3 | @load base/frameworks/notice 4 | @load base/frameworks/sumstats 5 | 6 | global fuidmap : set[string]; 7 | 8 | module FoxCryptoRansom; 9 | 10 | export { 11 | redef enum Notice::Type += { 12 | ## Notice corresponding to a possible ransomware attack 13 | RANSOMWARE_SMB 14 | }; 15 | 16 | ## Entropy check on the first packet send 17 | const enc_off = 0 &redef; 18 | 19 | ## Entropy check on certain bytes 20 | const enc_sdata = 0 &redef; 21 | const enc_edata = 1000 &redef; 22 | 23 | ## Entropy and Mean corresponding to a possible ransomware attack 24 | const enc_entropy = 7.5 &redef; 25 | const enc_mean = 125 &redef; 26 | 27 | ## Notice values corresponding to a possible ransomware attack 28 | const threshold_time = 30sec &redef; 29 | const threshold_limit = 5.0 &redef; 30 | 31 | ## Ignore list for certain filenames 32 | const ignore_list = /GoogleChrome/ &redef; 33 | 34 | redef enum Log::ID += {LOG}; 35 | type Info: record { 36 | ts: time &log; 37 | filename: string &log; 38 | entropy: double &log; 39 | mean: double &log; 40 | }; 41 | } 42 | 43 | event chunk_event (f: fa_file, data: string, off: count) 44 | { 45 | if ( off == enc_off ) { 46 | local fox_entropy = find_entropy(data[enc_sdata:enc_edata]); 47 | if ( fox_entropy$entropy >= enc_entropy && fox_entropy$mean >= enc_mean ) { 48 | 49 | SumStats::observe("SMB traffic detected", SumStats::Key(), SumStats::Observation($num=1)); 50 | 51 | local rec: FoxCryptoRansom::Info = [ $ts=network_time(), $filename = f$info$filename, $entropy=fox_entropy$entropy, $mean=fox_entropy$mean ]; 52 | Log::write(FoxCryptoRansom::LOG, rec); 53 | } 54 | } 55 | } 56 | 57 | 58 | event file_over_new_connection(f: fa_file, c: connection, is_orig: bool) 59 | { 60 | if (f$source == "SMB"){ 61 | 62 | local filename = "UNKNOWN"; 63 | 64 | if (f$info?$filename){ 65 | filename = f$info$filename; 66 | } 67 | 68 | local mime_type = "UNKNOWN"; 69 | 70 | if (f$info?$mime_type){ 71 | mime_type = f$info$mime_type; 72 | } 73 | 74 | if (mime_type == "UNKNOWN"){ 75 | 76 | if (ignore_list in filename){ 77 | return; 78 | }else{ 79 | 80 | if ( ! c$smb_state$current_file?$action){ 81 | return ; 82 | }else{ 83 | 84 | if (c$smb_state$current_file$action == SMB::FILE_WRITE){ 85 | local fuid = c$smb_state$current_file$fuid; 86 | 87 | if (fuid !in fuidmap){ 88 | Files::add_analyzer(f, Files::ANALYZER_DATA_EVENT, Files::AnalyzerArgs($chunk_event=chunk_event)); 89 | add fuidmap[fuid]; 90 | } 91 | }else{ 92 | } 93 | } 94 | } 95 | } 96 | } 97 | } 98 | 99 | event bro_init() 100 | { 101 | local r1 = SumStats::Reducer($stream="SMB traffic detected", 102 | $apply=set(SumStats::SUM)); 103 | 104 | SumStats::create([$name = "Ransomware detection", 105 | $epoch = threshold_time, 106 | $reducers = set(r1), 107 | $threshold = threshold_limit, 108 | $threshold_val(key: SumStats::Key, result: SumStats::Result) = 109 | { 110 | return result["SMB traffic detected"]$sum; 111 | }, 112 | $threshold_crossed(key: SumStats::Key, result: SumStats::Result) = 113 | { 114 | NOTICE([$note=RANSOMWARE_SMB, 115 | $msg="Ransomware encrypting share detected"]); 116 | }]); 117 | 118 | Log::create_stream(FoxCryptoRansom::LOG, [$columns=Info, $path="entropy"]); 119 | } 120 | --------------------------------------------------------------------------------