mirror of
https://github.com/zeek/zeek.git
synced 2025-10-01 22:28:20 +00:00

This makes a change to the record for smb1-negotiate-response as well. Times and dates are two 2-byte sections, not three. Switch the parsing to just use two uint16s, and pass those into the lanman time conversion function.
253 lines
11 KiB
JavaScript
253 lines
11 KiB
JavaScript
# This is an original Core Protocol command.
|
|
#
|
|
# This command is used to initiate an SMB connection between the
|
|
# client and the server. An SMB_COM_NEGOTIATE exchange MUST be
|
|
# completed before any other SMB messages are sent to the server.
|
|
#
|
|
# There MUST be only one SMB_COM_NEGOTIATE exchange per SMB
|
|
# connection. Subsequent SMB_COM_NEGOTIATE requests received by the
|
|
# server MUST be rejected with error responses. The server MUST NOT
|
|
# take any other action.
|
|
|
|
refine connection SMB_Conn += {
|
|
|
|
function proc_smb1_negotiate_request(header: SMB_Header, val: SMB1_negotiate_request): bool
|
|
%{
|
|
if ( smb1_negotiate_request )
|
|
{
|
|
auto dialects = zeek::make_intrusive<zeek::VectorVal>(zeek::id::string_vec);
|
|
|
|
for ( unsigned int i = 0; i < ${val.dialects}->size(); ++i )
|
|
{
|
|
auto dia = smb_string2stringval((*${val.dialects})[i]->name());
|
|
dialects->Assign(i, std::move(dia));
|
|
}
|
|
|
|
zeek::BifEvent::enqueue_smb1_negotiate_request(zeek_analyzer(), zeek_analyzer()->Conn(),
|
|
SMBHeaderVal(header),
|
|
std::move(dialects));
|
|
}
|
|
|
|
return true;
|
|
%}
|
|
|
|
function proc_smb1_negotiate_response(header: SMB_Header, val: SMB1_negotiate_response): bool
|
|
%{
|
|
if ( smb1_negotiate_response )
|
|
{
|
|
auto response = zeek::make_intrusive<zeek::RecordVal>(zeek::BifType::Record::SMB1::NegotiateResponse);
|
|
|
|
switch ( ${val.word_count} )
|
|
{
|
|
case 0x01:
|
|
{
|
|
auto core = zeek::make_intrusive<zeek::RecordVal>(zeek::BifType::Record::SMB1::NegotiateResponseCore);
|
|
core->Assign(0, ${val.dialect_index});
|
|
|
|
response->Assign(0, std::move(core));
|
|
}
|
|
break;
|
|
|
|
case 0x0d:
|
|
{
|
|
auto security = zeek::make_intrusive<zeek::RecordVal>(zeek::BifType::Record::SMB1::NegotiateResponseSecurity);
|
|
security->Assign(0, ${val.lanman.security_user_level});
|
|
security->Assign(1, ${val.lanman.security_challenge_response});
|
|
|
|
auto raw = zeek::make_intrusive<zeek::RecordVal>(zeek::BifType::Record::SMB1::NegotiateRawMode);
|
|
raw->Assign(0, ${val.lanman.raw_read_supported});
|
|
raw->Assign(1, ${val.lanman.raw_write_supported});
|
|
|
|
auto lanman = zeek::make_intrusive<zeek::RecordVal>(zeek::BifType::Record::SMB1::NegotiateResponseLANMAN);
|
|
lanman->Assign(0, ${val.word_count});
|
|
lanman->Assign(1, ${val.dialect_index});
|
|
lanman->Assign(2, std::move(security));
|
|
lanman->Assign(3, ${val.lanman.max_buffer_size});
|
|
lanman->Assign(4, ${val.lanman.max_mpx_count});
|
|
|
|
lanman->Assign(5, ${val.lanman.max_number_vcs});
|
|
lanman->Assign(6, std::move(raw));
|
|
lanman->Assign(7, ${val.lanman.session_key});
|
|
lanman->Assign(8, time_from_lanman(${val.lanman.server_time}, ${val.lanman.server_date}, ${val.lanman.server_tz}));
|
|
lanman->Assign(9, to_stringval(${val.lanman.encryption_key}));
|
|
|
|
lanman->Assign(10, smb_string2stringval(${val.lanman.primary_domain}));
|
|
|
|
response->Assign(1, std::move(lanman));
|
|
}
|
|
break;
|
|
|
|
case 0x11:
|
|
{
|
|
auto security = zeek::make_intrusive<zeek::RecordVal>(zeek::BifType::Record::SMB1::NegotiateResponseSecurity);
|
|
security->Assign(0, ${val.ntlm.security_user_level});
|
|
security->Assign(1, ${val.ntlm.security_challenge_response});
|
|
security->Assign(2, ${val.ntlm.security_signatures_enabled});
|
|
security->Assign(3, ${val.ntlm.security_signatures_required});
|
|
|
|
auto capabilities = zeek::make_intrusive<zeek::RecordVal>(zeek::BifType::Record::SMB1::NegotiateCapabilities);
|
|
capabilities->Assign(0, ${val.ntlm.capabilities_raw_mode});
|
|
capabilities->Assign(1, ${val.ntlm.capabilities_mpx_mode});
|
|
capabilities->Assign(2, ${val.ntlm.capabilities_unicode});
|
|
capabilities->Assign(3, ${val.ntlm.capabilities_large_files});
|
|
capabilities->Assign(4, ${val.ntlm.capabilities_nt_smbs});
|
|
|
|
capabilities->Assign(5, ${val.ntlm.capabilities_rpc_remote_apis});
|
|
capabilities->Assign(6, ${val.ntlm.capabilities_status32});
|
|
capabilities->Assign(7, ${val.ntlm.capabilities_level_2_oplocks});
|
|
capabilities->Assign(8, ${val.ntlm.capabilities_lock_and_read});
|
|
capabilities->Assign(9, ${val.ntlm.capabilities_nt_find});
|
|
|
|
capabilities->Assign(10, ${val.ntlm.capabilities_dfs});
|
|
capabilities->Assign(11, ${val.ntlm.capabilities_infolevel_passthru});
|
|
capabilities->Assign(12, ${val.ntlm.capabilities_large_readx});
|
|
capabilities->Assign(13, ${val.ntlm.capabilities_large_writex});
|
|
capabilities->Assign(14, ${val.ntlm.capabilities_unix});
|
|
|
|
capabilities->Assign(15, ${val.ntlm.capabilities_bulk_transfer});
|
|
capabilities->Assign(16, ${val.ntlm.capabilities_compressed_data});
|
|
capabilities->Assign(17, ${val.ntlm.capabilities_extended_security});
|
|
|
|
auto ntlm = zeek::make_intrusive<zeek::RecordVal>(zeek::BifType::Record::SMB1::NegotiateResponseNTLM);
|
|
ntlm->Assign(0, ${val.word_count});
|
|
ntlm->Assign(1, ${val.dialect_index});
|
|
ntlm->Assign(2, std::move(security));
|
|
ntlm->Assign(3, ${val.ntlm.max_buffer_size});
|
|
ntlm->Assign(4, ${val.ntlm.max_mpx_count});
|
|
|
|
ntlm->Assign(5, ${val.ntlm.max_number_vcs});
|
|
ntlm->Assign(6, ${val.ntlm.max_raw_size});
|
|
ntlm->Assign(7, ${val.ntlm.session_key});
|
|
ntlm->Assign(8, std::move(capabilities));
|
|
ntlm->Assign(9, filetime2zeektime(${val.ntlm.server_time}));
|
|
|
|
if ( ${val.ntlm.capabilities_extended_security} == false )
|
|
{
|
|
ntlm->Assign(10, to_stringval(${val.ntlm.encryption_key}));
|
|
ntlm->Assign(11, smb_string2stringval(${val.ntlm.domain_name}));
|
|
}
|
|
else
|
|
{
|
|
ntlm->Assign(12, to_stringval(${val.ntlm.server_guid}));
|
|
}
|
|
|
|
response->Assign(2, std::move(ntlm));
|
|
}
|
|
break;
|
|
}
|
|
zeek::BifEvent::enqueue_smb1_negotiate_response(zeek_analyzer(),
|
|
zeek_analyzer()->Conn(),
|
|
SMBHeaderVal(header),
|
|
std::move(response));
|
|
}
|
|
|
|
return true;
|
|
%}
|
|
};
|
|
|
|
type SMB_dialect = record {
|
|
buffer_format : uint8; # must be 0x2 for dialect
|
|
name : SMB_string(false, 0);
|
|
};
|
|
|
|
type SMB1_negotiate_request(header: SMB_Header) = record {
|
|
word_count: uint8; # must be 0
|
|
byte_count: uint16;
|
|
dialects: SMB_dialect[] &length=byte_count;
|
|
} &let {
|
|
proc : bool = $context.connection.proc_smb1_negotiate_request(header, this);
|
|
};
|
|
|
|
type SMB1_negotiate_response(header: SMB_Header) = record {
|
|
word_count: uint8;
|
|
dialect_index: uint16;
|
|
response: case word_count of {
|
|
0x01 -> core : SMB1_negotiate_core_response;
|
|
0x0d -> lanman : SMB1_negotiate_lanman_response(header);
|
|
0x11 -> ntlm : SMB1_negotiate_ntlm_response(header);
|
|
};
|
|
} &let {
|
|
proc: bool = $context.connection.proc_smb1_negotiate_response(header, this);
|
|
};
|
|
|
|
type SMB1_negotiate_core_response = record {
|
|
byte_count: uint16;
|
|
};
|
|
|
|
type SMB1_negotiate_lanman_response(header: SMB_Header) = record {
|
|
security_flags : uint16; # expanded in &let
|
|
max_buffer_size : uint16;
|
|
max_mpx_count : uint16;
|
|
max_number_vcs : uint16;
|
|
raw_mode : uint16; # expanded in &let
|
|
session_key : uint32;
|
|
server_time : uint16;
|
|
server_date : uint16;
|
|
server_tz : uint16;
|
|
encryption_key_length : uint16;
|
|
reserved : uint16; # must be zero
|
|
byte_count : uint16; # count of data bytes
|
|
encryption_key : bytestring &length=encryption_key_length;
|
|
primary_domain : SMB_string(header.unicode, offsetof(primary_domain));
|
|
} &let {
|
|
security_user_level : bool = ( security_flags & 0x1 ) > 0;
|
|
security_challenge_response : bool = ( security_flags & 0x2 ) > 0;
|
|
raw_read_supported : bool = ( raw_mode & 0x1 ) > 0;
|
|
raw_write_supported : bool = ( raw_mode & 0x2 ) > 0;
|
|
};
|
|
|
|
type SMB1_negotiate_ntlm_response(header: SMB_Header) = record {
|
|
security_flags : uint8; # Expanded in &let
|
|
max_mpx_count : uint16;
|
|
max_number_vcs : uint16;
|
|
max_buffer_size : uint32;
|
|
max_raw_size : uint32;
|
|
session_key : uint32;
|
|
capabilities : uint32; # Expanded in &let
|
|
server_time : uint64;
|
|
server_tz : uint16;
|
|
encryption_key_length : uint8;
|
|
byte_count : uint16;
|
|
encryption_key_present: case capabilities_extended_security of {
|
|
false -> encryption_key : bytestring &length=encryption_key_length;
|
|
true -> no_key : empty;
|
|
} &requires(capabilities_extended_security);
|
|
domain_name_present: case capabilities_extended_security of {
|
|
false -> domain_name : SMB_string(header.unicode, offsetof(domain_name_present));
|
|
true -> no_name : empty;
|
|
} &requires(capabilities_extended_security);
|
|
server_guid_present: case capabilities_extended_security of {
|
|
true -> server_guid : bytestring &length=16;
|
|
false -> no_guid : empty;
|
|
} &requires(capabilities_extended_security);
|
|
security_blob_present: case capabilities_extended_security of {
|
|
true -> security_blob : bytestring &length=(byte_count-16);
|
|
false -> no_blob : empty;
|
|
} &requires(capabilities_extended_security);
|
|
} &let {
|
|
security_user_level : bool = (security_flags & 0x1) > 0;
|
|
security_challenge_response : bool = (security_flags & 0x2) > 0;
|
|
security_signatures_enabled : bool = (security_flags & 0x4) > 0;
|
|
security_signatures_required : bool = (security_flags & 0x8) > 0;
|
|
capabilities_raw_mode : bool = (capabilities & 0x1) > 0;
|
|
capabilities_mpx_mode : bool = (capabilities & 0x2) > 0;
|
|
capabilities_unicode : bool = (capabilities & 0x4) > 0;
|
|
capabilities_large_files : bool = (capabilities & 0x8) > 0;
|
|
capabilities_nt_smbs : bool = (capabilities & 0x10) > 0;
|
|
capabilities_rpc_remote_apis : bool = (capabilities & 0x20) > 0;
|
|
capabilities_status32 : bool = (capabilities & 0x40) > 0;
|
|
capabilities_level_2_oplocks : bool = (capabilities & 0x80) > 0;
|
|
capabilities_lock_and_read : bool = (capabilities & 0x100) > 0;
|
|
capabilities_nt_find : bool = (capabilities & 0x200) > 0;
|
|
capabilities_dfs : bool = (capabilities & 0x1000) > 0;
|
|
capabilities_infolevel_passthru : bool = (capabilities & 0x2000) > 0;
|
|
capabilities_large_readx : bool = (capabilities & 0x4000) > 0;
|
|
capabilities_large_writex : bool = (capabilities & 0x8000) > 0;
|
|
capabilities_unix : bool = (capabilities & 0x00800000) > 0;
|
|
capabilities_reserved : bool = (capabilities & 0x02000000) > 0;
|
|
capabilities_bulk_transfer : bool = (capabilities & 0x20000000) > 0;
|
|
capabilities_compressed_data : bool = (capabilities & 0x40000000) > 0;
|
|
capabilities_extended_security : bool = (capabilities & 0x80000000) > 0;
|
|
|
|
gssapi_proc : bool = $context.connection.forward_gssapi(security_blob, false) &if(capabilities_extended_security);
|
|
};
|