diff --git a/scripts/base/frameworks/dpd/main.bro b/scripts/base/frameworks/dpd/main.bro index 4586e2c02e..ca2b7b6a5e 100644 --- a/scripts/base/frameworks/dpd/main.bro +++ b/scripts/base/frameworks/dpd/main.bro @@ -27,6 +27,9 @@ export { disabled_aids: set[count]; }; + ## Analyzers which you don't want to throw + const ignore_violations: set[Analyzer::Tag] = set() &redef; + ## Ignore violations which go this many bytes into the connection. ## Set to 0 to never ignore protocol violations. const ignore_violations_after = 10 * 1024 &redef; @@ -82,6 +85,9 @@ event protocol_violation(c: connection, atype: Analyzer::Tag, aid: count, reason if ( ignore_violations_after > 0 && size > ignore_violations_after ) return; + if ( atype in ignore_violations ) + return; + # Disable the analyzer that raised the last core-generated event. disable_analyzer(c$id, aid); add c$dpd$disabled_aids[aid]; diff --git a/scripts/base/protocols/dce-rpc/main.bro b/scripts/base/protocols/dce-rpc/main.bro index c757c52686..27ef1bdc6f 100644 --- a/scripts/base/protocols/dce-rpc/main.bro +++ b/scripts/base/protocols/dce-rpc/main.bro @@ -34,6 +34,8 @@ export { } &redef; } +redef DPD::ignore_violations += { Analyzer::ANALYZER_DCE_RPC }; + type State: record { uuid : string &optional; named_pipe : string &optional; diff --git a/scripts/base/protocols/ntlm/main.bro b/scripts/base/protocols/ntlm/main.bro index 30797862f4..26eb3b3ac2 100644 --- a/scripts/base/protocols/ntlm/main.bro +++ b/scripts/base/protocols/ntlm/main.bro @@ -46,6 +46,8 @@ export { } &redef; } +redef DPD::ignore_violations += { Analyzer::ANALYZER_NTLM }; + redef record connection += { ntlm: Info &optional; }; diff --git a/scripts/policy/protocols/smb/smb1-main.bro b/scripts/policy/protocols/smb/smb1-main.bro index eff71006ae..c1b8ead509 100644 --- a/scripts/policy/protocols/smb/smb1-main.bro +++ b/scripts/policy/protocols/smb/smb1-main.bro @@ -273,7 +273,12 @@ event smb1_trans2_find_first2_request(c: connection, hdr: SMB1::Header, args: SM { c$smb_state$current_cmd$argument = args$file_name; } - + +event smb1_session_setup_andx_request(c: connection, hdr: SMB1::Header, request: SMB1::SessionSetupAndXRequest) &priority=5 + { + # No behavior yet. + } + event smb1_session_setup_andx_response(c: connection, hdr: SMB1::Header, response: SMB1::SessionSetupAndXResponse) &priority=-5 { if ( SMB::write_cmd_log && diff --git a/src/analyzer/protocol/smb/smb-common.pac b/src/analyzer/protocol/smb/smb-common.pac index 45c357da77..5e2a655ed7 100644 --- a/src/analyzer/protocol/smb/smb-common.pac +++ b/src/analyzer/protocol/smb/smb-common.pac @@ -236,15 +236,42 @@ enum SMB_Status { STATUS_SMB_NO_SUPPORT = 0xFFFF0002, }; -function determine_transaction_type(setup_count: int, name: SMB_string): TransactionType +function determine_transaction_type(header: SMB_Header, name: SMB_string): TransactionType %{ if ( name == NULL ) { return SMB_UNKNOWN; } - if ( ${name.u.s}->size() == 14 && ${name.u.s[0]} == '\\' && ${name.u.s[2]} == 'P' && ${name.u.s[4]} == 'I' && ${name.u.s[6]} == 'P' && ${name.u.s[8]} == 'E' && ${name.u.s[10]} == '\\') + if ( (${header.unicode} && ${name.u.s}->size() > 10 && ${name.u.s[0]} == '\\' && + ${name.u.s[2]} == 'P' && + ${name.u.s[4]} == 'I' && + ${name.u.s[6]} == 'P' && + ${name.u.s[8]} == 'E' && + ${name.u.s[10]} == '\\') || + (!${header.unicode} && ${name.a}->size() > 5 && ${name.a}->val()->at(0) == '\\' && + ${name.a}->val()->at(1) == 'P' && + ${name.a}->val()->at(2) == 'I' && + ${name.a}->val()->at(3) == 'P' && + ${name.a}->val()->at(4) == 'E' && + ${name.a}->val()->at(5) == '\\') ) { + if ( (${header.unicode} && ${name.u.s}->size() > 22 && ${name.u.s[12]} == 'L' && + ${name.u.s[14]} == 'A' && + ${name.u.s[16]} == 'N' && + ${name.u.s[18]} == 'M' && + ${name.u.s[20]} == 'A' && + ${name.u.s[22]} == 'N') || + (!${header.unicode} && ${name.a}->size() > 11 && ${name.a}->val()->at(6) == 'L' && + ${name.a}->val()->at(7) == 'A' && + ${name.a}->val()->at(8) == 'N' && + ${name.a}->val()->at(9) == 'M' && + ${name.a}->val()->at(10) == 'A' && + ${name.a}->val()->at(11) == 'N') ) + { + return SMB_RAP; + } + return SMB_PIPE; } diff --git a/src/analyzer/protocol/smb/smb-strings.pac b/src/analyzer/protocol/smb/smb-strings.pac index 5ebc975c10..cb793c5c6c 100644 --- a/src/analyzer/protocol/smb/smb-strings.pac +++ b/src/analyzer/protocol/smb/smb-strings.pac @@ -12,7 +12,7 @@ function uint8s_to_stringval(data: uint8[]): StringVal function extract_string(s: SMB_string) : StringVal %{ - if ( s->unicode() == 0 ) + if ( s->unicode() == false ) { int length = s->a()->size(); char buf[length]; diff --git a/src/analyzer/protocol/smb/smb1-com-locking-andx.pac b/src/analyzer/protocol/smb/smb1-com-locking-andx.pac index e519dd8984..f937dafbab 100644 --- a/src/analyzer/protocol/smb/smb1-com-locking-andx.pac +++ b/src/analyzer/protocol/smb/smb1-com-locking-andx.pac @@ -28,7 +28,7 @@ type LOCKING_ANDX_RANGE64 = record { }; # http://msdn.microsoft.com/en-us/library/ee442004.aspx -type SMB1_locking_andx_request(header: SMB_Header) = record { +type SMB1_locking_andx_request(header: SMB_Header, offset: uint16) = record { word_count : uint8; andx : SMB_andx; file_id : uint16; @@ -47,13 +47,16 @@ type SMB1_locking_andx_request(header: SMB_Header) = record { 32 -> locks32 : LOCKING_ANDX_RANGE32[num_requested_locks]; 64 -> locks64 : LOCKING_ANDX_RANGE64[num_requested_locks]; }; + + extra_byte_parameters : bytestring &transient &length=(andx.offset == 0 || andx.offset >= (offset+offsetof(extra_byte_parameters))+2) ? 0 : (andx.offset-(offset+offsetof(extra_byte_parameters))); + + andx_command : SMB_andx_command(header, 1, offset+offsetof(andx_command), andx.command); } &let { proc : bool = $context.connection.proc_smb1_locking_andx_request(header, this); }; # http://msdn.microsoft.com/en-us/library/ee441519.aspx type SMB1_locking_andx_response(header: SMB_Header) = record { - } &let { proc : bool = $context.connection.proc_smb1_locking_andx_response(header, this); }; diff --git a/src/analyzer/protocol/smb/smb1-com-logoff-andx.pac b/src/analyzer/protocol/smb/smb1-com-logoff-andx.pac index eb4b12616d..2284568bb5 100644 --- a/src/analyzer/protocol/smb/smb1-com-logoff-andx.pac +++ b/src/analyzer/protocol/smb/smb1-com-logoff-andx.pac @@ -10,10 +10,14 @@ refine connection SMB_Conn += { }; -type SMB1_logoff_andx(header: SMB_Header, is_orig: bool) = record { +type SMB1_logoff_andx(header: SMB_Header, offset: uint16, is_orig: bool) = record { word_count : uint8; andx : SMB_andx; byte_count : uint16; + + extra_byte_parameters : bytestring &transient &length=(andx.offset == 0 || andx.offset >= (offset+offsetof(extra_byte_parameters))+2) ? 0 : (andx.offset-(offset+offsetof(extra_byte_parameters))); + + andx_command : SMB_andx_command(header, 1, offset+offsetof(andx_command), andx.command); } &let { proc : bool = $context.connection.proc_smb1_logoff_andx(header, this); }; diff --git a/src/analyzer/protocol/smb/smb1-com-nt-create-andx.pac b/src/analyzer/protocol/smb/smb1-com-nt-create-andx.pac index d8e9e1fded..36a583696e 100644 --- a/src/analyzer/protocol/smb/smb1-com-nt-create-andx.pac +++ b/src/analyzer/protocol/smb/smb1-com-nt-create-andx.pac @@ -40,7 +40,7 @@ refine connection SMB_Conn += { }; -type SMB1_nt_create_andx_request(header: SMB_Header) = record { +type SMB1_nt_create_andx_request(header: SMB_Header, offset: uint16) = record { word_count : uint8; andx : SMB_andx; reserved : uint8; @@ -60,12 +60,14 @@ type SMB1_nt_create_andx_request(header: SMB_Header) = record { byte_count : uint16; filename : SMB_string(header.unicode, offsetof(filename)); - andx_command : SMB_andx_command(header, 1, andx.command); + extra_byte_parameters : bytestring &transient &length=(andx.offset == 0 || andx.offset >= (offset+offsetof(extra_byte_parameters))+2) ? 0 : (andx.offset-(offset+offsetof(extra_byte_parameters))); + + andx_command : SMB_andx_command(header, 1, offset+offsetof(andx_command), andx.command); } &let { proc : bool = $context.connection.proc_smb1_nt_create_andx_request(header, this); }; -type SMB1_nt_create_andx_response(header: SMB_Header) = record { +type SMB1_nt_create_andx_response(header: SMB_Header, offset: uint16) = record { word_count : uint8; andx : SMB_andx; oplock_level : uint8; @@ -83,6 +85,10 @@ type SMB1_nt_create_andx_response(header: SMB_Header) = record { directory : uint8; byte_count : uint16; + + extra_byte_parameters : bytestring &transient &length=(andx.offset == 0 || andx.offset >= (offset+offsetof(extra_byte_parameters))+2) ? 0 : (andx.offset-(offset+offsetof(extra_byte_parameters))); + + andx_command : SMB_andx_command(header, 0, offset+offsetof(andx_command), andx.command); } &let { proc : bool = $context.connection.proc_smb1_nt_create_andx_response(header, this); }; diff --git a/src/analyzer/protocol/smb/smb1-com-open-andx.pac b/src/analyzer/protocol/smb/smb1-com-open-andx.pac index 80f0d2e490..8f19f6f3a4 100644 --- a/src/analyzer/protocol/smb/smb1-com-open-andx.pac +++ b/src/analyzer/protocol/smb/smb1-com-open-andx.pac @@ -41,7 +41,7 @@ refine connection SMB_Conn += { -type SMB1_open_andx_request(header: SMB_Header) = record { +type SMB1_open_andx_request(header: SMB_Header, offset: uint16) = record { word_count : uint8; andx : SMB_andx; flags : uint16; @@ -55,11 +55,15 @@ type SMB1_open_andx_request(header: SMB_Header) = record { reserved : padding[2]; byte_count : uint16; filename : SMB_string(header.unicode, offsetof(filename); + + extra_byte_parameters : bytestring &transient &length=(andx.offset == 0 || andx.offset >= (offset+offsetof(extra_byte_parameters))+2) ? 0 : (andx.offset-(offset+offsetof(extra_byte_parameters))); + + andx_command : SMB_andx_command(header, 1, offset+offsetof(andx_command), andx.command); } &let { proc : bool = $context.connection.proc_smb1_open_andx_request(header, this); } &byteorder=littleendian; -type SMB1_open_andx_response(header: SMB_Header) = record { +type SMB1_open_andx_response(header: SMB_Header, offset: uint16) = record { word_count : uint8; andx : SMB_andx; fid : uint16; @@ -72,6 +76,10 @@ type SMB1_open_andx_response(header: SMB_Header) = record { open_results : uint16; reserved : padding[3]; byte_count : uint16; + + extra_byte_parameters : bytestring &transient &length=(andx.offset == 0 || andx.offset >= (offset+offsetof(extra_byte_parameters))+2) ? 0 : (andx.offset-(offset+offsetof(extra_byte_parameters))); + + andx_command : SMB_andx_command(header, 0, offset+offsetof(andx_command), andx.command); } &let { proc : bool = $context.connection.proc_smb1_open_andx_response(header, this); } &byteorder=littleendian; diff --git a/src/analyzer/protocol/smb/smb1-com-open-andx.pcap b/src/analyzer/protocol/smb/smb1-com-open-andx.pcap deleted file mode 100644 index 80f0d2e490..0000000000 --- a/src/analyzer/protocol/smb/smb1-com-open-andx.pcap +++ /dev/null @@ -1,77 +0,0 @@ -refine connection SMB_Conn += { - - function proc_smb1_open_andx_request(h: SMB_Header, val: SMB1_open_andx_request): bool - %{ - if ( smb1_open_andx_request ) - BifEvent::generate_smb1_open_andx_request(bro_analyzer(), - bro_analyzer()->Conn(), - BuildHeaderVal(h), - ${val.flags}, - ${val.access_mode}, - ${val.search_attrs}, - ${val.file_attrs}, - ${val.creation_time}, - ${val.open_mode}, - ${val.allocation_size}, - ${val.timeout}, - smb_string2stringval(${val.filename})); - - return true; - %} - - function proc_smb1_open_andx_response(h: SMB_Header, val: SMB1_open_andx_response): bool - %{ - if ( smb1_open_andx_response ) - BifEvent::generate_smb1_open_andx_response(bro_analyzer(), - bro_analyzer()->Conn(), - BuildHeaderVal(h), - ${val.fid}, - ${val.file_attrs}, - ${val.last_write_time}, - ${val.file_data_size}, - ${val.access_rights}, - ${val.resource_type}, - ${val.nm_pipe_status}, - ${val.open_results}); - - return true; - %} - -}; - - - -type SMB1_open_andx_request(header: SMB_Header) = record { - word_count : uint8; - andx : SMB_andx; - flags : uint16; - access_mode : uint16; - search_attrs : uint16; - file_attrs : uint16; - creation_time : uint32; - open_mode : uint16; - allocation_size : uint32; - timeout : uint32; - reserved : padding[2]; - byte_count : uint16; - filename : SMB_string(header.unicode, offsetof(filename); -} &let { - proc : bool = $context.connection.proc_smb1_open_andx_request(header, this); -} &byteorder=littleendian; - -type SMB1_open_andx_response(header: SMB_Header) = record { - word_count : uint8; - andx : SMB_andx; - fid : uint16; - file_attrs : uint16; - last_write_time : uint32; - file_data_size : uint32; - access_rights : uint16; - resource_type : uint16; - nm_pipe_status : uint16; - open_results : uint16; - reserved : padding[3]; - byte_count : uint16; -} &let { - proc : bool = $context.connection.proc_smb1_open_andx_response(header, this); -} &byteorder=littleendian; diff --git a/src/analyzer/protocol/smb/smb1-com-read-andx.pac b/src/analyzer/protocol/smb/smb1-com-read-andx.pac index d947dd0d06..0ea340d88b 100644 --- a/src/analyzer/protocol/smb/smb1-com-read-andx.pac +++ b/src/analyzer/protocol/smb/smb1-com-read-andx.pac @@ -13,10 +13,10 @@ refine connection SMB_Conn += { bro_analyzer()->Conn(), BuildHeaderVal(h), ${val.file_id}, - ${val.offset}, + ${val.read_offset}, ${val.max_count}); - read_offsets[${h.mid}] = ${val.offset}; + read_offsets[${h.mid}] = ${val.read_offset}; return true; %} @@ -45,7 +45,7 @@ refine connection SMB_Conn += { -type SMB1_read_andx_request(header: SMB_Header) = record { +type SMB1_read_andx_request(header: SMB_Header, offset: uint16) = record { word_count : uint8; andx : SMB_andx; file_id : uint16; @@ -53,6 +53,7 @@ type SMB1_read_andx_request(header: SMB_Header) = record { max_count_low : uint16; min_count : uint16; max_count_high : uint32; + remaining : uint16; offset_high_u : case word_count of { 0x0C -> offset_high_tmp : uint32; @@ -60,14 +61,18 @@ type SMB1_read_andx_request(header: SMB_Header) = record { }; byte_count : uint16; + + extra_byte_parameters : bytestring &transient &length=((andx.offset == 0 || andx.offset >= (offset+offsetof(extra_byte_parameters))+2) ? 0 : (andx.offset-(offset+offsetof(extra_byte_parameters)))); + + andx_command : SMB_andx_command(header, 1, offset+offsetof(andx_command), andx.command); } &let { - offset_high : uint32 = (word_count == 0x0C) ? offset_high_tmp : 0; - offset : uint64 = (offset_high * 0x10000) + offset_low; - max_count : uint64 = (max_count_high * 0x10000) + max_count_low; + offset_high : uint32 = (word_count == 0x0C && offset_high_tmp != 0xffffffff) ? offset_high_tmp : 0; + read_offset : uint64 = (offset_high * 0x10000) + offset_low; + max_count : uint64 = ((max_count_high == 0xffffffff ? 0 : max_count_high) * 0x10000) + max_count_low; proc : bool = $context.connection.proc_smb1_read_andx_request(header, this); } &byteorder=littleendian; -type SMB1_read_andx_response(header: SMB_Header) = record { +type SMB1_read_andx_response(header: SMB_Header, offset: uint16) = record { word_count : uint8; andx : SMB_andx; available : uint16; @@ -81,6 +86,10 @@ type SMB1_read_andx_response(header: SMB_Header) = record { byte_count : uint16; pad : padding to data_offset - SMB_Header_length; data : bytestring &length=data_len; + + extra_byte_parameters : bytestring &transient &length=(andx.offset == 0 || andx.offset >= (offset+offsetof(extra_byte_parameters))+2) ? 0 : (andx.offset-(offset+offsetof(extra_byte_parameters))); + + andx_command : SMB_andx_command(header, 0, offset+offsetof(andx_command), andx.command); } &let { is_pipe : bool = $context.connection.get_tree_is_pipe(header.tid); pipe_proc : bool = $context.connection.forward_dce_rpc(data, 0, false) &if(is_pipe); diff --git a/src/analyzer/protocol/smb/smb1-com-session-setup-andx.pac b/src/analyzer/protocol/smb/smb1-com-session-setup-andx.pac index 45ef4c6127..299fd929fc 100644 --- a/src/analyzer/protocol/smb/smb1-com-session-setup-andx.pac +++ b/src/analyzer/protocol/smb/smb1-com-session-setup-andx.pac @@ -91,9 +91,9 @@ refine connection SMB_Conn += { { case 3: // pre NT LM 0.12 response->Assign(1, new Val(${val.lanman.is_guest}, TYPE_BOOL)); - response->Assign(2, smb_string2stringval(${val.lanman.native_os})); - response->Assign(3, smb_string2stringval(${val.lanman.native_lanman})); - response->Assign(4, smb_string2stringval(${val.lanman.primary_domain})); + response->Assign(2, ${val.lanman.byte_count} == 0 ? new StringVal("") : smb_string2stringval(${val.lanman.native_os[0]})); + response->Assign(3, ${val.lanman.byte_count} == 0 ? new StringVal("") : smb_string2stringval(${val.lanman.native_lanman[0]})); + response->Assign(4, ${val.lanman.byte_count} == 0 ? new StringVal("") : smb_string2stringval(${val.lanman.primary_domain[0]})); break; case 4: // NT LM 0.12 response->Assign(1, new Val(${val.ntlm.is_guest}, TYPE_BOOL)); @@ -117,29 +117,29 @@ refine connection SMB_Conn += { }; -type SMB1_session_setup_andx_request(header: SMB_Header) = record { +type SMB1_session_setup_andx_request(header: SMB_Header, offset: uint16) = record { word_count : uint8; lanman_or_ntlm : case word_count of { - 0x0a -> lanman : SMB1_session_setup_andx_request_lanman(header); - 0x0c -> ntlm_extended_security : SMB1_session_setup_andx_request_ntlm_extended_security(header); - 0x0d -> ntlm_nonextended_security : SMB1_session_setup_andx_request_ntlm_nonextended_security(header); + 0x0a -> lanman : SMB1_session_setup_andx_request_lanman(header, offset+offsetof(lanman_or_ntlm)); + 0x0c -> ntlm_extended_security : SMB1_session_setup_andx_request_ntlm_extended_security(header, offset+1); + 0x0d -> ntlm_nonextended_security : SMB1_session_setup_andx_request_ntlm_nonextended_security(header, offset+1); }; } &let { proc: bool = $context.connection.proc_smb1_session_setup_andx_request(header, this); }; -type SMB1_session_setup_andx_response(header: SMB_Header) = record { +type SMB1_session_setup_andx_response(header: SMB_Header, offset: uint16) = record { word_count : uint8; lanman_or_ntlm : case word_count of { - 0x03 -> lanman: SMB1_session_setup_andx_response_lanman(header); - 0x04 -> ntlm: SMB1_session_setup_andx_response_ntlm(header); + 0x03 -> lanman: SMB1_session_setup_andx_response_lanman(header, offset+1); + 0x04 -> ntlm: SMB1_session_setup_andx_response_ntlm(header, offset+1); default -> error: uint16; }; } &let { proc: bool = $context.connection.proc_smb1_session_setup_andx_response(header, this); }; -type SMB1_session_setup_andx_request_lanman(header: SMB_Header) = record { +type SMB1_session_setup_andx_request_lanman(header: SMB_Header, offset: uint16) = record { andx : SMB_andx; max_buffer_size : uint16; max_mpx_count : uint16; @@ -154,16 +154,24 @@ type SMB1_session_setup_andx_request_lanman(header: SMB_Header) = record { primary_domain : SMB_string(header.unicode, offsetof(primary_domain) + 1); native_os : SMB_string(header.unicode, offsetof(native_os) + 1); native_lanman : SMB_string(header.unicode, offsetof(native_lanman) + 1); + + extra_byte_parameters : bytestring &transient &length=(andx.offset == 0 || andx.offset >= (offset+offsetof(extra_byte_parameters))+2) ? 0 : (andx.offset-(offset+offsetof(extra_byte_parameters))); + + andx_command : SMB_andx_command(header, 1, offset+offsetof(andx_command), andx.command); }; -type SMB1_session_setup_andx_response_lanman(header: SMB_Header) = record { +type SMB1_session_setup_andx_response_lanman(header: SMB_Header, offset: uint16) = record { andx : SMB_andx; action : uint16; byte_count : uint16; # offset + 1 due to word_count in the parent type - native_os : SMB_string(header.unicode, offsetof(native_os) + 1); - native_lanman : SMB_string(header.unicode, offsetof(native_lanman) + 1); - primary_domain : SMB_string(header.unicode, offsetof(primary_domain) + 1); + native_os : SMB_string(header.unicode, offsetof(native_os) + 1)[byte_count == 0 ? 0 : 1]; + native_lanman : SMB_string(header.unicode, offsetof(native_lanman) + 1)[byte_count == 0 ? 0 : 1]; + primary_domain : SMB_string(header.unicode, offsetof(primary_domain) + 1)[byte_count == 0 ? 0 : 1]; + + extra_byte_parameters : bytestring &transient &length=(andx.offset == 0 || andx.offset >= (offset+offsetof(extra_byte_parameters))+2) ? 0 : (andx.offset-(offset+offsetof(extra_byte_parameters))); + + andx_command : SMB_andx_command(header, 0, offset+offsetof(andx_command), andx.command); } &let { is_guest: bool = ( action & 0x1 ) > 0; }; @@ -179,7 +187,7 @@ type SMB1_session_setup_andx_request_ntlm_capabilities = record { nt_find : bool = ( capabilities & 0x0200 ) > 0; }; -type SMB1_session_setup_andx_request_ntlm_nonextended_security(header: SMB_Header) = record { +type SMB1_session_setup_andx_request_ntlm_nonextended_security(header: SMB_Header, offset: uint16) = record { andx : SMB_andx; max_buffer_size : uint16; max_mpx_count : uint16; @@ -197,9 +205,13 @@ type SMB1_session_setup_andx_request_ntlm_nonextended_security(header: SMB_Heade primary_domain : SMB_string(header.unicode, offsetof(primary_domain) + 1); native_os : SMB_string(header.unicode, offsetof(native_os) + 1); native_lanman : SMB_string(header.unicode, offsetof(native_lanman) + 1); + + extra_byte_parameters : bytestring &transient &length=(andx.offset == 0 || andx.offset >= (offset+offsetof(extra_byte_parameters))+2) ? 0 : (andx.offset-(offset+offsetof(extra_byte_parameters))); + + andx_command : SMB_andx_command(header, 1, offset+offsetof(andx_command), andx.command); }; -type SMB1_session_setup_andx_request_ntlm_extended_security(header: SMB_Header) = record { +type SMB1_session_setup_andx_request_ntlm_extended_security(header: SMB_Header, offset: uint16) = record { andx : SMB_andx; max_buffer_size : uint16; max_mpx_count : uint16; @@ -213,11 +225,15 @@ type SMB1_session_setup_andx_request_ntlm_extended_security(header: SMB_Header) # offset + 1 due to word_count in the parent type native_os : SMB_string(header.unicode, offsetof(native_os) + 1); native_lanman : SMB_string(header.unicode, offsetof(native_lanman) + 1); + + extra_byte_parameters : bytestring &transient &length=(andx.offset >= (offset+offsetof(extra_byte_parameters))+2) ? 0 : (andx.offset-(offset+offsetof(extra_byte_parameters))); + + andx_command : SMB_andx_command(header, 1, offset+offsetof(andx_command), andx.command); } &let { pipe_proc : bool = $context.connection.forward_gssapi(security_blob, true); }; -type SMB1_session_setup_andx_response_ntlm(header: SMB_Header) = record { +type SMB1_session_setup_andx_response_ntlm(header: SMB_Header, offset: uint16) = record { andx : SMB_andx; action : uint16; security_blob_length : uint16; @@ -227,6 +243,10 @@ type SMB1_session_setup_andx_response_ntlm(header: SMB_Header) = record { native_os : SMB_string(header.unicode, offsetof(native_os) + 1); native_lanman : SMB_string(header.unicode, offsetof(native_lanman) + 1); primary_domain : SMB_string(header.unicode, offsetof(primary_domain) + 1); + + extra_byte_parameters : bytestring &transient &length=(andx.offset == 0 || andx.offset >= (offset+offsetof(extra_byte_parameters))+2) ? 0 : (andx.offset-(offset+offsetof(extra_byte_parameters))); + + andx_command : SMB_andx_command(header, 0, offset+offsetof(andx_command), andx.command); } &let { is_guest : bool = ( action & 0x1 ) > 0; gssapi_proc : bool = $context.connection.forward_gssapi(security_blob, false); diff --git a/src/analyzer/protocol/smb/smb1-com-transaction-secondary.pac b/src/analyzer/protocol/smb/smb1-com-transaction-secondary.pac index ceefb0a1a4..bcd9ba91bb 100644 --- a/src/analyzer/protocol/smb/smb1-com-transaction-secondary.pac +++ b/src/analyzer/protocol/smb/smb1-com-transaction-secondary.pac @@ -13,5 +13,5 @@ type SMB1_transaction_secondary_request(header: SMB_Header) = record { pad1 : padding to param_offset - SMB_Header_length; parameters : bytestring &length = param_count; pad2 : padding to data_offset - SMB_Header_length; - data : SMB1_transaction_data(header, true, data_count, 0, SMB_UNKNOWN); + data : SMB1_transaction_data(header, true, data_count, 0, SMB_UNKNOWN, false); }; diff --git a/src/analyzer/protocol/smb/smb1-com-transaction.pac b/src/analyzer/protocol/smb/smb1-com-transaction.pac index 8f2215cff9..d199b9062c 100644 --- a/src/analyzer/protocol/smb/smb1-com-transaction.pac +++ b/src/analyzer/protocol/smb/smb1-com-transaction.pac @@ -43,14 +43,13 @@ refine connection SMB_Conn += { function proc_smb1_transaction_response(header: SMB_Header, val: SMB1_transaction_response): bool %{ - //printf("transaction_response\n"); return true; %} }; type SMB1_transaction_data(header: SMB_Header, is_orig: bool, count: uint16, sub_cmd: uint16, - trans_type: int) = case trans_type of { + trans_type: int, is_pipe: bool) = case trans_type of { # SMB_MAILSLOT_BROWSE -> mailslot : SMB_MailSlot_message(header.unicode, count); # SMB_MAILSLOT_LANMAN -> lanman : SMB_MailSlot_message(header.unicode, count); # SMB_RAP -> rap : SMB_Pipe_message(header.unicode, count); @@ -61,7 +60,7 @@ type SMB1_transaction_data(header: SMB_Header, is_orig: bool, count: uint16, sub pipe_proc : bool = $context.connection.forward_dce_rpc(pipe_data, 0, is_orig) &if(trans_type == SMB_PIPE); }; -type SMB1_transaction_setup(header: SMB_Header) = record { +type SMB1_transaction_setup = record { op_code : uint16; file_id : uint16; } @@ -83,18 +82,19 @@ type SMB1_transaction_request(header: SMB_Header) = record { data_offset : uint16; setup_count : uint8; reserved3 : uint8; - setup : SMB1_transaction_setup(header); + # word_count 16 is a different dialect that behaves a bit differently. + setup : SMB1_transaction_setup[word_count == 16 ? 1 : setup_count]; byte_count : uint16; name : SMB_string(header.unicode, offsetof(name)); pad1 : padding to param_offset - SMB_Header_length; parameters : bytestring &length = param_count; pad2 : padding to data_offset - SMB_Header_length; - data : SMB1_transaction_data(header, true, data_count, sub_cmd, transtype); + data : SMB1_transaction_data(header, true, data_count, sub_cmd, transtype, is_pipe); } &let { - sub_cmd : uint16 = setup_count ? setup.op_code : 0; - transtype : int = determine_transaction_type(setup_count, name); - is_pipe : bool = (transtype == SMB_PIPE); + sub_cmd : uint16 = (sizeof(setup) && word_count != 16) > 0 ? setup[0].op_code : 0; + transtype : int = determine_transaction_type(header, name); + is_pipe : bool = (transtype == SMB_PIPE || (transtype == SMB_UNKNOWN && $context.connection.get_tree_is_pipe(header.tid))); proc_set_pipe : bool = $context.connection.set_is_file_a_pipe(header.mid, is_pipe); proc : bool = $context.connection.proc_smb1_transaction_request(header, this); @@ -119,7 +119,7 @@ type SMB1_transaction_response(header: SMB_Header) = record { pad0 : padding to param_offset - SMB_Header_length; parameters : bytestring &length = param_count; pad1 : padding to data_offset - SMB_Header_length; - data : SMB1_transaction_data(header, false, data_count, 0, is_pipe ? SMB_PIPE : SMB_UNKNOWN)[data_count>0 ? 1 : 0]; + data : SMB1_transaction_data(header, false, data_count, 0, is_pipe ? SMB_PIPE : SMB_UNKNOWN, is_pipe)[data_count>0 ? 1 : 0]; } &let { proc : bool = $context.connection.proc_smb1_transaction_response(header, this); is_pipe: bool = $context.connection.get_is_file_a_pipe(header.mid); diff --git a/src/analyzer/protocol/smb/smb1-com-tree-connect-andx.pac b/src/analyzer/protocol/smb/smb1-com-tree-connect-andx.pac index ef32492414..756a28bc96 100644 --- a/src/analyzer/protocol/smb/smb1-com-tree-connect-andx.pac +++ b/src/analyzer/protocol/smb/smb1-com-tree-connect-andx.pac @@ -14,41 +14,52 @@ refine connection SMB_Conn += { function proc_smb1_tree_connect_andx_response(header: SMB_Header, val: SMB1_tree_connect_andx_response): bool %{ set_tree_is_pipe(${header.tid}, strncmp((const char*) smb_string2stringval(${val.service})->Bytes(), "IPC", 3) == 0); + if ( smb1_tree_connect_andx_response ) + { BifEvent::generate_smb1_tree_connect_andx_response(bro_analyzer(), bro_analyzer()->Conn(), BuildHeaderVal(header), smb_string2stringval(${val.service}), - smb_string2stringval(${val.native_file_system})); + ${val.byte_count} > ${val.service.a}->size() ? smb_string2stringval(${val.native_file_system[0]}) : new StringVal("")); + } return true; %} }; -type SMB1_tree_connect_andx_request(header: SMB_Header) = record { +type SMB1_tree_connect_andx_request(header: SMB_Header, offset: uint16) = record { word_count : uint8; - andx : SMB_andx; - flags : uint16; + andx : SMB_andx; + flags : uint16; password_length : uint16; byte_count : uint16; password : uint8[password_length]; path : SMB_string(header.unicode, offsetof(path)); service : SMB_string(0, offsetof(service)); + + extra_byte_parameters : bytestring &transient &length=(andx.offset == 0 || andx.offset >= (offset+offsetof(extra_byte_parameters))+2) ? 0 : (andx.offset-(offset+offsetof(extra_byte_parameters))); + + andx_command : SMB_andx_command(header, 1, offset+offsetof(andx_command), andx.command); } &let { proc : bool = $context.connection.proc_smb1_tree_connect_andx_request(header, this); }; -type SMB1_tree_connect_andx_response(header: SMB_Header) = record { +type SMB1_tree_connect_andx_response(header: SMB_Header, offset: uint16) = record { word_count : uint8; andx : SMB_andx; - optional_support : uint16; - pad : padding[(word_count-3)*2]; + optional_support : uint16[word_count<3 ? 0 : 1]; + pad : padding[word_count<3 ? 0 : (word_count-3)*2]; byte_count : uint16; service : SMB_string(0, offsetof(service)); - native_file_system : SMB_string(header.unicode, offsetof(native_file_system)); + native_file_system : SMB_string(header.unicode, offsetof(native_file_system))[byte_count > sizeof(service) ? 1 : 0]; + + extra_byte_parameters : bytestring &transient &length=(andx.offset == 0 || andx.offset >= (offset+offsetof(extra_byte_parameters))+2) ? 0 : (andx.offset-(offset+offsetof(extra_byte_parameters))); + + andx_command : SMB_andx_command(header, 0, offset+offsetof(andx_command), andx.command); } &let { proc : bool = $context.connection.proc_smb1_tree_connect_andx_response(header, this); }; diff --git a/src/analyzer/protocol/smb/smb1-com-write-andx.pac b/src/analyzer/protocol/smb/smb1-com-write-andx.pac index fed5a7440a..79d36c52b5 100644 --- a/src/analyzer/protocol/smb/smb1-com-write-andx.pac +++ b/src/analyzer/protocol/smb/smb1-com-write-andx.pac @@ -7,13 +7,13 @@ refine connection SMB_Conn += { bro_analyzer()->Conn(), BuildHeaderVal(h), ${val.file_id}, - ${val.offset}, + ${val.write_offset}, ${val.data_len}); if ( ! ${val.is_pipe} && ${val.data}.length() > 0 ) { file_mgr->DataIn(${val.data}.begin(), ${val.data}.length(), - ${val.offset}, + ${val.write_offset}, bro_analyzer()->GetAnalyzerTag(), bro_analyzer()->Conn(), h->is_orig()); } @@ -34,7 +34,7 @@ refine connection SMB_Conn += { }; -type SMB1_write_andx_request(header: SMB_Header) = record { +type SMB1_write_andx_request(header: SMB_Header, offset: uint16) = record { word_count : uint8; andx : SMB_andx; file_id : uint16; @@ -53,17 +53,21 @@ type SMB1_write_andx_request(header: SMB_Header) = record { byte_count : uint16; pad : padding to data_offset - SMB_Header_length; data : bytestring &length=data_len; + + extra_byte_parameters : bytestring &transient &length=(andx.offset == 0 || andx.offset >= (offset+offsetof(extra_byte_parameters))+2) ? 0 : (andx.offset-(offset+offsetof(extra_byte_parameters))); + + andx_command : SMB_andx_command(header, 1, offset+offsetof(andx_command), andx.command); } &let { is_pipe : bool = $context.connection.get_tree_is_pipe(header.tid); pipe_proc : bool = $context.connection.forward_dce_rpc(data, 0, true) &if(is_pipe); data_len : uint32 = (data_len_high << 16) + data_len_low; offset_high : uint32 = (word_count == 0x0E) ? offset_high_tmp : 0; - offset : uint64 = (offset_high * 0x10000) + offset_low; + write_offset: uint64 = (offset_high * 0x10000) + offset_low; proc : bool = $context.connection.proc_smb1_write_andx_request(header, this); }; -type SMB1_write_andx_response(header: SMB_Header) = record { +type SMB1_write_andx_response(header: SMB_Header, offset: uint16) = record { word_count : uint8; andx : SMB_andx; written_low : uint16; @@ -72,6 +76,10 @@ type SMB1_write_andx_response(header: SMB_Header) = record { reserved : uint16; byte_count : uint16; + + extra_byte_parameters : bytestring &transient &length=(andx.offset == 0 || andx.offset >= (offset+offsetof(extra_byte_parameters))+2) ? 0 : (andx.offset-(offset+offsetof(extra_byte_parameters))); + + andx_command : SMB_andx_command(header, 0, offset+offsetof(andx_command), andx.command); } &let { written_bytes : uint32 = (written_high * 0x10000) + written_low; proc : bool = $context.connection.proc_smb1_write_andx_response(header, this); diff --git a/src/analyzer/protocol/smb/smb1-protocol.pac b/src/analyzer/protocol/smb/smb1-protocol.pac index 19afc626b6..b7ad6af140 100644 --- a/src/analyzer/protocol/smb/smb1-protocol.pac +++ b/src/analyzer/protocol/smb/smb1-protocol.pac @@ -98,7 +98,7 @@ type SMB_PDU(is_orig: bool, msg_len: uint32) = record { # Message length of 35 means that the actual message is # only three bytes which means it's an empty response. 35 -> no_msg : SMB_No_Message(header, is_orig); - default -> msg : SMB_Message(header, header.command, is_orig); + default -> msg : SMB_Message(header, SMB_Header_length, header.command, is_orig); }; }; @@ -115,27 +115,27 @@ type SMB_empty_response(header: SMB_Header) = record { proc : bool = $context.connection.proc_smb_empty_response(header); }; -type SMB_Message(header: SMB_Header, command: uint8, is_orig: bool) = case is_orig of { - true -> request : SMB_Message_Request(header, command, is_orig); - false -> response : SMB_Message_Response(header, command, is_orig); +type SMB_Message(header: SMB_Header, offset: uint16, command: uint8, is_orig: bool) = case is_orig of { + true -> request : SMB_Message_Request(header, offset, command, is_orig); + false -> response : SMB_Message_Response(header, offset, command, is_orig); }; -type SMB_andx_command(header: SMB_Header, is_orig: bool, command: uint8) = case command of { +type SMB_andx_command(header: SMB_Header, is_orig: bool, offset: uint16, command: uint8) = case command of { 0xff -> no_futher_commands : empty; - default -> message : SMB_Message(header, command, is_orig); + default -> message : SMB_Message(header, offset, command, is_orig); }; -type SMB_Message_Request(header: SMB_Header, command: uint8, is_orig: bool) = case command of { +type SMB_Message_Request(header: SMB_Header, offset: uint16, command: uint8, is_orig: bool) = case command of { # SMB1 Command Extensions #SMB_COM_OPEN_ANDX -> open_andx : SMB_open_andx_request(header); - SMB_COM_READ_ANDX -> read_andx : SMB1_read_andx_request(header); - SMB_COM_WRITE_ANDX -> write_andx : SMB1_write_andx_request(header); + SMB_COM_READ_ANDX -> read_andx : SMB1_read_andx_request(header, offset); + SMB_COM_WRITE_ANDX -> write_andx : SMB1_write_andx_request(header, offset); SMB_COM_TRANSACTION2 -> transaction2 : SMB1_transaction2_request(header); SMB_COM_NEGOTIATE -> negotiate : SMB1_negotiate_request(header); - SMB_COM_SESSION_SETUP_ANDX -> session_setup_andx : SMB1_session_setup_andx_request(header); - SMB_COM_TREE_CONNECT_ANDX -> tree_connect_andx : SMB1_tree_connect_andx_request(header); + SMB_COM_SESSION_SETUP_ANDX -> session_setup_andx : SMB1_session_setup_andx_request(header, offset); + SMB_COM_TREE_CONNECT_ANDX -> tree_connect_andx : SMB1_tree_connect_andx_request(header, offset); SMB_COM_NT_TRANSACT -> nt_transact : SMB1_nt_transact_request(header); - SMB_COM_NT_CREATE_ANDX -> nt_create_andx : SMB1_nt_create_andx_request(header); + SMB_COM_NT_CREATE_ANDX -> nt_create_andx : SMB1_nt_create_andx_request(header, offset); # SMB_COM_CREATE_DIRECTORY -> create_directory : SMB1_create_directory_request(header); # #SMB_COM_DELETE_DIRECTORY -> delete_directory : SMB_delete_directory_request(header); @@ -168,7 +168,7 @@ type SMB_Message_Request(header: SMB_Header, command: uint8, is_orig: bool) = ca # #SMB_COM_QUERY_SERVER -> query_server : SMB_query_server_request(header); # #SMB_COM_SET_INFORMATION2 -> set_information2 : SMB_set_information2_request(header); # #SMB_COM_QUERY_INFORMATION2 -> query_information2 : SMB_query_information2_request(header); - SMB_COM_LOCKING_ANDX -> locking_andx : SMB1_locking_andx_request(header); + SMB_COM_LOCKING_ANDX -> locking_andx : SMB1_locking_andx_request(header, offset); SMB_COM_TRANSACTION -> transaction : SMB1_transaction_request(header); # SMB_COM_TRANSACTION_SECONDARY -> transaction_secondary : SMB1_transaction_secondary_request(header); # #SMB_COM_IOCTL -> ioctl : SMB_ioctl_request(header); @@ -184,7 +184,7 @@ type SMB_Message_Request(header: SMB_Header, command: uint8, is_orig: bool) = ca # #SMB_COM_FIND_NOTIFY_CLOSE -> find_notify_close : SMB_find_notify_close_request(header); # #SMB_COM_TREE_CONNECT -> tree_connect : SMB_tree_connect_request(header); SMB_COM_TREE_DISCONNECT -> tree_disconnect : SMB1_tree_disconnect(header, is_orig); - SMB_COM_LOGOFF_ANDX -> logoff_andx : SMB1_logoff_andx(header, is_orig); + SMB_COM_LOGOFF_ANDX -> logoff_andx : SMB1_logoff_andx(header, offset, is_orig); # #SMB_COM_QUERY_INFORMATION_DISK -> query_information_disk : SMB_query_information_disk_request(header); # #SMB_COM_SEARCH -> search : SMB_search_request(header); # #SMB_COM_FIND -> find : SMB_find_request(header); @@ -203,17 +203,17 @@ type SMB_Message_Request(header: SMB_Header, command: uint8, is_orig: bool) = ca default -> unknown_msg : bytestring &restofdata; # TODO: do something different here! } &byteorder = littleendian; -type SMB_Message_Response(header: SMB_Header, command: uint8, is_orig: bool) = case command of { +type SMB_Message_Response(header: SMB_Header, offset: uint16, command: uint8, is_orig: bool) = case command of { # SMB1 Command Extensions - #SMB_COM_OPEN_ANDX -> open_andx : SMB_open_andx_response(header); - SMB_COM_READ_ANDX -> read_andx : SMB1_read_andx_response(header); - SMB_COM_WRITE_ANDX -> write_andx : SMB1_write_andx_response(header); + #SMB_COM_OPEN_ANDX -> open_andx : SMB_open_andx_response(header, offset); + SMB_COM_READ_ANDX -> read_andx : SMB1_read_andx_response(header, offset); + SMB_COM_WRITE_ANDX -> write_andx : SMB1_write_andx_response(header, offset); SMB_COM_TRANSACTION2 -> transaction2 : SMB1_transaction2_response(header); SMB_COM_NEGOTIATE -> negotiate : SMB1_negotiate_response(header); - SMB_COM_SESSION_SETUP_ANDX -> session_setup_andx : SMB1_session_setup_andx_response(header); - SMB_COM_TREE_CONNECT_ANDX -> tree_connect_andx : SMB1_tree_connect_andx_response(header); + SMB_COM_SESSION_SETUP_ANDX -> session_setup_andx : SMB1_session_setup_andx_response(header, offset); + SMB_COM_TREE_CONNECT_ANDX -> tree_connect_andx : SMB1_tree_connect_andx_response(header, offset); SMB_COM_NT_TRANSACT -> nt_transact : SMB1_nt_transact_response(header); - SMB_COM_NT_CREATE_ANDX -> nt_create_andx : SMB1_nt_create_andx_response(header); + SMB_COM_NT_CREATE_ANDX -> nt_create_andx : SMB1_nt_create_andx_response(header, offset); # SMB_COM_CREATE_DIRECTORY -> create_directory : SMB1_create_directory_response(header); # #SMB_COM_DELETE_DIRECTORY -> delete_directory : SMB_delete_directory_response(header); @@ -261,7 +261,7 @@ type SMB_Message_Response(header: SMB_Header, command: uint8, is_orig: bool) = c # #SMB_COM_FIND_NOTIFY_CLOSE -> find_notify_close : SMB_find_notify_close_response(header); # #SMB_COM_TREE_CONNECT -> tree_connect : SMB_tree_connect_response(header); SMB_COM_TREE_DISCONNECT -> tree_disconnect : SMB1_tree_disconnect(header, is_orig); - SMB_COM_LOGOFF_ANDX -> logoff_andx : SMB1_logoff_andx(header, is_orig); + SMB_COM_LOGOFF_ANDX -> logoff_andx : SMB1_logoff_andx(header, offset, is_orig); # #SMB_COM_QUERY_INFORMATION_DISK -> query_information_disk : SMB_query_information_disk_response(header); # #SMB_COM_SEARCH -> search : SMB_search_response(header); # #SMB_COM_FIND -> find : SMB_find_response(header);