SMB: fix number of small issues.

Changes:
* change virtual to override where appropriate
* analyzer triggered assert in debug mode because it did not call Done()
  on manually instantiated analyzers.
* added a few length checks to methods
* commented unused code and removed a few unused class members
This commit is contained in:
Johanna Amann 2016-06-20 14:53:48 -07:00
parent 0e49b9ef98
commit be92821a69
14 changed files with 75 additions and 65 deletions

View file

@ -37,7 +37,7 @@ void DCE_RPC_Analyzer::EndpointEOF(bool is_orig)
TCP_ApplicationAnalyzer::EndpointEOF(is_orig); TCP_ApplicationAnalyzer::EndpointEOF(is_orig);
interp->FlowEOF(is_orig); interp->FlowEOF(is_orig);
} }
void DCE_RPC_Analyzer::Undelivered(uint64 seq, int len, bool orig) void DCE_RPC_Analyzer::Undelivered(uint64 seq, int len, bool orig)
{ {
TCP_ApplicationAnalyzer::Undelivered(seq, len, orig); TCP_ApplicationAnalyzer::Undelivered(seq, len, orig);
@ -49,7 +49,7 @@ void DCE_RPC_Analyzer::DeliverStream(int len, const u_char* data, bool orig)
TCP_ApplicationAnalyzer::DeliverStream(len, data, orig); TCP_ApplicationAnalyzer::DeliverStream(len, data, orig);
assert(TCP()); assert(TCP());
try try
{ {
interp->NewData(orig, data, data + len); interp->NewData(orig, data, data + len);
} }

View file

@ -16,7 +16,7 @@
namespace analyzer { namespace dce_rpc { namespace analyzer { namespace dce_rpc {
class UUID { /* class UUID {
public: public:
UUID(); UUID();
UUID(const u_char data[16]); UUID(const u_char data[16]);
@ -75,7 +75,7 @@ struct dce_rpc_endpoint_addr {
return string(buf); return string(buf);
} }
}; }; */
/* /*
enum DCE_RPC_PTYPE { enum DCE_RPC_PTYPE {
@ -180,10 +180,10 @@ public:
DCE_RPC_Analyzer(Connection* conn); DCE_RPC_Analyzer(Connection* conn);
~DCE_RPC_Analyzer(); ~DCE_RPC_Analyzer();
virtual void Done(); void Done() override;
virtual void DeliverStream(int len, const u_char* data, bool orig); void DeliverStream(int len, const u_char* data, bool orig) override;
virtual void Undelivered(uint64 seq, int len, bool orig); void Undelivered(uint64 seq, int len, bool orig) override;
virtual void EndpointEOF(bool is_orig); void EndpointEOF(bool is_orig) override;
bool SetFileID(uint64 fid_in) bool SetFileID(uint64 fid_in)
{ interp->set_file_id(fid_in); return true; } { interp->set_file_id(fid_in); return true; }
@ -195,6 +195,6 @@ protected:
binpac::DCE_RPC::DCE_RPC_Conn* interp; binpac::DCE_RPC::DCE_RPC_Conn* interp;
}; };
} } // namespace analyzer::* } } // namespace analyzer::*
#endif /* dce_rpc_h */ #endif /* dce_rpc_h */

View file

@ -13,7 +13,6 @@ public:
plugin::Configuration Configure() plugin::Configuration Configure()
{ {
AddComponent(new ::analyzer::Component("DCE_RPC", ::analyzer::dce_rpc::DCE_RPC_Analyzer::Instantiate)); AddComponent(new ::analyzer::Component("DCE_RPC", ::analyzer::dce_rpc::DCE_RPC_Analyzer::Instantiate));
//AddComponent(new ::analyzer::Component("Contents_DCE_RPC", 0));
plugin::Configuration config; plugin::Configuration config;
config.name = "Bro::DCE_RPC"; config.name = "Bro::DCE_RPC";

View file

@ -19,13 +19,13 @@ public:
virtual ~GSSAPI_Analyzer(); virtual ~GSSAPI_Analyzer();
// Overriden from Analyzer. // Overriden from Analyzer.
virtual void Done(); void Done() override;
virtual void DeliverStream(int len, const u_char* data, bool orig); void DeliverStream(int len, const u_char* data, bool orig) override;
virtual void Undelivered(uint64 seq, int len, bool orig); void Undelivered(uint64 seq, int len, bool orig) override;
// Overriden from tcp::TCP_ApplicationAnalyzer. // Overriden from tcp::TCP_ApplicationAnalyzer.
virtual void EndpointEOF(bool is_orig); void EndpointEOF(bool is_orig) override;
static analyzer::Analyzer* Instantiate(Connection* conn) static analyzer::Analyzer* Instantiate(Connection* conn)
{ return new GSSAPI_Analyzer(conn); } { return new GSSAPI_Analyzer(conn); }

View file

@ -10,7 +10,10 @@ refine connection GSSAPI_Conn += {
%cleanup{ %cleanup{
if ( ntlm ) if ( ntlm )
{
ntlm->Done();
delete ntlm; delete ntlm;
}
%} %}
function forward_ntlm(data: bytestring, is_orig: bool): bool function forward_ntlm(data: bytestring, is_orig: bool): bool

View file

@ -124,7 +124,7 @@ public:
NetbiosSSN_State State() const { return state; } NetbiosSSN_State State() const { return state; }
protected: protected:
virtual void DeliverStream(int len, const u_char* data, bool orig); void DeliverStream(int len, const u_char* data, bool orig) override;
NetbiosSSN_Interpreter* interp; NetbiosSSN_Interpreter* interp;
@ -144,17 +144,17 @@ public:
NetbiosSSN_Analyzer(Connection* conn); NetbiosSSN_Analyzer(Connection* conn);
~NetbiosSSN_Analyzer(); ~NetbiosSSN_Analyzer();
virtual void Done(); void Done() override;
virtual void DeliverPacket(int len, const u_char* data, bool orig, void DeliverPacket(int len, const u_char* data, bool orig,
uint64 seq, const IP_Hdr* ip, int caplen); uint64 seq, const IP_Hdr* ip, int caplen) override;
static analyzer::Analyzer* Instantiate(Connection* conn) static analyzer::Analyzer* Instantiate(Connection* conn)
{ return new NetbiosSSN_Analyzer(conn); } { return new NetbiosSSN_Analyzer(conn); }
protected: protected:
virtual void ConnectionClosed(tcp::TCP_Endpoint* endpoint, void ConnectionClosed(tcp::TCP_Endpoint* endpoint,
tcp::TCP_Endpoint* peer, int gen_event); tcp::TCP_Endpoint* peer, int gen_event) override;
virtual void EndpointEOF(bool is_orig); void EndpointEOF(bool is_orig) override;
void ExpireTimer(double t); void ExpireTimer(double t);
@ -168,6 +168,6 @@ protected:
// FIXME: Doesn't really fit into new analyzer structure. What to do? // FIXME: Doesn't really fit into new analyzer structure. What to do?
int IsReuse(double t, const u_char* pkt); int IsReuse(double t, const u_char* pkt);
} } // namespace analyzer::* } } // namespace analyzer::*
#endif #endif

View file

@ -19,13 +19,13 @@ public:
virtual ~NTLM_Analyzer(); virtual ~NTLM_Analyzer();
// Overriden from Analyzer. // Overriden from Analyzer.
virtual void Done(); void Done() override;
virtual void DeliverStream(int len, const u_char* data, bool orig); void DeliverStream(int len, const u_char* data, bool orig) override;
virtual void Undelivered(uint64 seq, int len, bool orig); void Undelivered(uint64 seq, int len, bool orig) override;
// Overriden from tcp::TCP_ApplicationAnalyzer. // Overriden from tcp::TCP_ApplicationAnalyzer.
virtual void EndpointEOF(bool is_orig); void EndpointEOF(bool is_orig) override;
static analyzer::Analyzer* Instantiate(Connection* conn) static analyzer::Analyzer* Instantiate(Connection* conn)
{ return new NTLM_Analyzer(conn); } { return new NTLM_Analyzer(conn); }

View file

@ -6,10 +6,10 @@ refine connection NTLM_Conn += {
%{ %{
double secs = (ts / 10000000.0); double secs = (ts / 10000000.0);
// Bro can't support times back to the 1600's // Bro can't support times back to the 1600's
// so we subtract a lot of seconds. // so we subtract a lot of seconds.
Val* bro_ts = new Val(secs - 11644473600.0, TYPE_TIME); Val* bro_ts = new Val(secs - 11644473600.0, TYPE_TIME);
return bro_ts; return bro_ts;
%} %}

View file

@ -33,7 +33,7 @@ void SMB_Analyzer::EndpointEOF(bool is_orig)
TCP_ApplicationAnalyzer::EndpointEOF(is_orig); TCP_ApplicationAnalyzer::EndpointEOF(is_orig);
interp->FlowEOF(is_orig); interp->FlowEOF(is_orig);
} }
void SMB_Analyzer::Undelivered(uint64 seq, int len, bool orig) void SMB_Analyzer::Undelivered(uint64 seq, int len, bool orig)
{ {
TCP_ApplicationAnalyzer::Undelivered(seq, len, orig); TCP_ApplicationAnalyzer::Undelivered(seq, len, orig);
@ -46,10 +46,10 @@ void SMB_Analyzer::DeliverStream(int len, const u_char* data, bool orig)
assert(TCP()); assert(TCP());
try try
{ {
interp->NewData(orig, data, data + len); interp->NewData(orig, data, data + len);
// Let's assume that if there are no binpac exceptions after // Let's assume that if there are no binpac exceptions after
// 3 data chunks that this is probably actually SMB. // 3 data chunks that this is probably actually SMB.
if ( chunks >= 3 ) if ( chunks >= 3 )
ProtocolConfirmation(); ProtocolConfirmation();
@ -93,8 +93,11 @@ void Contents_SMB::Undelivered(uint64 seq, int len, bool orig)
NeedResync(); NeedResync();
} }
bool Contents_SMB::HasSMBHeader(const u_char* data) bool Contents_SMB::HasSMBHeader(int len, const u_char* data)
{ {
if ( len < 8 )
return false;
return (strncmp((const char*) data+4, "\xffSMB", 4) == 0 || return (strncmp((const char*) data+4, "\xffSMB", 4) == 0 ||
strncmp((const char*) data+4, "\xfeSMB", 4) == 0); strncmp((const char*) data+4, "\xfeSMB", 4) == 0);
} }
@ -102,12 +105,16 @@ bool Contents_SMB::HasSMBHeader(const u_char* data)
void Contents_SMB::DeliverSMB(int len, const u_char* data) void Contents_SMB::DeliverSMB(int len, const u_char* data)
{ {
// Check the 4-byte header. // Check the 4-byte header.
if ( ! HasSMBHeader(data) ) if ( ! HasSMBHeader(len, data) )
{ {
Conn()->Weird(fmt("SMB-over-TCP header error: %02x %05x, >>\\x%02x%c%c%c<<", if ( len >= 4 )
//dshdr[0], dshdr[1], dshdr[2], dshdr[3], Conn()->Weird(fmt("SMB-over-TCP header error: %02x %05x, >>\\x%02x%c%c%c<<",
msg_type, msg_len, //dshdr[0], dshdr[1], dshdr[2], dshdr[3],
data[0], data[1], data[2], data[3])); msg_type, msg_len,
data[0], data[1], data[2], data[3]));
else
Conn()->Weird(fmt("SMB-over-TCP header error: %02x %05x", msg_type, msg_len));
NeedResync(); NeedResync();
} }
else else
@ -121,21 +128,21 @@ bool Contents_SMB::CheckResync(int& len, const u_char*& data, bool orig)
if (resync_state == INSYNC) if (resync_state == INSYNC)
return true; return true;
// This is an attempt to re-synchronize the stream after a content gap. // This is an attempt to re-synchronize the stream after a content gap.
// Returns true if we are in sync. // Returns true if we are in sync.
// Returns false otherwise (we are in resync mode) // Returns false otherwise (we are in resync mode)
// //
// We try to look for the beginning of a SMB message, assuming // We try to look for the beginning of a SMB message, assuming
// SMB messages start at packet boundaries (though they may span // SMB messages start at packet boundaries (though they may span
// over multiple packets) (note that the data* of DeliverStream() // over multiple packets) (note that the data* of DeliverStream()
// usually starts at a packet boundrary). // usually starts at a packet boundrary).
// //
// Now lets see whether data points to the beginning of a // Now lets see whether data points to the beginning of a
// SMB message. If the resync processs is successful, we should // SMB message. If the resync processs is successful, we should
// be at the beginning of a frame. // be at the beginning of a frame.
// check if the SMB header starts with an SMB1 or SMB2 marker // check if the SMB header starts with an SMB1 or SMB2 marker
if ( ! HasSMBHeader(data) ) if ( ! HasSMBHeader(len, data) )
{ {
NeedResync(); NeedResync();
return false; return false;
@ -151,7 +158,7 @@ bool Contents_SMB::CheckResync(int& len, const u_char*& data, bool orig)
void Contents_SMB::DeliverStream(int len, const u_char* data, bool orig) void Contents_SMB::DeliverStream(int len, const u_char* data, bool orig)
{ {
TCP_SupportAnalyzer::DeliverStream(len, data, orig); TCP_SupportAnalyzer::DeliverStream(len, data, orig);
if (!CheckResync(len, data, orig)) if (!CheckResync(len, data, orig))
return; // Not in sync yet. Still resyncing return; // Not in sync yet. Still resyncing
@ -178,7 +185,7 @@ void Contents_SMB::DeliverStream(int len, const u_char* data, bool orig)
const u_char *dummy_p = msg_buf.GetBuf(); const u_char *dummy_p = msg_buf.GetBuf();
int dummy_len = (int) msg_buf.GetFill(); int dummy_len = (int) msg_buf.GetFill();
DeliverSMB(dummy_len, dummy_p); DeliverSMB(dummy_len, dummy_p);
state = WAIT_FOR_HDR; state = WAIT_FOR_HDR;
} }
} }

View file

@ -15,7 +15,7 @@ public:
Contents_SMB(Connection* conn, bool orig); Contents_SMB(Connection* conn, bool orig);
~Contents_SMB(); ~Contents_SMB();
virtual void DeliverStream(int len, const u_char* data, bool orig); void DeliverStream(int len, const u_char* data, bool orig) override;
protected: protected:
typedef enum { typedef enum {
@ -26,20 +26,18 @@ protected:
NEED_RESYNC, NEED_RESYNC,
INSYNC, INSYNC,
} resync_state_t; } resync_state_t;
virtual void Init(); void Init() override;
virtual bool CheckResync(int& len, const u_char*& data, bool orig); virtual bool CheckResync(int& len, const u_char*& data, bool orig);
virtual void Undelivered(uint64 seq, int len, bool orig); void Undelivered(uint64 seq, int len, bool orig) override;
virtual void NeedResync() { virtual void NeedResync() {
resync_state = NEED_RESYNC; resync_state = NEED_RESYNC;
state = WAIT_FOR_HDR; state = WAIT_FOR_HDR;
} }
bool HasSMBHeader(const u_char* data); bool HasSMBHeader(int len, const u_char* data);
void DeliverSMB(int len, const u_char* data); void DeliverSMB(int len, const u_char* data);
binpac::SMB::SMB_Conn* smb_session;
rpc::RPC_Reasm_Buffer hdr_buf; // Reassembles the NetBIOS length and glue. rpc::RPC_Reasm_Buffer hdr_buf; // Reassembles the NetBIOS length and glue.
rpc::RPC_Reasm_Buffer msg_buf; // Reassembles the SMB message. rpc::RPC_Reasm_Buffer msg_buf; // Reassembles the SMB message.
int msg_len; int msg_len;
@ -54,25 +52,23 @@ class SMB_Analyzer : public tcp::TCP_ApplicationAnalyzer {
public: public:
SMB_Analyzer(Connection* conn); SMB_Analyzer(Connection* conn);
virtual ~SMB_Analyzer(); virtual ~SMB_Analyzer();
virtual void Done(); void Done() override;
virtual void DeliverStream(int len, const u_char* data, bool orig); void DeliverStream(int len, const u_char* data, bool orig) override;
virtual void Undelivered(uint64 seq, int len, bool orig); void Undelivered(uint64 seq, int len, bool orig) override;
virtual void EndpointEOF(bool is_orig); void EndpointEOF(bool is_orig) override;
static analyzer::Analyzer* Instantiate(Connection* conn) static analyzer::Analyzer* Instantiate(Connection* conn)
{ return new SMB_Analyzer(conn); } { return new SMB_Analyzer(conn); }
protected: protected:
binpac::SMB::SMB_Conn* interp; binpac::SMB::SMB_Conn* interp;
Contents_SMB* o_smb;
Contents_SMB* r_smb;
// Count the number of chunks received by the analyzer // Count the number of chunks received by the analyzer
// but only used to count the first few. // but only used to count the first few.
uint8 chunks; uint8 chunks;
}; };
} } // namespace analyzer::* } } // namespace analyzer::*
#endif #endif

View file

@ -64,6 +64,6 @@ type TDS_Token_EnvChange = record {
}; };
type TDS_Token_Info = record { type TDS_Token_Info = record {
}; };

View file

@ -10,7 +10,10 @@ refine connection SMB_Conn += {
%cleanup{ %cleanup{
if ( gssapi ) if ( gssapi )
{
gssapi->Done();
delete gssapi; delete gssapi;
}
%} %}
function forward_gssapi(data: bytestring, is_orig: bool): bool function forward_gssapi(data: bytestring, is_orig: bool): bool

View file

@ -5,7 +5,7 @@
refine connection SMB_Conn += { refine connection SMB_Conn += {
%member{ %member{
map<uint16,bool> tree_is_pipe_map; map<uint16,bool> tree_is_pipe_map;
map<uint64,analyzer::dce_rpc::DCE_RPC_Analyzer*> fid_to_analyzer_map; map<uint64,analyzer::dce_rpc::DCE_RPC_Analyzer*> fid_to_analyzer_map;;
%} %}
%cleanup{ %cleanup{
@ -13,7 +13,10 @@ refine connection SMB_Conn += {
for ( auto kv : fid_to_analyzer_map ) for ( auto kv : fid_to_analyzer_map )
{ {
if ( kv.second ) if ( kv.second )
{
kv.second->Done();
delete kv.second; delete kv.second;
}
} }
%} %}
@ -50,4 +53,4 @@ refine connection SMB_Conn += {
return true; return true;
%} %}
}; };

View file

@ -1,11 +1,10 @@
function uint8s_to_stringval(s: uint8[]): StringVal function uint8s_to_stringval(data: uint8[]): StringVal
%{ %{
int length = 0; int length = 0;
const char* sp; const char* sp;
bool ascii = true; bool ascii = true;
vector<uint8>* data = s;
length = data->size(); length = data->size();
// Scan the string once to see if it's all ascii // Scan the string once to see if it's all ascii
// embedded in UCS-2 (16 bit unicode). // embedded in UCS-2 (16 bit unicode).
@ -21,7 +20,7 @@ function uint8s_to_stringval(s: uint8[]): StringVal
char *buf = new char[length]; char *buf = new char[length];
for ( int i = 0; i < length; i=i+2) for ( int i = 0; i + 1 < length; i=i+2) // check if we may read the character after the current one (else-case)
{ {
if ( ascii ) if ( ascii )
{ {