mirror of
https://github.com/zeek/zeek.git
synced 2025-10-02 14:48:21 +00:00
Complete breakout of SMB, GSSAPI, and NTLM
- Looser coupling between these analyzers. - New ntlm.log (still pretty early) - Improved string handling for NTLM (convert UTF16 to UTF8) - SMB2 analyzer now supports GSSAPI. - Improved abstraction of DCE_RPC operations (still not finished) - Lots of whitespace cleanup.
This commit is contained in:
parent
ff3437d157
commit
5b5589e167
22 changed files with 446 additions and 926 deletions
|
@ -2315,18 +2315,10 @@ type ntp_msg: record {
|
|||
};
|
||||
|
||||
|
||||
module SMB;
|
||||
module NTLM;
|
||||
|
||||
export {
|
||||
## MAC times for a file.
|
||||
type SMB::MACTimes: record {
|
||||
modified : time &log;
|
||||
accessed : time &log;
|
||||
created : time &log;
|
||||
changed : time &log;
|
||||
} &log;
|
||||
|
||||
type SMB::NTLMVersion: record {
|
||||
type NTLM::Version: record {
|
||||
## The major version of the Windows operating system in use
|
||||
major : count;
|
||||
## The minor version of the Windows operating system in use
|
||||
|
@ -2337,7 +2329,7 @@ export {
|
|||
ntlmssp : count;
|
||||
};
|
||||
|
||||
type SMB::NTLMNegotiateFlags: record {
|
||||
type NTLM::NegotiateFlags: record {
|
||||
## If set, requires 56-bit encryption
|
||||
negotiate_56 : bool;
|
||||
## If set, requests an explicit key exchange
|
||||
|
@ -2349,7 +2341,6 @@ export {
|
|||
## If set, indicates that the TargetInfo fields in the
|
||||
## CHALLENGE_MESSAGE are populated
|
||||
negotiate_target_info : bool;
|
||||
|
||||
## If set, requests the usage of the LMOWF function
|
||||
request_non_nt_session_key : bool;
|
||||
## If set, requests and identify level token
|
||||
|
@ -2393,18 +2384,18 @@ export {
|
|||
negotiate_unicode : bool;
|
||||
};
|
||||
|
||||
type SMB::NTLMNegotiate: record {
|
||||
type NTLM::Negotiate: record {
|
||||
## The negotiate flags
|
||||
flags : SMB::NTLMNegotiateFlags;
|
||||
flags : NTLM::NegotiateFlags;
|
||||
## The domain name of the client, if known
|
||||
domain_name : string &optional;
|
||||
## The machine name of the client, if known
|
||||
workstation : string &optional;
|
||||
## The Windows version information, if supplied
|
||||
version : SMB::NTLMVersion &optional;
|
||||
version : NTLM::Version &optional;
|
||||
};
|
||||
|
||||
type SMB::NTLMAVs: record {
|
||||
type NTLM::AVs: record {
|
||||
## The server's NetBIOS computer name
|
||||
nb_computer_name : string;
|
||||
## The server's NetBIOS domain name
|
||||
|
@ -2422,7 +2413,7 @@ export {
|
|||
## The associated timestamp, if present
|
||||
timestamp : time &optional;
|
||||
## Indicates that the client is providing
|
||||
## mess achine ID created at computer startup to
|
||||
## a machine ID created at computer startup to
|
||||
## identify the calling machine
|
||||
single_host_id : count &optional;
|
||||
|
||||
|
@ -2430,23 +2421,23 @@ export {
|
|||
target_name : string &optional;
|
||||
};
|
||||
|
||||
type SMB::NTLMChallenge: record {
|
||||
type NTLM::Challenge: record {
|
||||
## The negotiate flags
|
||||
flags : SMB::NTLMNegotiateFlags;
|
||||
flags : NTLM::NegotiateFlags;
|
||||
## The server authentication realm. If the server is
|
||||
## domain-joined, the name of the domain. Otherwise
|
||||
## the server name. See flags.target_type_domain
|
||||
## and flags.target_type_server
|
||||
target_name : string &optional;
|
||||
## The Windows version information, if supplied
|
||||
version : SMB::NTLMVersion &optional;
|
||||
version : NTLM::Version &optional;
|
||||
## Attribute-value pairs specified by the server
|
||||
target_info : SMB::NTLMAVs &optional;
|
||||
target_info : NTLM::AVs &optional;
|
||||
};
|
||||
|
||||
type SMB::NTLMAuthenticate: record {
|
||||
type NTLM::Authenticate: record {
|
||||
## The negotiate flags
|
||||
flags : SMB::NTLMNegotiateFlags;
|
||||
flags : NTLM::NegotiateFlags;
|
||||
## The domain or computer name hosting the account
|
||||
domain_name : string;
|
||||
## The name of the user to be authenticated.
|
||||
|
@ -2454,9 +2445,20 @@ export {
|
|||
## The name of the computer to which the user was logged on.
|
||||
workstation : string;
|
||||
## The Windows version information, if supplied
|
||||
version : SMB::NTLMVersion &optional;
|
||||
version : NTLM::Version &optional;
|
||||
};
|
||||
}
|
||||
|
||||
module SMB;
|
||||
|
||||
export {
|
||||
## MAC times for a file.
|
||||
type SMB::MACTimes: record {
|
||||
modified : time &log;
|
||||
accessed : time &log;
|
||||
created : time &log;
|
||||
changed : time &log;
|
||||
} &log;
|
||||
}
|
||||
|
||||
module SMB1;
|
||||
|
|
|
@ -53,6 +53,7 @@
|
|||
@load base/protocols/krb
|
||||
@load base/protocols/modbus
|
||||
@load base/protocols/mysql
|
||||
@load base/protocols/ntlm
|
||||
@load base/protocols/pop3
|
||||
@load base/protocols/radius
|
||||
@load base/protocols/rdp
|
||||
|
|
1
scripts/base/protocols/ntlm/__load__.bro
Normal file
1
scripts/base/protocols/ntlm/__load__.bro
Normal file
|
@ -0,0 +1 @@
|
|||
@load ./main
|
54
scripts/base/protocols/ntlm/main.bro
Normal file
54
scripts/base/protocols/ntlm/main.bro
Normal file
|
@ -0,0 +1,54 @@
|
|||
module NTLM;
|
||||
|
||||
export {
|
||||
redef enum Log::ID += { LOG };
|
||||
|
||||
type Info: record {
|
||||
## Timestamp for when the event happened.
|
||||
ts : time &log;
|
||||
## Unique ID for the connection.
|
||||
uid : string &log;
|
||||
## The connection's 4-tuple of endpoint addresses/ports.
|
||||
id : conn_id &log;
|
||||
|
||||
username: string &log &optional;
|
||||
hostname: string &log &optional;
|
||||
domainname: string &log &optional;
|
||||
};
|
||||
}
|
||||
|
||||
redef record connection += {
|
||||
ntlm: Info &optional;
|
||||
};
|
||||
|
||||
event bro_init() &priority=5
|
||||
{
|
||||
Log::create_stream(NTLM::LOG, [$columns=Info, $path="ntlm"]);
|
||||
}
|
||||
|
||||
event ntlm_negotiate(c: connection, request: NTLM::Negotiate) &priority=5
|
||||
{
|
||||
#print request;
|
||||
}
|
||||
|
||||
event ntlm_challenge(c: connection, challenge: NTLM::Challenge) &priority=5
|
||||
{
|
||||
#print "challenge!!!!!";
|
||||
#print challenge;
|
||||
}
|
||||
|
||||
event ntlm_authenticate(c: connection, request: NTLM::Authenticate) &priority=5
|
||||
{
|
||||
c$ntlm = NTLM::Info($ts=network_time(), $uid=c$uid, $id=c$id);
|
||||
if ( request?$domain_name )
|
||||
c$ntlm$domainname = request$domain_name;
|
||||
if ( request?$workstation )
|
||||
c$ntlm$hostname = request$workstation;
|
||||
if ( request?$user_name )
|
||||
c$ntlm$username = request$user_name;
|
||||
}
|
||||
|
||||
event ntlm_authenticate(c: connection, request: NTLM::Authenticate) &priority=-5
|
||||
{
|
||||
Log::write(NTLM::LOG, c$ntlm);
|
||||
}
|
|
@ -281,51 +281,6 @@ event smb1_session_setup_andx_response(c: connection, hdr: SMB1::Header, respons
|
|||
}
|
||||
}
|
||||
|
||||
event smb_ntlm_negotiate(c: connection, hdr: SMB1::Header, request: SMB::NTLMNegotiate)
|
||||
{
|
||||
c$smb_state$current_cmd$sub_command = "NTLMSSP_NEGOTIATE";
|
||||
}
|
||||
|
||||
event smb_ntlm_authenticate(c: connection, hdr: SMB1::Header, request: SMB::NTLMAuthenticate) &priority=5
|
||||
{
|
||||
c$smb_state$current_cmd$sub_command = "NTLMSSP_AUTHENTICATE";
|
||||
|
||||
c$smb_state$current_auth = SMB::AuthInfo($ts=network_time(), $uid=c$uid, $id=c$id);
|
||||
if ( request?$domain_name )
|
||||
c$smb_state$current_auth$domainname = request$domain_name;
|
||||
if ( request?$workstation )
|
||||
c$smb_state$current_auth$hostname = request$workstation;
|
||||
if ( request?$user_name )
|
||||
c$smb_state$current_auth$username = request$user_name;
|
||||
|
||||
local user: string = "";
|
||||
if ( ( request?$domain_name && request$domain_name != "" ) && ( request?$user_name && request$user_name != "" ) )
|
||||
user = fmt("%s\\%s", request$domain_name, request$user_name);
|
||||
else if ( ( request?$workstation && request$workstation != "" ) && ( request?$user_name && request$user_name != "" ) )
|
||||
user = fmt("%s\\%s", request$workstation, request$user_name);
|
||||
else if ( request?$user_name && request$user_name != "" )
|
||||
user = request$user_name;
|
||||
else if ( request?$domain_name && request$domain_name != "" )
|
||||
user = fmt("%s\\", request$domain_name);
|
||||
else if ( request?$workstation && request$workstation != "" )
|
||||
user = fmt("%s", request$workstation);
|
||||
|
||||
if ( user != "" )
|
||||
{
|
||||
c$smb_state$current_cmd$argument = user;
|
||||
}
|
||||
|
||||
if ( hdr$uid !in c$smb_state$uid_map )
|
||||
{
|
||||
c$smb_state$uid_map[hdr$uid] = user;
|
||||
}
|
||||
}
|
||||
|
||||
event smb_ntlm_authenticate(c: connection, hdr: SMB1::Header, request: SMB::NTLMAuthenticate) &priority=5
|
||||
{
|
||||
Log::write(SMB::AUTH_LOG, c$smb_state$current_auth);
|
||||
}
|
||||
|
||||
event smb1_transaction_request(c: connection, hdr: SMB1::Header, name: string, sub_cmd: count)
|
||||
{
|
||||
c$smb_state$current_cmd$sub_command = SMB1::trans_sub_commands[sub_cmd];
|
||||
|
|
|
@ -12,6 +12,7 @@ add_subdirectory(file)
|
|||
add_subdirectory(finger)
|
||||
add_subdirectory(ftp)
|
||||
add_subdirectory(gnutella)
|
||||
add_subdirectory(gssapi)
|
||||
add_subdirectory(gtpv1)
|
||||
add_subdirectory(http)
|
||||
add_subdirectory(icmp)
|
||||
|
@ -25,6 +26,7 @@ add_subdirectory(modbus)
|
|||
add_subdirectory(mysql)
|
||||
add_subdirectory(ncp)
|
||||
add_subdirectory(netbios)
|
||||
add_subdirectory(ntlm)
|
||||
add_subdirectory(ntp)
|
||||
add_subdirectory(pia)
|
||||
add_subdirectory(pop3)
|
||||
|
|
|
@ -10,7 +10,9 @@ bro_plugin_pac(
|
|||
dce_rpc.pac
|
||||
dce_rpc-protocol.pac
|
||||
dce_rpc-analyzer.pac
|
||||
dce_rpc-gssapi.pac
|
||||
endpoint-atsvc.pac
|
||||
endpoint-epmapper.pac
|
||||
endpoint-atsvc.pac)
|
||||
)
|
||||
bro_plugin_end()
|
||||
|
||||
|
|
42
src/analyzer/protocol/dce-rpc/dce_rpc-gssapi.pac
Normal file
42
src/analyzer/protocol/dce-rpc/dce_rpc-gssapi.pac
Normal file
|
@ -0,0 +1,42 @@
|
|||
refine connection DCE_RPC_Conn += {
|
||||
%member{
|
||||
analyzer::Analyzer *gssapi;
|
||||
analyzer::Analyzer *ntlm;
|
||||
%}
|
||||
|
||||
%init{
|
||||
gssapi = analyzer_mgr->InstantiateAnalyzer("GSSAPI", bro_analyzer->Conn());
|
||||
ntlm = analyzer_mgr->InstantiateAnalyzer("NTLM", bro_analyzer->Conn());
|
||||
%}
|
||||
|
||||
%cleanup{
|
||||
if ( gssapi )
|
||||
delete gssapi;
|
||||
if ( ntlm )
|
||||
delete ntlm;
|
||||
%}
|
||||
|
||||
function forward_auth(auth: DCE_RPC_Auth, is_orig: bool): bool
|
||||
%{
|
||||
switch ( ${auth.type} )
|
||||
{
|
||||
case 0x0a:
|
||||
if ( ntlm )
|
||||
ntlm->DeliverStream(${auth.blob}.length(), ${auth.blob}.begin(), is_orig);
|
||||
break;
|
||||
//case 0xXX:
|
||||
// if ( gssapi )
|
||||
// gssapi->DeliverStream(${data}.length(), ${data}.begin(), is_orig);
|
||||
// break;
|
||||
default:
|
||||
bro_analyzer()->Weird(fmt("unknown_dce_rpc_auth_type_%d",${auth.type}));
|
||||
break;
|
||||
}
|
||||
|
||||
return true;
|
||||
%}
|
||||
};
|
||||
|
||||
refine typeattr DCE_RPC_Auth += &let {
|
||||
proc = $context.connection.forward_auth(this, true);
|
||||
}
|
|
@ -23,5 +23,6 @@ flow DCE_RPC_Flow(is_orig: bool) {
|
|||
flowunit = DCE_RPC_PDU(is_orig) withcontext(connection, this);
|
||||
};
|
||||
|
||||
%include epmapper.pac
|
||||
%include endpoint-atsvc.pac
|
||||
%include endpoint-epmapper.pac
|
||||
%include dce_rpc-analyzer.pac
|
||||
|
|
|
@ -1,38 +1,41 @@
|
|||
type ATSVC_Request(unicode: bool, opnum: uint8) = record {
|
||||
empty: padding[1];
|
||||
op: case opnum of {
|
||||
0 -> add : ATSVC_NetrJobAdd(unicode);
|
||||
default -> unknown : bytestring &restofdata;
|
||||
};
|
||||
};
|
||||
|
||||
type ATSVC_String_Pointer(unicode: bool) = record {
|
||||
referent_id : uint32;
|
||||
max_count : uint32;
|
||||
offset : uint32;
|
||||
actual_count : uint32;
|
||||
string : SMB_string(unicode, offsetof(string));
|
||||
};
|
||||
|
||||
type ATSVC_NetrJobAdd(unicode: bool) = record {
|
||||
server : ATSVC_String_Pointer(unicode);
|
||||
unknown : padding[2];
|
||||
job_time : uint32;
|
||||
days_of_month : uint32;
|
||||
days_of_week : uint8;
|
||||
flags : uint8;
|
||||
unknown2 : padding[2];
|
||||
command : ATSVC_String_Pointer(unicode);
|
||||
};
|
||||
|
||||
type ATSVC_Reply(unicode: bool, opnum: uint16) = record {
|
||||
op: case opnum of {
|
||||
0 -> add: ATSVC_JobID(unicode);
|
||||
default -> unknown: bytestring &restofdata;
|
||||
};
|
||||
};
|
||||
|
||||
type ATSVC_JobID(unicode: bool) = record {
|
||||
id : uint32;
|
||||
status : uint32;
|
||||
};
|
||||
#%include ../smb/smb-strings.pac
|
||||
#
|
||||
#type ATSVC_Request(unicode: bool, opnum: uint8) = record {
|
||||
# empty: padding[1];
|
||||
# op: case opnum of {
|
||||
# 0 -> add : ATSVC_NetrJobAdd(unicode);
|
||||
# default -> unknown : bytestring &restofdata;
|
||||
# };
|
||||
#};
|
||||
#
|
||||
#type ATSVC_String_Pointer(unicode: bool) = record {
|
||||
# referent_id : uint32;
|
||||
# max_count : uint32;
|
||||
# offset : uint32;
|
||||
# actual_count : uint32;
|
||||
# string : SMB_string(unicode, offsetof(string));
|
||||
#};
|
||||
#
|
||||
#type ATSVC_NetrJobAdd(unicode: bool) = record {
|
||||
# server : ATSVC_String_Pointer(unicode);
|
||||
# unknown : padding[2];
|
||||
# job_time : uint32;
|
||||
# days_of_month : uint32;
|
||||
# days_of_week : uint8;
|
||||
# flags : uint8;
|
||||
# unknown2 : padding[2];
|
||||
# command : ATSVC_String_Pointer(unicode);
|
||||
#};
|
||||
#
|
||||
#type ATSVC_Reply(unicode: bool, opnum: uint16) = record {
|
||||
# op: case opnum of {
|
||||
# 0 -> add: ATSVC_JobID(unicode);
|
||||
# default -> unknown: bytestring &restofdata;
|
||||
# };
|
||||
#};
|
||||
#
|
||||
#type ATSVC_JobID(unicode: bool) = record {
|
||||
# id : uint32;
|
||||
# status : uint32;
|
||||
#};
|
||||
#
|
|
@ -6,9 +6,6 @@ include_directories(AFTER ${CMAKE_CURRENT_BINARY_DIR}/../dce-rpc)
|
|||
bro_plugin_begin(Bro SMB)
|
||||
bro_plugin_cc(SMB.cc Plugin.cc)
|
||||
bro_plugin_bif(
|
||||
smb_ntlmssp.bif
|
||||
smb_pipe.bif
|
||||
|
||||
smb1_com_check_directory.bif
|
||||
smb1_com_close.bif
|
||||
smb1_com_create_directory.bif
|
||||
|
@ -40,6 +37,7 @@ bro_plugin_bif(
|
|||
smb2_com_write.bif
|
||||
smb2_events.bif
|
||||
|
||||
smb_pipe.bif
|
||||
types.bif)
|
||||
bro_plugin_pac(
|
||||
smb.pac
|
||||
|
@ -47,8 +45,8 @@ bro_plugin_pac(
|
|||
smb-strings.pac
|
||||
smb-time.pac
|
||||
smb-pipe.pac
|
||||
smb-gssapi.pac
|
||||
smb-mailslot.pac
|
||||
smb-ntlmssp.pac
|
||||
|
||||
smb1-protocol.pac
|
||||
smb1-com-check-directory.pac
|
||||
|
|
|
@ -10,14 +10,6 @@
|
|||
|
||||
namespace analyzer { namespace smb {
|
||||
|
||||
enum IPC_named_pipe {
|
||||
IPC_NONE,
|
||||
IPC_LOCATOR,
|
||||
IPC_EPMAPPER,
|
||||
IPC_SAMR, // Security Account Manager
|
||||
};
|
||||
|
||||
|
||||
class Contents_SMB : public tcp::TCP_SupportAnalyzer {
|
||||
public:
|
||||
Contents_SMB(Connection* conn, bool orig);
|
||||
|
|
11
src/analyzer/protocol/smb/smb-gssapi.pac
Normal file
11
src/analyzer/protocol/smb/smb-gssapi.pac
Normal file
|
@ -0,0 +1,11 @@
|
|||
|
||||
refine connection SMB_Conn += {
|
||||
|
||||
function forward_gssapi(data: bytestring, is_orig: bool): bool
|
||||
%{
|
||||
if ( gssapi )
|
||||
gssapi->DeliverStream(${data}.length(), ${data}.begin(), is_orig);
|
||||
|
||||
return true;
|
||||
%}
|
||||
};
|
|
@ -1,57 +0,0 @@
|
|||
# Supporting types for ASN.1
|
||||
#
|
||||
# From the Kerberos analyzer
|
||||
#
|
||||
# TODO: Figure out a way to include this code only once.
|
||||
|
||||
type ASN1Encoding = record {
|
||||
meta: ASN1EncodingMeta;
|
||||
content: bytestring &length = meta.length;
|
||||
};
|
||||
|
||||
type ASN1EncodingMeta = record {
|
||||
tag: uint8;
|
||||
len: uint8;
|
||||
more_len: bytestring &length = long_len ? len & 0x7f : 0;
|
||||
} &let {
|
||||
long_len: bool = len & 0x80;
|
||||
length: uint64 = long_len ? binary_to_int64(more_len) : len & 0x7f;
|
||||
index: uint8 = tag - 160;
|
||||
};
|
||||
|
||||
type ASN1Integer = record {
|
||||
encoding: ASN1Encoding;
|
||||
};
|
||||
|
||||
type ASN1OctetString = record {
|
||||
encoding: ASN1Encoding;
|
||||
};
|
||||
|
||||
type SequenceElement(grab_content: bool) = record {
|
||||
index_meta: ASN1EncodingMeta;
|
||||
have_content: case grab_content of {
|
||||
true -> data: ASN1Encoding;
|
||||
false -> meta: ASN1EncodingMeta;
|
||||
};
|
||||
} &let {
|
||||
index: uint8 = index_meta.index;
|
||||
length: uint64 = index_meta.length;
|
||||
};
|
||||
|
||||
type Array = record {
|
||||
array_meta: ASN1EncodingMeta;
|
||||
data: ASN1Encoding[];
|
||||
};
|
||||
|
||||
function binary_to_int64(bs: bytestring): int64
|
||||
%{
|
||||
int64 rval = 0;
|
||||
|
||||
for ( int i = 0; i < bs.length(); ++i )
|
||||
{
|
||||
uint64 byte = bs[i];
|
||||
rval |= byte << (8 * (bs.length() - (i + 1)));
|
||||
}
|
||||
|
||||
return rval;
|
||||
%}
|
|
@ -1,430 +0,0 @@
|
|||
refine connection SMB_Conn += {
|
||||
function build_negotiate_flag_record(val: SMB_NTLM_Negotiate_Flags): BroVal
|
||||
%{
|
||||
RecordVal* flags = new RecordVal(BifType::Record::SMB::NTLMNegotiateFlags);
|
||||
flags->Assign(0, new Val(${val.negotiate_56}, TYPE_BOOL));
|
||||
flags->Assign(1, new Val(${val.negotiate_key_exch}, TYPE_BOOL));
|
||||
flags->Assign(2, new Val(${val.negotiate_128}, TYPE_BOOL));
|
||||
flags->Assign(3, new Val(${val.negotiate_version}, TYPE_BOOL));
|
||||
flags->Assign(4, new Val(${val.negotiate_target_info}, TYPE_BOOL));
|
||||
|
||||
flags->Assign(5, new Val(${val.request_non_nt_session_key}, TYPE_BOOL));
|
||||
flags->Assign(6, new Val(${val.negotiate_identify}, TYPE_BOOL));
|
||||
flags->Assign(7, new Val(${val.negotiate_extended_sessionsecurity}, TYPE_BOOL));
|
||||
flags->Assign(8, new Val(${val.target_type_server}, TYPE_BOOL));
|
||||
flags->Assign(9, new Val(${val.target_type_domain}, TYPE_BOOL));
|
||||
|
||||
flags->Assign(10, new Val(${val.negotiate_always_sign}, TYPE_BOOL));
|
||||
flags->Assign(11, new Val(${val.negotiate_oem_workstation_supplied}, TYPE_BOOL));
|
||||
flags->Assign(12, new Val(${val.negotiate_oem_domain_supplied}, TYPE_BOOL));
|
||||
flags->Assign(13, new Val(${val.negotiate_anonymous_connection}, TYPE_BOOL));
|
||||
flags->Assign(14, new Val(${val.negotiate_ntlm}, TYPE_BOOL));
|
||||
|
||||
flags->Assign(15, new Val(${val.negotiate_lm_key}, TYPE_BOOL));
|
||||
flags->Assign(16, new Val(${val.negotiate_datagram}, TYPE_BOOL));
|
||||
flags->Assign(17, new Val(${val.negotiate_seal}, TYPE_BOOL));
|
||||
flags->Assign(18, new Val(${val.negotiate_sign}, TYPE_BOOL));
|
||||
flags->Assign(19, new Val(${val.request_target}, TYPE_BOOL));
|
||||
|
||||
flags->Assign(20, new Val(${val.negotiate_oem}, TYPE_BOOL));
|
||||
flags->Assign(21, new Val(${val.negotiate_unicode}, TYPE_BOOL));
|
||||
|
||||
return flags;
|
||||
%}
|
||||
|
||||
function build_version_record(val: SMB_NTLM_Version): BroVal
|
||||
%{
|
||||
RecordVal* result = new RecordVal(BifType::Record::SMB::NTLMVersion);
|
||||
result->Assign(0, new Val(${val.major_version}, TYPE_COUNT));
|
||||
result->Assign(1, new Val(${val.minor_version}, TYPE_COUNT));
|
||||
result->Assign(2, new Val(${val.build_number}, TYPE_COUNT));
|
||||
result->Assign(3, new Val(${val.ntlm_revision}, TYPE_COUNT));
|
||||
|
||||
return result;
|
||||
%}
|
||||
|
||||
function build_av_record(val: SMB_NTLM_AV_Pair_Sequence): BroVal
|
||||
%{
|
||||
RecordVal* result = new RecordVal(BifType::Record::SMB::NTLMAVs);
|
||||
for ( uint i = 0; ${val.pairs[i].id} != 0; i++ )
|
||||
{
|
||||
switch ( ${val.pairs[i].id} )
|
||||
{
|
||||
case 1:
|
||||
result->Assign(0, uint8s_to_stringval(${val.pairs[i].nb_computer_name.data}));
|
||||
break;
|
||||
case 2:
|
||||
result->Assign(1, uint8s_to_stringval(${val.pairs[i].nb_domain_name.data}));
|
||||
break;
|
||||
case 3:
|
||||
result->Assign(2, uint8s_to_stringval(${val.pairs[i].dns_computer_name.data}));
|
||||
break;
|
||||
case 4:
|
||||
result->Assign(3, uint8s_to_stringval(${val.pairs[i].dns_domain_name.data}));
|
||||
break;
|
||||
case 5:
|
||||
result->Assign(4, uint8s_to_stringval(${val.pairs[i].dns_tree_name.data}));
|
||||
break;
|
||||
case 6:
|
||||
result->Assign(5, new Val(${val.pairs[i].constrained_auth}, TYPE_BOOL));
|
||||
break;
|
||||
case 7:
|
||||
result->Assign(6, filetime2brotime(${val.pairs[i].timestamp}));
|
||||
break;
|
||||
case 8:
|
||||
result->Assign(7, new Val(${val.pairs[i].single_host.machine_id}, TYPE_COUNT));
|
||||
break;
|
||||
case 9:
|
||||
result->Assign(8, uint8s_to_stringval(${val.pairs[i].target_name.data}));
|
||||
break;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
%}
|
||||
|
||||
function proc_smb_ntlm_ssp(header: SMB_Header, val:SMB_NTLM_SSP): bool
|
||||
%{
|
||||
if ( ${val.gssapi.is_init} )
|
||||
return true;
|
||||
|
||||
for ( uint i = 0; i < ${val.gssapi.resp.args}->size(); ++i )
|
||||
{
|
||||
switch ( ${val.gssapi.resp.args[i].seq_meta.index} )
|
||||
{
|
||||
case 0:
|
||||
if ( ${val.gssapi.resp.args[i].args.neg_state} == 0 )
|
||||
BifEvent::generate_smb_ntlm_accepted(bro_analyzer(), bro_analyzer()->Conn(), BuildHeaderVal(header));
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
%}
|
||||
|
||||
function proc_smb_ntlm_negotiate(header: SMB_Header, val: SMB_NTLM_Negotiate): bool
|
||||
%{
|
||||
RecordVal* result = new RecordVal(BifType::Record::SMB::NTLMNegotiate);
|
||||
result->Assign(0, build_negotiate_flag_record(${val.flags}));
|
||||
|
||||
if ( ${val.flags.negotiate_oem_domain_supplied} )
|
||||
result->Assign(1, uint8s_to_stringval(${val.domain_name.string.data}));
|
||||
|
||||
if ( ${val.flags.negotiate_oem_workstation_supplied} )
|
||||
result->Assign(2, uint8s_to_stringval(${val.workstation.string.data}));
|
||||
|
||||
if ( ${val.flags.negotiate_version} )
|
||||
result->Assign(3, build_version_record(${val.version}));
|
||||
|
||||
BifEvent::generate_smb_ntlm_negotiate(bro_analyzer(), bro_analyzer()->Conn(), BuildHeaderVal(header), result);
|
||||
|
||||
return true;
|
||||
%}
|
||||
|
||||
function proc_smb_ntlm_challenge(header: SMB_Header, val: SMB_NTLM_Challenge): bool
|
||||
%{
|
||||
RecordVal* result = new RecordVal(BifType::Record::SMB::NTLMChallenge);
|
||||
result->Assign(0, build_negotiate_flag_record(${val.flags}));
|
||||
|
||||
if ( ${val.flags.request_target} )
|
||||
result->Assign(1, uint8s_to_stringval(${val.target_name.string.data}));
|
||||
|
||||
if ( ${val.flags.negotiate_version} )
|
||||
result->Assign(2, build_version_record(${val.version}));
|
||||
|
||||
if ( ${val.flags.negotiate_target_info} )
|
||||
result->Assign(3, build_av_record(${val.target_info}));
|
||||
|
||||
BifEvent::generate_smb_ntlm_challenge(bro_analyzer(), bro_analyzer()->Conn(), BuildHeaderVal(header), result);
|
||||
|
||||
return true;
|
||||
%}
|
||||
|
||||
function proc_smb_ntlm_authenticate(header: SMB_Header, val: SMB_NTLM_Authenticate): bool
|
||||
%{
|
||||
RecordVal* result = new RecordVal(BifType::Record::SMB::NTLMAuthenticate);
|
||||
result->Assign(0, build_negotiate_flag_record(${val.flags}));
|
||||
|
||||
if ( ${val.domain_name_fields.length} > 0 )
|
||||
result->Assign(1, uint8s_to_stringval(${val.domain_name.string.data}));
|
||||
|
||||
if ( ${val.user_name_fields.length} > 0 )
|
||||
result->Assign(2, uint8s_to_stringval(${val.user_name.string.data}));
|
||||
|
||||
if ( ${val.workstation_fields.length} > 0 )
|
||||
result->Assign(3, uint8s_to_stringval(${val.workstation.string.data}));
|
||||
|
||||
if ( ${val.flags.negotiate_version} )
|
||||
result->Assign(4, build_version_record(${val.version}));
|
||||
|
||||
BifEvent::generate_smb_ntlm_authenticate(bro_analyzer(), bro_analyzer()->Conn(), BuildHeaderVal(header), result);
|
||||
|
||||
return true;
|
||||
%}
|
||||
};
|
||||
|
||||
type GSSAPI_NEG_TOKEN(header: SMB_Header) = record {
|
||||
wrapper : ASN1EncodingMeta;
|
||||
have_oid : case is_init of {
|
||||
true -> oid : ASN1Encoding;
|
||||
false -> no_oid : empty;
|
||||
};
|
||||
have_init_wrapper : case is_init of {
|
||||
true -> init_wrapper : ASN1EncodingMeta;
|
||||
false -> no_init_wrapper : empty;
|
||||
};
|
||||
msg_type : case is_init of {
|
||||
true -> init: GSSAPI_NEG_TOKEN_INIT(header);
|
||||
false -> resp: GSSAPI_NEG_TOKEN_RESP(header);
|
||||
};
|
||||
} &let {
|
||||
is_init: bool = (wrapper.tag == 0x60);
|
||||
};
|
||||
|
||||
type GSSAPI_NEG_TOKEN_INIT(header: SMB_Header) = record {
|
||||
seq_meta : ASN1EncodingMeta;
|
||||
args : GSSAPI_NEG_TOKEN_INIT_Arg(header)[];
|
||||
};
|
||||
|
||||
type GSSAPI_NEG_TOKEN_INIT_Arg(header: SMB_Header) = record {
|
||||
seq_meta : ASN1EncodingMeta;
|
||||
args : GSSAPI_NEG_TOKEN_INIT_Arg_Data(header, seq_meta.index) &length=seq_meta.length;
|
||||
};
|
||||
|
||||
type GSSAPI_NEG_TOKEN_INIT_Arg_Data(header: SMB_Header, index: uint8) = case index of {
|
||||
0 -> mech_type_list : ASN1Encoding;
|
||||
1 -> req_flags : ASN1Encoding;
|
||||
2 -> mech_token : SMB_NTLM_SSP_Token(header);
|
||||
3 -> mech_list_mic : ASN1OctetString;
|
||||
};
|
||||
|
||||
type GSSAPI_NEG_TOKEN_RESP(header: SMB_Header) = record {
|
||||
seq_meta : ASN1EncodingMeta;
|
||||
args : GSSAPI_NEG_TOKEN_RESP_Arg(header)[];
|
||||
};
|
||||
|
||||
type GSSAPI_NEG_TOKEN_RESP_Arg(header: SMB_Header) = record {
|
||||
seq_meta : ASN1EncodingMeta;
|
||||
args : GSSAPI_NEG_TOKEN_RESP_Arg_Data(header, seq_meta.index) &length=seq_meta.length;
|
||||
};
|
||||
|
||||
type GSSAPI_NEG_TOKEN_RESP_Arg_Data(header: SMB_Header, index: uint8) = case index of {
|
||||
0 -> neg_state : ASN1Integer;
|
||||
1 -> supported_mech : ASN1Encoding;
|
||||
2 -> response_token : SMB_NTLM_SSP_Token(header);
|
||||
3 -> mech_list_mic : ASN1OctetString;
|
||||
default -> def : bytestring &restofdata &transient;
|
||||
};
|
||||
|
||||
type SMB_NTLM_SSP(header: SMB_Header) = record {
|
||||
gssapi: GSSAPI_NEG_TOKEN(header);
|
||||
} &let {
|
||||
proc: bool = $context.connection.proc_smb_ntlm_ssp(header, this);
|
||||
};
|
||||
|
||||
type SMB_NTLM_SSP_Token(header: SMB_Header) = record {
|
||||
meta : ASN1EncodingMeta;
|
||||
signature : bytestring &length=8;
|
||||
msg_type : uint32;
|
||||
msg : case msg_type of {
|
||||
1 -> negotiate : SMB_NTLM_Negotiate(header, offsetof(msg) - offsetof(signature));
|
||||
2 -> challenge : SMB_NTLM_Challenge(header, offsetof(msg) - offsetof(signature));
|
||||
3 -> authenticate : SMB_NTLM_Authenticate(header, offsetof(msg) - offsetof(signature));
|
||||
default -> def : bytestring &restofdata &transient;
|
||||
};
|
||||
};
|
||||
|
||||
type SMB_NTLM_Negotiate(header: SMB_Header, offset: uint16) = record {
|
||||
flags : SMB_NTLM_Negotiate_Flags;
|
||||
domain_name_fields : SMB_NTLM_StringData;
|
||||
workstation_fields : SMB_NTLM_StringData;
|
||||
version_present : case flags.negotiate_version of {
|
||||
true -> version : SMB_NTLM_Version;
|
||||
false -> no_version : empty;
|
||||
};
|
||||
payload : bytestring &restofdata;
|
||||
} &let {
|
||||
absolute_offset : uint16 = offsetof(payload) + offset;
|
||||
domain_name : SMB_NTLM_String(domain_name_fields, absolute_offset, flags.negotiate_unicode) withinput payload &if(flags.negotiate_oem_domain_supplied);
|
||||
workstation : SMB_NTLM_String(workstation_fields, absolute_offset, flags.negotiate_unicode) withinput payload &if(flags.negotiate_oem_workstation_supplied);
|
||||
|
||||
proc : bool = $context.connection.proc_smb_ntlm_negotiate(header, this);
|
||||
};
|
||||
|
||||
type SMB_NTLM_Challenge(header: SMB_Header, offset: uint16) = record {
|
||||
target_name_fields : SMB_NTLM_StringData;
|
||||
flags : SMB_NTLM_Negotiate_Flags;
|
||||
challenge : uint64;
|
||||
reserved : padding[8];
|
||||
target_info_fields : SMB_NTLM_StringData;
|
||||
version_present : case flags.negotiate_version of {
|
||||
true -> version : SMB_NTLM_Version;
|
||||
false -> no_version : empty;
|
||||
};
|
||||
payload : bytestring &restofdata;
|
||||
} &let {
|
||||
absolute_offset : uint16 = offsetof(payload) + offset;
|
||||
target_name : SMB_NTLM_String(target_name_fields, absolute_offset, flags.negotiate_unicode) withinput payload &if(flags.request_target);
|
||||
target_info : SMB_NTLM_AV_Pair_Sequence(target_info_fields.offset - absolute_offset) withinput payload &if(flags.negotiate_target_info);
|
||||
|
||||
proc : bool = $context.connection.proc_smb_ntlm_challenge(header, this);
|
||||
};
|
||||
|
||||
type SMB_NTLM_Authenticate(header: SMB_Header, offset: uint16) = record {
|
||||
lm_challenge_response_fields : SMB_NTLM_StringData;
|
||||
nt_challenge_response_fields : SMB_NTLM_StringData;
|
||||
domain_name_fields : SMB_NTLM_StringData;
|
||||
user_name_fields : SMB_NTLM_StringData;
|
||||
workstation_fields : SMB_NTLM_StringData;
|
||||
encrypted_session_key_fields : SMB_NTLM_StringData;
|
||||
flags : SMB_NTLM_Negotiate_Flags;
|
||||
version_present : case flags.negotiate_version of {
|
||||
true -> version : SMB_NTLM_Version;
|
||||
false -> no_version : empty;
|
||||
};
|
||||
|
||||
# Windows NT, 2000, XP, and 2003 don't have the MIC field
|
||||
# TODO - figure out how to parse this for those that do have it
|
||||
# mic : bytestring &length=16;
|
||||
|
||||
payload : bytestring &restofdata;
|
||||
} &let {
|
||||
absolute_offset : uint16 = offsetof(payload) + offset;
|
||||
domain_name : SMB_NTLM_String(domain_name_fields, absolute_offset, flags.negotiate_unicode) withinput payload &if(domain_name_fields.length > 0);
|
||||
user_name : SMB_NTLM_String(user_name_fields, absolute_offset, flags.negotiate_unicode) withinput payload &if(user_name_fields.length > 0);
|
||||
workstation : SMB_NTLM_String(workstation_fields, absolute_offset , flags.negotiate_unicode) withinput payload &if(workstation_fields.length > 0);
|
||||
encrypted_session_key : SMB_NTLM_String(encrypted_session_key_fields, absolute_offset, flags.negotiate_unicode) withinput payload &if(flags.negotiate_key_exch);
|
||||
|
||||
proc : bool = $context.connection.proc_smb_ntlm_authenticate(header, this);
|
||||
};
|
||||
|
||||
type SMB_NTLM_Version = record {
|
||||
major_version : uint8;
|
||||
minor_version : uint8;
|
||||
build_number : uint16;
|
||||
reserved : padding[3];
|
||||
ntlm_revision : uint8;
|
||||
};
|
||||
|
||||
type SMB_NTLM_StringData = record {
|
||||
length : uint16;
|
||||
max_length : uint16;
|
||||
offset : uint32;
|
||||
};
|
||||
|
||||
type SMB_Fixed_Length_String(unicode: bool) = record {
|
||||
data: uint8[] &restofdata;
|
||||
};
|
||||
|
||||
type SMB_NTLM_String(fields: SMB_NTLM_StringData, offset: uint16, unicode: bool) = record {
|
||||
pad1 : padding to fields.offset - offset;
|
||||
string : SMB_Fixed_Length_String(unicode) &length=fields.length;
|
||||
};
|
||||
|
||||
type SMB_NTLM_AV_Pair_Sequence(offset: uint16) = record {
|
||||
pad1 : padding to offset;
|
||||
pairs : SMB_NTLM_AV_Pair[] &until($element.last);
|
||||
};
|
||||
|
||||
type SMB_NTLM_AV_Pair = record {
|
||||
id : uint16;
|
||||
length : uint16;
|
||||
value_case : case id of {
|
||||
0x0000 -> av_eol : empty;
|
||||
0x0001 -> nb_computer_name : SMB_Fixed_Length_String(true) &length=length;
|
||||
0x0002 -> nb_domain_name : SMB_Fixed_Length_String(true) &length=length;
|
||||
0x0003 -> dns_computer_name : SMB_Fixed_Length_String(true) &length=length;
|
||||
0x0004 -> dns_domain_name : SMB_Fixed_Length_String(true) &length=length;
|
||||
0x0005 -> dns_tree_name : SMB_Fixed_Length_String(true) &length=length;
|
||||
0x0006 -> av_flags : uint32;
|
||||
0x0007 -> timestamp : uint64;
|
||||
0x0008 -> single_host : SMB_NTLM_Single_Host;
|
||||
0x0009 -> target_name : SMB_Fixed_Length_String(true) &length=length;
|
||||
0x000a -> channel_bindings : uint16;
|
||||
};
|
||||
} &let {
|
||||
last : bool = ( id == 0x0000);
|
||||
# av_flags refinement
|
||||
constrained_auth: bool = (av_flags & 0x00000001) > 0 &if ( id == 0x0006);
|
||||
mic_present : bool = (av_flags & 0x00000002) > 0 &if ( id == 0x0006);
|
||||
untrusted_source: bool = (av_flags & 0x00000004) > 0 &if ( id == 0x0006);
|
||||
};
|
||||
|
||||
type SMB_NTLM_Single_Host = record {
|
||||
size : uint32;
|
||||
padpad : padding[4];
|
||||
data_present : uint32;
|
||||
optional : case custom_data_present of {
|
||||
true -> custom_data : bytestring &length=4;
|
||||
false -> nothing : empty;
|
||||
};
|
||||
machine_id : uint32;
|
||||
} &let {
|
||||
custom_data_present: bool = (data_present & 0x00000001) > 0;
|
||||
};
|
||||
|
||||
type SMB_LM_Response(offset: uint16) = record {
|
||||
# This can be either LM (24 byte response) or
|
||||
# LMv2 (16 byte response + 8 byte client challenge. No way to
|
||||
# know for sure.
|
||||
padpad : padding to offset;
|
||||
response : bytestring &length=24;
|
||||
};
|
||||
|
||||
type SMB_NTLM_Response(offset: uint16) = record {
|
||||
padpad : padding to offset;
|
||||
response : bytestring &length=24;
|
||||
};
|
||||
|
||||
type SMB_NTLMv2_Response(flags: SMB_NTLM_Negotiate_Flags, offset: uint16) = record {
|
||||
padpad : padding to offset;
|
||||
response : bytestring &length=16;
|
||||
client_challenge : SMB_NTLMv2_Client_Challenge(flags);
|
||||
};
|
||||
|
||||
type SMB_NTLMv2_Client_Challenge(flags: SMB_NTLM_Negotiate_Flags) = record {
|
||||
resp_type : uint8;
|
||||
max_resp_type : uint8;
|
||||
reserved : padding[6];
|
||||
timestamp : uint64;
|
||||
client_challenge : bytestring &length=8;
|
||||
reserved2 : padding[4];
|
||||
av_pairs : SMB_NTLM_AV_Pair_Sequence(0);
|
||||
};
|
||||
|
||||
type SMB_NTLM_Negotiate_Flags = record {
|
||||
flags: uint32;
|
||||
} &let {
|
||||
negotiate_56 : bool = (flags & 0x80000000) > 0;
|
||||
negotiate_key_exch : bool = (flags & 0x40000000) > 0;
|
||||
negotiate_128 : bool = (flags & 0x20000000) > 0;
|
||||
|
||||
negotiate_version : bool = (flags & 0x02000000) > 0;
|
||||
|
||||
negotiate_target_info : bool = (flags & 0x00800000) > 0;
|
||||
request_non_nt_session_key : bool = (flags & 0x00400000) > 0;
|
||||
negotiate_identify : bool = (flags & 0x00100000) > 0;
|
||||
|
||||
negotiate_extended_sessionsecurity : bool = (flags & 0x00040000) > 0;
|
||||
target_type_server : bool = (flags & 0x00020000) > 0;
|
||||
target_type_domain : bool = (flags & 0x00010000) > 0;
|
||||
|
||||
negotiate_always_sign : bool = (flags & 0x00008000) > 0;
|
||||
negotiate_oem_workstation_supplied : bool = (flags & 0x00002000) > 0;
|
||||
negotiate_oem_domain_supplied : bool = (flags & 0x00001000) > 0;
|
||||
|
||||
negotiate_anonymous_connection : bool = (flags & 0x00000400) > 0;
|
||||
negotiate_ntlm : bool = (flags & 0x00000100) > 0;
|
||||
|
||||
negotiate_lm_key : bool = (flags & 0x00000080) > 0;
|
||||
negotiate_datagram : bool = (flags & 0x00000040) > 0;
|
||||
negotiate_seal : bool = (flags & 0x00000020) > 0;
|
||||
|
||||
negotiate_sign : bool = (flags & 0x00000008) > 0;
|
||||
request_target : bool = (flags & 0x00000004) > 0;
|
||||
negotiate_oem : bool = (flags & 0x00000002) > 0;
|
||||
negotiate_unicode : bool = (flags & 0x00000001) > 0;
|
||||
|
||||
is_oem : bool = !negotiate_unicode && negotiate_oem;
|
||||
is_invalid : bool = !negotiate_unicode && !negotiate_oem;
|
||||
};
|
|
@ -4,16 +4,12 @@
|
|||
%extern{
|
||||
#include "analyzer/Manager.h"
|
||||
#include "analyzer/Analyzer.h"
|
||||
// #include "analyzer/protocol/dce-rpc/DCE_RPC.h"
|
||||
|
||||
#include "smb1_events.bif.h"
|
||||
#include "smb2_events.bif.h"
|
||||
|
||||
#include "types.bif.h"
|
||||
|
||||
#include "smb_ntlmssp.bif.h"
|
||||
#include "smb_pipe.bif.h"
|
||||
|
||||
#include "smb1_com_check_directory.bif.h"
|
||||
#include "smb1_com_close.bif.h"
|
||||
#include "smb1_com_create_directory.bif.h"
|
||||
|
@ -57,9 +53,9 @@ connection SMB_Conn(bro_analyzer: BroAnalyzer) {
|
|||
%include smb-strings.pac
|
||||
%include smb-common.pac
|
||||
%include smb-time.pac
|
||||
|
||||
%include smb-ntlmssp-asn1.pac
|
||||
%include smb-ntlmssp.pac
|
||||
%include smb-mailslot.pac
|
||||
%include smb-pipe.pac
|
||||
%include smb-gssapi.pac
|
||||
|
||||
# SMB1 Commands
|
||||
%include smb1-com-check-directory.pac
|
||||
|
@ -82,9 +78,6 @@ connection SMB_Conn(bro_analyzer: BroAnalyzer) {
|
|||
%include smb1-com-tree-disconnect.pac
|
||||
%include smb1-com-write-andx.pac
|
||||
|
||||
%include smb-mailslot.pac
|
||||
%include smb-pipe.pac
|
||||
|
||||
# SMB2 Commands
|
||||
%include smb2-com-close.pac
|
||||
%include smb2-com-create.pac
|
||||
|
@ -146,14 +139,18 @@ flow SMB_Flow(is_orig: bool) {
|
|||
refine connection SMB_Conn += {
|
||||
%member{
|
||||
analyzer::Analyzer *dcerpc;
|
||||
analyzer::Analyzer *gssapi;
|
||||
%}
|
||||
|
||||
%init{
|
||||
dcerpc = analyzer_mgr->InstantiateAnalyzer("DCE_RPC", bro_analyzer->Conn());
|
||||
gssapi = analyzer_mgr->InstantiateAnalyzer("GSSAPI", bro_analyzer->Conn());
|
||||
%}
|
||||
|
||||
%cleanup{
|
||||
if ( dcerpc )
|
||||
delete dcerpc;
|
||||
if ( gssapi )
|
||||
delete gssapi;
|
||||
%}
|
||||
};
|
||||
|
|
|
@ -161,7 +161,6 @@ refine connection SMB_Conn += {
|
|||
else
|
||||
{
|
||||
ntlm->Assign(12, bytestring_to_val(${val.ntlm.server_guid}));
|
||||
// ntlm->Assign(13, bytestring_to_val(${val.ntlm.security_blob}));
|
||||
}
|
||||
|
||||
response->Assign(2, ntlm);
|
||||
|
@ -250,7 +249,7 @@ type SMB1_negotiate_ntlm_response(header: SMB_Header) = record {
|
|||
false -> no_guid : empty;
|
||||
} &requires(capabilities_extended_security);
|
||||
security_blob_present: case capabilities_extended_security of {
|
||||
true -> security_blob: SMB_NTLM_SSP(header) &length=(byte_count-16);
|
||||
true -> security_blob : bytestring &length=(byte_count-16);
|
||||
false -> no_blob : empty;
|
||||
} &requires(capabilities_extended_security);
|
||||
} &let {
|
||||
|
@ -277,5 +276,7 @@ type SMB1_negotiate_ntlm_response(header: SMB_Header) = record {
|
|||
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);
|
||||
};
|
||||
|
||||
|
|
|
@ -47,7 +47,6 @@ refine connection SMB_Conn += {
|
|||
request->Assign(5, smb_string2stringval(${val.ntlm_extended_security.native_os}));
|
||||
request->Assign(6, smb_string2stringval(${val.ntlm_extended_security.native_lanman}));
|
||||
|
||||
//request->Assign(12, bytestring_to_val(${val.ntlm_extended_security.security_blob}));
|
||||
request->Assign(13, capabilities);
|
||||
break;
|
||||
|
||||
|
@ -107,7 +106,10 @@ refine connection SMB_Conn += {
|
|||
break;
|
||||
}
|
||||
|
||||
BifEvent::generate_smb1_session_setup_andx_response(bro_analyzer(), bro_analyzer()->Conn(), BuildHeaderVal(header), response);
|
||||
BifEvent::generate_smb1_session_setup_andx_response(bro_analyzer(),
|
||||
bro_analyzer()->Conn(),
|
||||
BuildHeaderVal(header),
|
||||
response);
|
||||
}
|
||||
|
||||
return true;
|
||||
|
@ -207,10 +209,12 @@ type SMB1_session_setup_andx_request_ntlm_extended_security(header: SMB_Header)
|
|||
reserved : uint32;
|
||||
capabilities : SMB1_session_setup_andx_request_ntlm_capabilities;
|
||||
byte_count : uint16;
|
||||
security_blob : SMB_NTLM_SSP(header) &length=security_blob_length;
|
||||
security_blob : bytestring &length=security_blob_length;
|
||||
# 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);
|
||||
} &let {
|
||||
pipe_proc : bool = $context.connection.forward_gssapi(security_blob, true);
|
||||
};
|
||||
|
||||
type SMB1_session_setup_andx_response_ntlm(header: SMB_Header) = record {
|
||||
|
@ -218,12 +222,13 @@ type SMB1_session_setup_andx_response_ntlm(header: SMB_Header) = record {
|
|||
action : uint16;
|
||||
security_blob_length : uint16;
|
||||
byte_count : uint16;
|
||||
security_blob : SMB_NTLM_SSP(header) &length=security_blob_length;
|
||||
security_blob : bytestring &length=security_blob_length;
|
||||
# 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);
|
||||
} &let {
|
||||
is_guest : bool = ( action & 0x1 ) > 0;
|
||||
gssapi_proc : bool = $context.connection.forward_gssapi(security_blob, false);
|
||||
};
|
||||
|
||||
|
|
|
@ -62,7 +62,12 @@ type SMB2_negotiate_response(header: SMB2_Header) = record {
|
|||
max_write_size : uint32;
|
||||
system_time : SMB_timestamp;
|
||||
server_start_time : SMB_timestamp;
|
||||
security : SMB2_security;
|
||||
security_offset : uint16;
|
||||
security_length : uint16;
|
||||
pad1 : padding to security_offset - header.head_length;
|
||||
security_blob : bytestring &length=security_length;
|
||||
} &byteorder=littleendian, &let {
|
||||
proc : bool = $context.connection.proc_smb2_negotiate_response(header, this);
|
||||
gssapi_proc : bool = $context.connection.forward_gssapi(security_blob, false);
|
||||
|
||||
};
|
|
@ -45,20 +45,27 @@ type SMB2_session_setup_request(header: SMB2_Header) = record {
|
|||
security_mode : uint8;
|
||||
capabilities : uint32;
|
||||
channel : uint32;
|
||||
security : SMB2_security;
|
||||
security_offset : uint16;
|
||||
security_length : uint16;
|
||||
pad1 : padding to security_offset - header.head_length;
|
||||
security_blob : bytestring &length=security_length;
|
||||
} &let {
|
||||
proc: bool = $context.connection.proc_smb2_session_setup_request(header, this);
|
||||
gssapi_proc : bool = $context.connection.forward_gssapi(security_blob, true);
|
||||
};
|
||||
|
||||
type SMB2_session_setup_response(header: SMB2_Header) = record {
|
||||
structure_size : uint16;
|
||||
session_flags : uint16;
|
||||
security : SMB2_security;
|
||||
security_offset : uint16;
|
||||
security_length : uint16;
|
||||
pad1 : padding to security_offset - header.head_length;
|
||||
security_blob : bytestring &length=security_length;
|
||||
} &let {
|
||||
flag_guest = (session_flags & 0x1) > 0;
|
||||
flag_anonymous = (session_flags & 0x2) > 0;
|
||||
flag_encrypt = (session_flags & 0x4) > 0;
|
||||
|
||||
} &let {
|
||||
proc: bool = $context.connection.proc_smb2_session_setup_response(header, this);
|
||||
gssapi_proc : bool = $context.connection.forward_gssapi(security_blob, false);
|
||||
};
|
||||
|
|
|
@ -202,14 +202,6 @@ type SMB2_Header(is_orig: bool) = record {
|
|||
proc : bool = $context.connection.proc_smb2_message(this, is_orig);
|
||||
} &byteorder=littleendian;
|
||||
|
||||
type SMB2_security = record {
|
||||
buffer_offset : uint16;
|
||||
buffer_len : uint16;
|
||||
# TODO: handle previous session IDs
|
||||
sec_buffer : bytestring &length = buffer_len;
|
||||
} &byteorder = littleendian;
|
||||
|
||||
|
||||
# file ids and guids are the same thing and need unified somehow.
|
||||
type SMB2_guid = record {
|
||||
persistent : uint64;
|
||||
|
|
|
@ -1,64 +0,0 @@
|
|||
## Generated for SMB/CIFS requests that contain a security blob with a GSSAPI NTLM message of type *negotiate*.
|
||||
##
|
||||
## See `Wikipedia <http://en.wikipedia.org/wiki/Server_Message_Block>`__ for
|
||||
## more information about the SMB/CIFS protocol. Bro's SMB/CIFS analyzer parses
|
||||
## both SMB-over-NetBIOS on ports 138/139 and SMB-over-TCP on port 445.
|
||||
##
|
||||
## c: The connection.
|
||||
##
|
||||
## hdr: The parsed header of the SMB message.
|
||||
##
|
||||
## negotiate: The parsed data of the NTLM message. See init-bare for more details.
|
||||
##
|
||||
event smb_ntlm_negotiate%(c: connection, hdr: SMB1::Header, request: SMB::NTLMNegotiate%);
|
||||
|
||||
## Generated for SMB/CIFS requests that contain a security blob with a GSSAPI NTLM message of type *challenge*.
|
||||
##
|
||||
## See `Wikipedia <http://en.wikipedia.org/wiki/Server_Message_Block>`__ for
|
||||
## more information about the SMB/CIFS protocol. Bro's SMB/CIFS analyzer parses
|
||||
## both SMB-over-NetBIOS on ports 138/139 and SMB-over-TCP on port 445.
|
||||
##
|
||||
## c: The connection.
|
||||
##
|
||||
## hdr: The parsed header of the SMB message.
|
||||
##
|
||||
## negotiate: The parsed data of the NTLM message. See init-bare for more details.
|
||||
##
|
||||
event smb_ntlm_challenge%(c: connection, hdr: SMB1::Header, request: SMB::NTLMChallenge%);
|
||||
|
||||
## Generated for SMB/CIFS requests that contain a security blob with a GSSAPI NTLM message of type *authenticate*.
|
||||
##
|
||||
## See `Wikipedia <http://en.wikipedia.org/wiki/Server_Message_Block>`__ for
|
||||
## more information about the SMB/CIFS protocol. Bro's SMB/CIFS analyzer parses
|
||||
## both SMB-over-NetBIOS on ports 138/139 and SMB-over-TCP on port 445.
|
||||
##
|
||||
## c: The connection.
|
||||
##
|
||||
## hdr: The parsed header of the SMB message.
|
||||
##
|
||||
## negotiate: The parsed data of the NTLM message. See init-bare for more details.
|
||||
##
|
||||
event smb_ntlm_authenticate%(c: connection, hdr: SMB1::Header, request: SMB::NTLMAuthenticate%);
|
||||
|
||||
## Generated for SMB/CIFS requests that contain a security blob with a GSSAPI message of type *accept-completed*.
|
||||
##
|
||||
## See `Wikipedia <http://en.wikipedia.org/wiki/Server_Message_Block>`__ for
|
||||
## more information about the SMB/CIFS protocol. Bro's SMB/CIFS analyzer parses
|
||||
## both SMB-over-NetBIOS on ports 138/139 and SMB-over-TCP on port 445.
|
||||
##
|
||||
## c: The connection.
|
||||
##
|
||||
## hdr: The parsed header of the SMB message.
|
||||
##
|
||||
event smb_ntlm_accepted%(c: connection, hdr: SMB1::Header%);
|
||||
|
||||
|
||||
#### Types
|
||||
|
||||
type SMB::NTLMNegotiate: record;
|
||||
type SMB::NTLMChallenge: record;
|
||||
type SMB::NTLMAuthenticate: record;
|
||||
|
||||
type SMB::NTLMNegotiateFlags: record;
|
||||
type SMB::NTLMVersion: record;
|
||||
type SMB::NTLMAVs: record;
|
Loading…
Add table
Add a link
Reference in a new issue