From 6d56edc3de480113e2db5f19b10827601bc92849 Mon Sep 17 00:00:00 2001 From: Victor Julien Date: Mon, 12 Mar 2018 09:32:17 +0100 Subject: [PATCH] smb2: log client and server guid from negotiate --- rust/src/smb/log.rs | 19 +++++++++++++++++++ rust/src/smb/smb.rs | 6 ++++++ rust/src/smb/smb2.rs | 14 +++++++++++++- rust/src/smb/smb2_records.rs | 30 ++++++++++++++++++++++++++---- 4 files changed, 64 insertions(+), 5 deletions(-) diff --git a/rust/src/smb/log.rs b/rust/src/smb/log.rs index bc2c6c6b1b..a8b3cb170e 100644 --- a/rust/src/smb/log.rs +++ b/rust/src/smb/log.rs @@ -26,6 +26,19 @@ use smb::smb2::*; use smb::dcerpc::*; use nom; +fn guid_to_string(guid: &Vec) -> String { + if guid.len() == 16 { + let output = format!("{:02x}{:02x}{:02x}{:02x}-{:02x}{:02x}-{:02x}{:02x}-{:02x}{:02x}-{:02x}{:02x}{:02x}{:02x}{:02x}{:02x}", + guid[3], guid[2], guid[1], guid[0], + guid[5], guid[4], guid[7], guid[6], + guid[9], guid[8], guid[11], guid[10], + guid[15], guid[14], guid[13], guid[12]); + output + } else { + "".to_string() + } +} + fn smb_common_header(state: &SMBState, tx: &SMBTransaction) -> Json { let js = Json::object(); @@ -222,6 +235,12 @@ fn smb_common_header(state: &SMBState, tx: &SMBTransaction) -> Json } js.set("client_dialects", jsa); } + + if let Some(ref g) = x.client_guid { + js.set_string("client_guid", &guid_to_string(g)); + } + + js.set_string("server_guid", &guid_to_string(&x.server_guid)); }, Some(SMBTransactionTypeData::TREECONNECT(ref x)) => { js.set_integer("tree_id", x.tree_id as u64); diff --git a/rust/src/smb/smb.rs b/rust/src/smb/smb.rs index 19535f2876..929a4c4ce8 100644 --- a/rust/src/smb/smb.rs +++ b/rust/src/smb/smb.rs @@ -376,6 +376,10 @@ pub struct SMBTransactionNegotiate { pub smb_ver: u8, pub dialects: Vec>, pub dialects2: Vec>, + + // SMB1 doesn't have the client GUID + pub client_guid: Option>, + pub server_guid: Vec, } impl SMBTransactionNegotiate { @@ -384,6 +388,8 @@ impl SMBTransactionNegotiate { smb_ver: smb_ver, dialects: Vec::new(), dialects2: Vec::new(), + client_guid: None, + server_guid: Vec::with_capacity(16), } } } diff --git a/rust/src/smb/smb2.rs b/rust/src/smb/smb2.rs index 346c58b17c..3a582b2204 100644 --- a/rust/src/smb/smb2.rs +++ b/rust/src/smb/smb2.rs @@ -322,6 +322,7 @@ pub fn smb2_request_record<'b>(state: &mut SMBState, r: &Smb2Record<'b>) let tx = state.new_negotiate_tx(2); if let Some(SMBTransactionTypeData::NEGOTIATE(ref mut tdn)) = tx.type_data { tdn.dialects2 = dialects; + tdn.client_guid = Some(rd.client_guid.to_vec()); } tx.request_done = true; } @@ -685,13 +686,21 @@ pub fn smb2_response_record<'b>(state: &mut SMBState, r: &Smb2Record<'b>) } }, SMB2_COMMAND_NEGOTIATE_PROTOCOL => { - match parse_smb2_response_negotiate_protocol(r.data) { + let res = if r.nt_status == SMB_NTSTATUS_SUCCESS { + parse_smb2_response_negotiate_protocol(r.data) + } else { + parse_smb2_response_negotiate_protocol_error(r.data) + }; + match res { IResult::Done(_, rd) => { SCLogDebug!("SERVER dialect => {}", &smb2_dialect_string(rd.dialect)); state.dialect = rd.dialect; let found2 = match state.get_negotiate_tx(2) { Some(tx) => { + if let Some(SMBTransactionTypeData::NEGOTIATE(ref mut tdn)) = tx.type_data { + tdn.server_guid = rd.server_guid.to_vec(); + } tx.set_status(r.nt_status, false); tx.response_done = true; true @@ -701,6 +710,9 @@ pub fn smb2_response_record<'b>(state: &mut SMBState, r: &Smb2Record<'b>) // SMB2 response to SMB1 request? let found1 = !found2 && match state.get_negotiate_tx(1) { Some(tx) => { + if let Some(SMBTransactionTypeData::NEGOTIATE(ref mut tdn)) = tx.type_data { + tdn.server_guid = rd.server_guid.to_vec(); + } tx.set_status(r.nt_status, false); tx.response_done = true; true diff --git a/rust/src/smb/smb2_records.rs b/rust/src/smb/smb2_records.rs index 2283b2a907..d39e47fec5 100644 --- a/rust/src/smb/smb2_records.rs +++ b/rust/src/smb/smb2_records.rs @@ -82,25 +82,33 @@ named!(pub parse_smb2_request_record, )); #[derive(Debug,PartialEq)] -pub struct Smb2NegotiateProtocolRequestRecord<> { +pub struct Smb2NegotiateProtocolRequestRecord<'a> { pub dialects_vec: Vec, + pub client_guid: &'a[u8], } named!(pub parse_smb2_request_negotiate_protocol, do_parse!( struct_size: take!(2) >> dialects_count: le_u16 - >> blob1: take!(32) + >> sec_mode: le_u16 + >> reserved1: le_u16 + >> capabilities: le_u32 + >> client_guid: take!(16) + >> ctx_offset: le_u32 + >> ctx_cnt: le_u16 + >> reserved2: le_u16 >> dia_vec: count!(le_u16, dialects_count as usize) - >> blob2: rest >> (Smb2NegotiateProtocolRequestRecord { dialects_vec: dia_vec, + client_guid: client_guid, }) )); #[derive(Debug,PartialEq)] -pub struct Smb2NegotiateProtocolResponseRecord<> { +pub struct Smb2NegotiateProtocolResponseRecord<'a> { pub dialect: u16, + pub server_guid: &'a[u8], } named!(pub parse_smb2_response_negotiate_protocol, @@ -108,11 +116,25 @@ named!(pub parse_smb2_response_negotiate_protocol> skip1: take!(2) >> dialect: le_u16 + >> ctx_cnt: le_u16 + >> server_guid: take!(16) >> (Smb2NegotiateProtocolResponseRecord { dialect: dialect, + server_guid: server_guid, }) )); +named!(pub parse_smb2_response_negotiate_protocol_error, + do_parse!( + struct_size: take!(2) + >> skip1: take!(2) + >> (Smb2NegotiateProtocolResponseRecord { + dialect: 0, + server_guid: &[], + }) +)); + + #[derive(Debug,PartialEq)] pub struct Smb2SessionSetupRequestRecord<'a> { pub data: &'a[u8],