smb: add unit tests

Issue: 4865
pull/8815/head
Lancer Cheng 2 years ago committed by Victor Julien
parent a006aef4d0
commit 0cf742a9ca

@ -345,7 +345,7 @@ pub fn parse_smb2_request_close(i: &[u8]) -> IResult<&[u8], Smb2CloseRequestReco
Ok((i, record))
}
#[derive(Debug)]
#[derive(Debug, PartialEq)]
pub struct Smb2SetInfoRequestRenameRecord<'a> {
pub name: &'a[u8],
}
@ -360,7 +360,7 @@ pub fn parse_smb2_request_setinfo_rename(i: &[u8]) -> IResult<&[u8], Smb2SetInfo
Ok((i, record))
}
#[derive(Debug)]
#[derive(Debug, PartialEq)]
pub struct Smb2SetInfoRequestDispoRecord {
pub delete: bool,
}
@ -373,7 +373,7 @@ pub fn parse_smb2_request_setinfo_disposition(i: &[u8]) -> IResult<&[u8], Smb2Se
Ok((i, record))
}
#[derive(Debug)]
#[derive(Debug, PartialEq)]
pub enum Smb2SetInfoRequestData<'a> {
DISPOSITION(Smb2SetInfoRequestDispoRecord),
RENAME(Smb2SetInfoRequestRenameRecord<'a>),
@ -626,3 +626,240 @@ pub fn search_smb_record(i: &[u8]) -> IResult<&[u8], &[u8]> {
}
Err(Err::Incomplete(Needed::new(4_usize - d.len())))
}
#[cfg(test)]
mod tests {
use super::*;
use crate::smb::smb2::smb2_dialect_string;
use std::convert::TryInto;
fn guid_to_string(guid: &[u8]) -> 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()
}
}
#[test]
fn test_parse_smb2_request_record() {
let data = hex::decode("fe534d42400000000000000000000100010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000").unwrap();
let result = parse_smb2_request_record(&data).unwrap();
let record: Smb2Record = result.1;
assert_eq!(record, Smb2Record {
direction: 1,
header_len: 64,
nt_status: 0,
command: 0,
message_id: 0,
tree_id: 0,
async_id: 0,
session_id: 0,
data: &[],
});
}
#[test]
fn test_parse_smb2_request_negotiate_protocol() {
// https://github.com/bro/bro/blob/master/testing/btest/Traces/smb/smb3_negotiate_context.pcap
// smb3_negotiate_context.pcap no.12
let data = hex::decode("24000800010000007f00000016ab4fd9625676488cd1707d08e52b5878000000020000000202100222022402000302031003110300000000010026000000000001002000010067e5f669ff3e0ad12e89ad84ceb1d35dfee53ede3e4858a6d1a9099ac1635a9600000200060000000000020001000200").unwrap();
let result = parse_smb2_request_negotiate_protocol(&data).unwrap();
let record: Smb2NegotiateProtocolRequestRecord = result.1;
let dialects:Vec<String> = record.dialects_vec.iter().map(|d|smb2_dialect_string(*d)).collect();
assert_eq!(dialects, ["2.02", "2.10", "2.22", "2.24", "3.00", "3.02", "3.10", "3.11"]);
assert_eq!(guid_to_string(record.client_guid), "d94fab16-5662-4876-d18c-7d70582be508"); // TODO: guid order
}
#[test]
fn test_parse_smb2_response_tree_connect() {
// https://github.com/bro/bro/blob/master/testing/btest/Traces/smb/smb2.pcap
// filter:smb2 no.11
let data = hex::decode("100001000008000000000000ff011f00").unwrap();
let result = parse_smb2_response_tree_connect(&data).unwrap();
let record: Smb2TreeConnectResponseRecord = result.1;
assert_eq!(record.share_type, 1); // 1: SMB2_SHARE_TYPE_DISK
}
#[test]
fn test_parse_smb2_request_create() {
// https://raw.githubusercontent.com/bro/bro/master/testing/btest/Traces/smb/smb2.pcap
// filter:smb2 no.26
let data = hex::decode("390000000200000000000000000000000000000000000000810010008000000003000000020000002100200078000000800000005800000000007200760073002800000010000400000018001000000044486e510000000000000000000000000000000000000000180000001000040000001800000000004d78416300000000000000001000040000001800000000005146696400000000").unwrap();
let result = parse_smb2_request_create(&data).unwrap();
let record: Smb2CreateRequestRecord = result.1;
assert_eq!(record.disposition, 2); // FILE_CREATE: 2
assert_eq!(record.create_options, 0x200021);
assert_eq!(record.data, &[]);
let del = record.create_options & 0x0000_1000 != 0;
let dir = record.create_options & 0x0000_0001 != 0;
assert_eq!(del, false);
assert_eq!(dir, true);
}
#[test]
fn test_parse_smb2_request_close() {
// https://raw.githubusercontent.com/bro/bro/master/testing/btest/Traces/smb/smb2.pcap
// filter:smb2 no.24
let data = hex::decode("1800000000000000490000000000000005000000ffffffff").unwrap();
let result = parse_smb2_request_close(&data).unwrap();
let record: Smb2CloseRequestRecord = result.1;
assert_eq!(guid_to_string(record.guid), "00000049-0000-0000-0005-0000ffffffff");
}
#[test]
fn test_parse_smb2_request_setinfo() {
// https://raw.githubusercontent.com/bro/bro/master/testing/btest/Traces/smb/smb2.pcap
// filter:tcp.stream eq 0 no.36
let data = hex::decode("210001140800000060000000000000004d0000000000000009000000ffffffff4b06170000000000").unwrap();
let result = parse_smb2_request_setinfo(&data).unwrap();
let record: Smb2SetInfoRequestRecord = result.1;
assert_eq!(record.class, 1);
assert_eq!(record.infolvl, 20);
assert_eq!(record.data, Smb2SetInfoRequestData::UNHANDLED);
assert_eq!(guid_to_string(record.guid), "0000004d-0000-0000-0009-0000ffffffff");
}
#[test]
fn test_parse_smb2_request_read() {
// https://raw.githubusercontent.com/bro/bro/master/testing/btest/Traces/smb/smb2.pcap
// filter:smb2 no.20
let data = hex::decode("31005000000400000000000000000000490000000000000005000000ffffffff00000000000000000000000000000000").unwrap();
let result = parse_smb2_request_read(&data).unwrap();
let record: Smb2ReadRequestRecord = result.1;
assert_eq!(record.rd_len, 1024);
assert_eq!(record.rd_offset, 0);
assert_eq!(guid_to_string(record.guid), "00000049-0000-0000-0005-0000ffffffff");
}
#[test]
fn test_parse_smb2_request_write() {
// https://raw.githubusercontent.com/bro/bro/master/testing/btest/Traces/smb/smb2.pcap
// filter:tcp.stream eq 0 no.18
let data = hex::decode("31007000740000000000000000000000490000000000000005000000ffffffff0000000000000000000000000000000005000b03100000007400000001000000b810b810000000000200000000000100c84f324b7016d30112785a47bf6ee18803000000045d888aeb1cc9119fe808002b1048600200000001000100c84f324b7016d30112785a47bf6ee188030000002c1cb76c12984045030000000000000001000000").unwrap();
let result = parse_smb2_request_write(&data).unwrap();
let record: Smb2WriteRequestRecord = result.1;
assert_eq!(record.wr_len, 116);
assert_eq!(record.wr_offset, 0);
assert_eq!(guid_to_string(record.guid), "00000049-0000-0000-0005-0000ffffffff");
assert_eq!(record.data.len(), 116);
}
#[test]
fn test_parse_smb2_response_read() {
// https://raw.githubusercontent.com/bro/bro/master/testing/btest/Traces/smb/smb2.pcap
// filter:tcp.stream eq 0 no.21
let data = hex::decode("110050005c000000000000000000000005000c03100000005c00000001000000b810b810b97200000d005c504950455c73727673766300000200000000000000045d888aeb1cc9119fe808002b10486002000000030003000000000000000000000000000000000000000000").unwrap();
let result = parse_smb2_response_read(&data).unwrap();
let record: Smb2ReadResponseRecord = result.1;
assert_eq!(record.len, 92);
assert_eq!(record.data.len(), 92);
}
#[test]
fn test_parse_smb2_record_direction() {
let data = hex::decode("fe534d42400000000000000000000100010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000").unwrap();
let result = parse_smb2_record_direction(&data).unwrap();
let record: Smb2RecordDir = result.1;
assert_eq!(record.request, false);
let data = hex::decode("fe534d4240000000000000000100080000000000000000000100000000000000fffe000000000000000000000000000000000000000000000000000000000000").unwrap();
let result = parse_smb2_record_direction(&data).unwrap();
let record: Smb2RecordDir = result.1;
assert_eq!(record.request, true);
}
#[test]
fn test_parse_smb2_request_tree_connect() {
let data = hex::decode("0900000048002c005c005c003100390032002e003100360038002e003100390039002e003100330033005c004900500043002400").unwrap();
let result = parse_smb2_request_tree_connect(&data);
assert_eq!(result.is_ok(), true);
let record = result.unwrap().1;
assert!(record.share_name.len() > 2);
let share_name_len = u16::from_le_bytes(record.share_name[0..2].try_into().unwrap());
assert_eq!(share_name_len ,44);
assert_eq!(record.share_name.len() ,share_name_len as usize + 2);
let mut share_name = record.share_name[2..].to_vec();
share_name.retain(|&i|i != 0x00);
assert_eq!(String::from_utf8_lossy(&share_name), "\\\\192.168.199.133\\IPC$");
}
#[test]
fn test_parse_smb2_response_record() {
let data = hex::decode("fe534d4240000000000000000000010001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000041000100ff020000966eafa3357f0440a5f9643e1bfa8c56070000000000800000008000000080001064882d8527d201a1f3ae878427d20180004001000000006082013c06062b0601050502a08201303082012ca01a3018060a2b06010401823702021e060a2b06010401823702020aa282010c048201084e45474f45585453010000000000000060000000700000007fb23ba7cacc4e216323ca8472061efbd2c4f6d6b3017012f0bf4f7202ec684ee801ef64e55401ab86b1c9ebde4e39ea0000000000000000600000000100000000000000000000005c33530deaf90d4db2ec4ae3786ec3084e45474f45585453030000000100000040000000980000007fb23ba7cacc4e216323ca8472061efb5c33530deaf90d4db2ec4ae3786ec30840000000580000003056a05430523027802530233121301f06035504031318546f6b656e205369676e696e67205075626c6963204b65793027802530233121301f06035504031318546f6b656e205369676e696e67205075626c6963204b6579").unwrap();
let result = parse_smb2_response_record(&data);
assert_eq!(result.is_ok(), true);
let record = result.unwrap().1;
assert_eq!(record.direction, 1);
assert_eq!(record.header_len, 64);
assert_eq!(record.nt_status, 0);
assert_eq!(record.command, crate::smb::smb2::SMB2_COMMAND_NEGOTIATE_PROTOCOL);
assert_eq!(record.message_id, 0);
assert_eq!(record.tree_id, 0);
assert_eq!(record.async_id, 0);
assert_eq!(record.session_id, 0);
let neg_proto_result = parse_smb2_response_negotiate_protocol(record.data);
assert_eq!(neg_proto_result.is_ok(), true);
let neg_proto = neg_proto_result.unwrap().1;
assert_eq!(guid_to_string(neg_proto.server_guid), "a3af6e96-7f35-4004-f9a5-3e64568cfa1b");
assert_eq!(neg_proto.dialect, 0x2ff);
assert_eq!(smb2_dialect_string(neg_proto.dialect), "2.??".to_string());
assert_eq!(neg_proto.max_trans_size, 0x800000);
assert_eq!(neg_proto.max_read_size, 0x800000);
assert_eq!(neg_proto.max_write_size, 0x800000);
}
#[test]
fn test_todo_parse_smb2_response_negotiate_protocol_error() {
// TODO: find pcap
}
#[test]
fn test_parse_smb2_response_write() {
let data = hex::decode("11000000a00000000000000000000000").unwrap();
let result = parse_smb2_response_write(&data);
assert_eq!(result.is_ok(), true);
let record = result.unwrap().1;
assert_eq!(record.wr_cnt, 160);
}
#[test]
fn test_parse_smb2_response_create() {
let data = hex::decode("5900000001000000000000000000000000000000000000000000000000000000000000000000000000100000000000000000000000000000800000000000000001000000db3b5a009a29ea00000000000000000000000000").unwrap();
let result = parse_smb2_response_create(&data);
assert_eq!(result.is_ok(), true);
let record = result.unwrap().1;
assert_eq!(guid_to_string(record.guid), "00000001-3bdb-005a-299a-00ea00000000");
assert_eq!(record.create_ts, SMBFiletime::new(0));
assert_eq!(record.last_access_ts, SMBFiletime::new(0));
assert_eq!(record.last_write_ts, SMBFiletime::new(0));
assert_eq!(record.last_change_ts, SMBFiletime::new(0));
assert_eq!(record.size, 0);
}
#[test]
fn test_parse_smb2_response_ioctl() {
let data = hex::decode("31000000fc011400ffffffffffffffffffffffffffffffff7000000000000000700000003001000000000000000000009800000004000000010000000000000000ca9a3b0000000002000000c0a8c7850000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004000000010000000000000000ca9a3b000000001700000000000000fe8000000000000065b53a9792d191990000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000").unwrap();
let result = parse_smb2_response_ioctl(&data);
assert_eq!(result.is_ok(), true);
let record = result.unwrap().1;
assert_eq!(record.indata_len, 0);
assert_eq!(guid_to_string(record.guid), "ffffffff-ffff-ffff-ffff-ffffffffffff");
assert_eq!(record.is_pipe, false);
assert_eq!(record.outdata_len, 304);
assert_eq!(record.indata_offset, 112);
assert_eq!(record.outdata_offset, 112);
}
#[test]
fn test_parse_smb2_request_ioctl() {
let data = hex::decode("39000000fc011400ffffffffffffffffffffffffffffffff7800000000000000000000007800000000000000000001000100000000000000").unwrap();
let result = parse_smb2_request_ioctl(&data);
assert_eq!(result.is_ok(), true);
let record = result.unwrap().1;
assert_eq!(guid_to_string(record.guid), "ffffffff-ffff-ffff-ffff-ffffffffffff");
assert_eq!(record.is_pipe, false);
assert_eq!(record.function, 0x1401fc);
assert_eq!(record.data, &[]);
}
}

@ -42,3 +42,18 @@ pub fn parse_smb3_transform_record(i: &[u8]) -> IResult<&[u8], Smb3TransformReco
};
Ok((i, record))
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_parse_smb3_transform_record() {
// https://raw.githubusercontent.com/bro/bro/master/testing/btest/Traces/smb/smb3.pcap
let data = hex::decode("fd534d42188d39cea4b1e3f640aff5d0b1569852c0bd665516dbb4b499507f000000000069000000000001003d00009400480000d9f8a66572b40c621bea6f5922a412a8eb2e3cc2af9ce26a277e75898cb523b9eb49ef660a6a1a09368fadd6a58e893e08eb3b7c068bdb74b6cd38e9ed1a2559cefb2ebc2172fd86c08a1a636eb851f20bf53a242f4cfaf7ab44e77291073ad492d6297c3d3a67757c").unwrap();
let result = parse_smb3_transform_record(&data).unwrap();
let record: Smb3TransformRecord = result.1;
assert_eq!(record.session_id, 79167320227901);
assert_eq!(record.enc_algo, 1);
assert_eq!(record.enc_data.len(), 105);
}
}

Loading…
Cancel
Save