smb2: parse and log timestamps in CREATE

pull/3281/head
Victor Julien 9 years ago
parent 28f16e38ac
commit 0e05ef7369

@ -193,6 +193,13 @@ fn smb_common_header(state: &SMBState, tx: &SMBTransaction) -> Json
} else { } else {
js.set_string("access", "normal"); js.set_string("access", "normal");
} }
// field names inspired by Bro
js.set_integer("created", x.create_ts as u64);
js.set_integer("accessed", x.last_access_ts as u64);
js.set_integer("modified", x.last_write_ts as u64);
js.set_integer("changed", x.last_change_ts as u64);
js.set_integer("size", x.size);
}, },
Some(SMBTransactionTypeData::NEGOTIATE(ref x)) => { Some(SMBTransactionTypeData::NEGOTIATE(ref x)) => {
if x.smb_ver == 1 { if x.smb_ver == 1 {

@ -304,6 +304,32 @@ impl SMBVerCmdStat {
} }
} }
/// "The FILETIME structure is a 64-bit value that represents the number of
/// 100-nanosecond intervals that have elapsed since January 1, 1601,
/// Coordinated Universal Time (UTC)."
#[derive(Eq, PartialEq, Debug, Clone)]
pub struct SMBFiletime {
ts: u64,
}
impl SMBFiletime {
pub fn new(raw: u64) -> SMBFiletime {
SMBFiletime {
ts: raw,
}
}
/// inspired by Bro, convert FILETIME to secs since unix epoch
pub fn as_unix(&self) -> u32 {
if self.ts > 116_444_736_000_000_000_u64 {
let ts = self.ts / 10000000 - 11644473600;
ts as u32
} else {
0
}
}
}
#[derive(Debug)] #[derive(Debug)]
pub enum SMBTransactionTypeData { pub enum SMBTransactionTypeData {
FILE(SMBTransactionFile), FILE(SMBTransactionFile),
@ -320,6 +346,13 @@ pub struct SMBTransactionCreate {
pub delete_on_close: bool, pub delete_on_close: bool,
pub directory: bool, pub directory: bool,
pub filename: Vec<u8>, pub filename: Vec<u8>,
pub create_ts: u32,
pub last_access_ts: u32,
pub last_write_ts: u32,
pub last_change_ts: u32,
pub size: u64,
} }
impl SMBTransactionCreate { impl SMBTransactionCreate {
@ -329,6 +362,11 @@ impl SMBTransactionCreate {
delete_on_close: del, delete_on_close: del,
directory: dir, directory: dir,
filename: filename, filename: filename,
create_ts: 0,
last_access_ts: 0,
last_write_ts: 0,
last_change_ts: 0,
size: 0,
} }
} }
} }

@ -597,22 +597,37 @@ pub fn smb2_response_record<'b>(state: &mut SMBState, r: &Smb2Record<'b>)
SCLogDebug!("SMBv2: Create response => {:?}", cr); SCLogDebug!("SMBv2: Create response => {:?}", cr);
let guid_key = SMBCommonHdr::from2(r, SMBHDR_TYPE_FILENAME); let guid_key = SMBCommonHdr::from2(r, SMBHDR_TYPE_FILENAME);
match state.ssn2vec_map.remove(&guid_key) { if let Some(mut p) = state.ssn2vec_map.remove(&guid_key) {
Some(mut p) => {
p.retain(|&i|i != 0x00); p.retain(|&i|i != 0x00);
state.guid2name_map.insert(cr.guid.to_vec(), p); state.guid2name_map.insert(cr.guid.to_vec(), p);
}, } else {
_ => {
SCLogDebug!("SMBv2 response: GUID NOT FOUND"); SCLogDebug!("SMBv2 response: GUID NOT FOUND");
}, }
let tx_hdr = SMBCommonHdr::from2(r, SMBHDR_TYPE_GENERICTX);
if let Some(tx) = state.get_generic_tx(2, r.command, &tx_hdr) {
SCLogDebug!("tx {} with {}/{} marked as done",
tx.id, r.command, &smb2_command_string(r.command));
tx.set_status(r.nt_status, false);
tx.response_done = true;
if let Some(SMBTransactionTypeData::CREATE(ref mut tdn)) = tx.type_data {
tdn.create_ts = cr.create_ts.as_unix();
tdn.last_access_ts = cr.last_access_ts.as_unix();
tdn.last_write_ts = cr.last_write_ts.as_unix();
tdn.last_change_ts = cr.last_change_ts.as_unix();
tdn.size = cr.size;
}
} }
} }
_ => { _ => {
events.push(SMBEvent::MalformedData); events.push(SMBEvent::MalformedData);
}, },
} }
} true
} else {
false false
}
}, },
SMB2_COMMAND_TREE_DISCONNECT => { SMB2_COMMAND_TREE_DISCONNECT => {
// normally removed when processing request, // normally removed when processing request,

@ -16,6 +16,7 @@
*/ */
use nom::{rest, le_u8, le_u16, le_u32, le_u64, AsBytes}; use nom::{rest, le_u8, le_u16, le_u32, le_u64, AsBytes};
use smb::smb::*;
#[derive(Debug,PartialEq)] #[derive(Debug,PartialEq)]
pub struct Smb2SecBlobRecord<'a> { pub struct Smb2SecBlobRecord<'a> {
@ -339,15 +340,36 @@ named!(pub parse_smb2_response_read<Smb2ReadResponseRecord>,
#[derive(Debug,PartialEq)] #[derive(Debug,PartialEq)]
pub struct Smb2CreateResponseRecord<'a> { pub struct Smb2CreateResponseRecord<'a> {
pub guid: &'a[u8], pub guid: &'a[u8],
pub create_ts: SMBFiletime,
pub last_access_ts: SMBFiletime,
pub last_write_ts: SMBFiletime,
pub last_change_ts: SMBFiletime,
pub size: u64,
} }
named!(pub parse_smb2_response_create<Smb2CreateResponseRecord>, named!(pub parse_smb2_response_create<Smb2CreateResponseRecord>,
do_parse!( do_parse!(
skip1: take!(64) ssize: le_u16
>> oplock: le_u8
>> resp_flags: le_u8
>> create_action: le_u32
>> create_ts: le_u64
>> last_access_ts: le_u64
>> last_write_ts: le_u64
>> last_change_ts: le_u64
>> alloc_size: le_u64
>> eof: le_u64
>> attrs: le_u32
>> padding: take!(4)
>> guid: take!(16) >> guid: take!(16)
>> skip2: take!(8) >> skip2: take!(8)
>> (Smb2CreateResponseRecord { >> (Smb2CreateResponseRecord {
guid : guid, guid : guid,
create_ts: SMBFiletime::new(create_ts),
last_access_ts: SMBFiletime::new(last_access_ts),
last_write_ts: SMBFiletime::new(last_write_ts),
last_change_ts: SMBFiletime::new(last_change_ts),
size: eof,
}) })
)); ));

Loading…
Cancel
Save