smb3: parse transform records

pull/3281/head
Victor Julien 8 years ago
parent 894a73ee06
commit b34392051d

@ -26,6 +26,7 @@ pub mod smb1;
pub mod smb1_session; pub mod smb1_session;
pub mod smb2; pub mod smb2;
pub mod smb2_session; pub mod smb2_session;
pub mod smb3;
pub mod dcerpc; pub mod dcerpc;
pub mod session; pub mod session;
pub mod log; pub mod log;

@ -44,6 +44,7 @@ use smb::smb2_records::*;
use smb::smb1::*; use smb::smb1::*;
use smb::smb2::*; use smb::smb2::*;
use smb::smb3::*;
use smb::dcerpc::*; use smb::dcerpc::*;
use smb::session::*; use smb::session::*;
use smb::events::*; use smb::events::*;
@ -1053,7 +1054,7 @@ impl SMBState {
match parse_smb_version(&nbss_part_hdr.data) { match parse_smb_version(&nbss_part_hdr.data) {
IResult::Done(_, ref smb) => { IResult::Done(_, ref smb) => {
SCLogDebug!("SMB {:?}", smb); SCLogDebug!("SMB {:?}", smb);
if smb.version == 255u8 { // SMB1 if smb.version == 0xff_u8 { // SMB1
SCLogDebug!("SMBv1 record"); SCLogDebug!("SMBv1 record");
match parse_smb_record(&nbss_part_hdr.data) { match parse_smb_record(&nbss_part_hdr.data) {
IResult::Done(_, ref r) => { IResult::Done(_, ref r) => {
@ -1077,7 +1078,7 @@ impl SMBState {
_ => { }, _ => { },
} }
} else if smb.version == 254u8 { // SMB2 } else if smb.version == 0xfe_u8 { // SMB2
SCLogDebug!("SMBv2 record"); SCLogDebug!("SMBv2 record");
match parse_smb2_request_record(&nbss_part_hdr.data) { match parse_smb2_request_record(&nbss_part_hdr.data) {
IResult::Done(_, ref smb_record) => { IResult::Done(_, ref smb_record) => {
@ -1092,6 +1093,7 @@ impl SMBState {
_ => { }, _ => { },
} }
} }
// no SMB3 here yet, will buffer full records
}, },
_ => { }, _ => { },
} }
@ -1151,7 +1153,7 @@ impl SMBState {
// gap // gap
if self.ts_gap { if self.ts_gap {
SCLogDebug!("TODO TS trying to catch up after GAP (input {})", cur_i.len()); SCLogDebug!("TODO TS trying to catch up after GAP (input {})", cur_i.len());
match search_smb2_record(cur_i) { match search_smb_record(cur_i) {
IResult::Done(_, pg) => { IResult::Done(_, pg) => {
SCLogDebug!("smb record found"); SCLogDebug!("smb record found");
let smb2_offset = cur_i.len() - pg.data.len(); let smb2_offset = cur_i.len() - pg.data.len();
@ -1179,7 +1181,7 @@ impl SMBState {
match parse_smb_version(&nbss_hdr.data) { match parse_smb_version(&nbss_hdr.data) {
IResult::Done(_, ref smb) => { IResult::Done(_, ref smb) => {
SCLogDebug!("SMB {:?}", smb); SCLogDebug!("SMB {:?}", smb);
if smb.version == 255u8 { // SMB1 if smb.version == 0xff_u8 { // SMB1
SCLogDebug!("SMBv1 record"); SCLogDebug!("SMBv1 record");
match parse_smb_record(&nbss_hdr.data) { match parse_smb_record(&nbss_hdr.data) {
IResult::Done(_, ref smb_record) => { IResult::Done(_, ref smb_record) => {
@ -1190,7 +1192,7 @@ impl SMBState {
return 1; return 1;
}, },
} }
} else if smb.version == 254u8 { // SMB2 } else if smb.version == 0xfe_u8 { // SMB2
let mut nbss_data = nbss_hdr.data; let mut nbss_data = nbss_hdr.data;
while nbss_data.len() > 0 { while nbss_data.len() > 0 {
SCLogDebug!("SMBv2 record"); SCLogDebug!("SMBv2 record");
@ -1207,6 +1209,20 @@ impl SMBState {
}, },
} }
} }
} else if smb.version == 0xfd_u8 { // SMB3 transform
let mut nbss_data = nbss_hdr.data;
while nbss_data.len() > 0 {
SCLogDebug!("SMBv3 transform record");
match parse_smb3_transform_record(&nbss_data) {
IResult::Done(nbss_data_rem, ref _smb3_record) => {
nbss_data = nbss_data_rem;
},
_ => {
self.set_event(SMBEvent::MalformedData);
return 1;
},
}
}
} }
}, },
_ => { _ => {
@ -1305,6 +1321,7 @@ impl SMBState {
_ => { }, _ => { },
} }
} }
// no SMB3 here yet, will buffer full records
}, },
_ => { }, _ => { },
} }
@ -1361,8 +1378,8 @@ impl SMBState {
} }
// gap // gap
if self.tc_gap { if self.tc_gap {
SCLogDebug!("TODO TC trying to catch up after GAP (input {})", cur_i.len()); SCLogDebug!("TC trying to catch up after GAP (input {})", cur_i.len());
match search_smb2_record(cur_i) { match search_smb_record(cur_i) {
IResult::Done(_, pg) => { IResult::Done(_, pg) => {
SCLogDebug!("smb record found"); SCLogDebug!("smb record found");
let smb2_offset = cur_i.len() - pg.data.len(); let smb2_offset = cur_i.len() - pg.data.len();
@ -1390,7 +1407,7 @@ impl SMBState {
match parse_smb_version(&nbss_hdr.data) { match parse_smb_version(&nbss_hdr.data) {
IResult::Done(_, ref smb) => { IResult::Done(_, ref smb) => {
SCLogDebug!("SMB {:?}", smb); SCLogDebug!("SMB {:?}", smb);
if smb.version == 255u8 { // SMB1 if smb.version == 0xff_u8 { // SMB1
SCLogDebug!("SMBv1 record"); SCLogDebug!("SMBv1 record");
match parse_smb_record(&nbss_hdr.data) { match parse_smb_record(&nbss_hdr.data) {
IResult::Done(_, ref smb_record) => { IResult::Done(_, ref smb_record) => {
@ -1401,7 +1418,7 @@ impl SMBState {
return 1; return 1;
}, },
} }
} else if smb.version == 254u8 { // SMB2 } else if smb.version == 0xfe_u8 { // SMB2
let mut nbss_data = nbss_hdr.data; let mut nbss_data = nbss_hdr.data;
while nbss_data.len() > 0 { while nbss_data.len() > 0 {
SCLogDebug!("SMBv2 record"); SCLogDebug!("SMBv2 record");
@ -1416,6 +1433,20 @@ impl SMBState {
}, },
} }
} }
} else if smb.version == 0xfd_u8 { // SMB3 transform
let mut nbss_data = nbss_hdr.data;
while nbss_data.len() > 0 {
SCLogDebug!("SMBv3 transform record");
match parse_smb3_transform_record(&nbss_data) {
IResult::Done(nbss_data_rem, ref _smb3_record) => {
nbss_data = nbss_data_rem;
},
_ => {
self.set_event(SMBEvent::MalformedData);
return 1;
},
}
}
} }
}, },
IResult::Incomplete(_) => { IResult::Incomplete(_) => {

@ -15,7 +15,7 @@
* 02110-1301, USA. * 02110-1301, USA.
*/ */
use nom::{rest, le_u8, le_u16, le_u32, le_u64, IResult, AsBytes}; use nom::{rest, le_u8, le_u16, le_u32, le_u64, AsBytes};
#[derive(Debug,PartialEq)] #[derive(Debug,PartialEq)]
pub struct Smb2SecBlobRecord<'a> { pub struct Smb2SecBlobRecord<'a> {
@ -405,28 +405,17 @@ named!(pub parse_smb2_response_record<Smb2Record>,
)); ));
#[derive(Debug,PartialEq)] #[derive(Debug,PartialEq)]
pub struct Smb2RecordPostGap<'a> { pub struct SmbRecordPostGap<'a> {
pub data: &'a[u8], pub data: &'a[u8],
} }
named!(pub search_smb2_record<Smb2RecordPostGap>, named!(pub search_smb_record<SmbRecordPostGap>,
do_parse!( do_parse!(
alt!(take_until!([0xfe, 0x53, 0x4d, 0x42].as_bytes())| // SMB2 alt!(take_until!([0xfe, 0x53, 0x4d, 0x42].as_bytes())| // SMB2
take_until!([0xff, 0x53, 0x4d, 0x42].as_bytes())) // SMB1 take_until!([0xff, 0x53, 0x4d, 0x42].as_bytes())| // SMB1
take_until!([0xfd, 0x53, 0x4d, 0x42].as_bytes())) // SMB3 transform hdr
>> data : rest >> data : rest
>> ( Smb2RecordPostGap { >> ( SmbRecordPostGap {
data:data, data:data,
}) })
)); ));
pub fn search_smb2_record_f<'a>(input: &'a [u8])
-> IResult<&'a [u8], Smb2RecordPostGap>
{
return closure!(&'a [u8], do_parse!(
take_until!([0xfe, 0x53, 0x4d, 0x42].as_bytes())
>> data : rest
>> ( Smb2RecordPostGap {
data:data,
})
))(input);
}

@ -0,0 +1,42 @@
/* Copyright (C) 2018 Open Information Security Foundation
*
* You can copy, redistribute or modify this Program under the terms of
* the GNU General Public License version 2 as published by the Free
* Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* version 2 along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
* 02110-1301, USA.
*/
use nom::{le_u16, le_u32, le_u64};
#[derive(Debug,PartialEq)]
pub struct Smb3TransformRecord<'a> {
pub session_id: u64,
pub enc_algo: u16,
pub enc_data: &'a[u8],
}
named!(pub parse_smb3_transform_record<Smb3TransformRecord>,
do_parse!(
tag!(b"\xfdSMB")
>> signature: take!(16)
>> nonce: take!(16)
>> msg_size: le_u32
>> reserved: le_u16
>> enc_algo: le_u16
>> session_id: le_u64
>> enc_data: take!(msg_size)
>> ( Smb3TransformRecord {
session_id: session_id,
enc_algo: enc_algo,
enc_data: enc_data,
})
));
Loading…
Cancel
Save