From 895a54cea4b6a6679af33fe5556d6a4d3568abf7 Mon Sep 17 00:00:00 2001 From: Pierre Chifflier Date: Sun, 14 Nov 2021 17:18:14 +0100 Subject: [PATCH] rust/smb: convert parser to nom7 functions (DCERPC records) --- rust/src/smb/dcerpc_records.rs | 265 +++++++++++++++++---------------- 1 file changed, 135 insertions(+), 130 deletions(-) diff --git a/rust/src/smb/dcerpc_records.rs b/rust/src/smb/dcerpc_records.rs index 8d0b07faf9..57bbdf830a 100644 --- a/rust/src/smb/dcerpc_records.rs +++ b/rust/src/smb/dcerpc_records.rs @@ -16,11 +16,15 @@ */ use crate::smb::error::SmbError; -use nom; -use nom::IResult; -use nom::combinator::rest; -use nom::number::Endianness; -use nom::number::streaming::{be_u16, le_u8, le_u16, le_u32}; +use nom7::bits::{bits, streaming::take as take_bits}; +use nom7::bytes::streaming::take; +use nom7::combinator::{cond, rest}; +use nom7::error::Error; +use nom7::multi::count; +use nom7::number::Endianness; +use nom7::number::streaming::{be_u16, le_u8, le_u16, le_u32, u16, u32}; +use nom7::sequence::tuple; +use nom7::IResult; #[derive(Debug,PartialEq)] pub struct DceRpcResponseRecord<'a> { @@ -30,7 +34,7 @@ pub struct DceRpcResponseRecord<'a> { /// parse a packet type 'response' DCERPC record. Implemented /// as function to be able to pass the fraglen in. pub fn parse_dcerpc_response_record(i:&[u8], frag_len: u16 ) - -> IResult<&[u8], DceRpcResponseRecord, SmbError> + -> nom::IResult<&[u8], DceRpcResponseRecord, SmbError> { if frag_len < 24 { return Err(nom::Err::Error(SmbError::RecordTooSmall)); @@ -53,8 +57,9 @@ pub struct DceRpcRequestRecord<'a> { /// parse a packet type 'request' DCERPC record. Implemented /// as function to be able to pass the fraglen in. pub fn parse_dcerpc_request_record(i:&[u8], frag_len: u16, little: bool) - -> IResult<&[u8], DceRpcRequestRecord, SmbError> + -> nom::IResult<&[u8], DceRpcRequestRecord, SmbError> { + use nom::number::Endianness; if frag_len < 24 { return Err(nom::Err::Error(SmbError::RecordTooSmall)); } @@ -77,37 +82,37 @@ pub struct DceRpcBindIface<'a> { pub ver_min: u16, } -named!(pub parse_dcerpc_bind_iface, - do_parse!( - _ctx_id: le_u16 - >> _num_trans_items: le_u8 - >> take!(1) // reserved - >> interface: take!(16) - >> ver: le_u16 - >> ver_min: le_u16 - >> take!(20) - >> (DceRpcBindIface { - iface:interface, - ver:ver, - ver_min:ver_min, - }) -)); - -named!(pub parse_dcerpc_bind_iface_big, - do_parse!( - _ctx_id: le_u16 - >> _num_trans_items: le_u8 - >> take!(1) // reserved - >> interface: take!(16) - >> ver_min: be_u16 - >> ver: be_u16 - >> take!(20) - >> (DceRpcBindIface { - iface:interface, - ver:ver, - ver_min:ver_min, - }) -)); +pub fn parse_dcerpc_bind_iface(i: &[u8]) -> IResult<&[u8], DceRpcBindIface> { + let (i, _ctx_id) = le_u16(i)?; + let (i, _num_trans_items) = le_u8(i)?; + let (i, _) = take(1_usize)(i)?; // reserved + let (i, interface) = take(16_usize)(i)?; + let (i, ver) = le_u16(i)?; + let (i, ver_min) = le_u16(i)?; + let (i, _) = take(20_usize)(i)?; + let res = DceRpcBindIface { + iface:interface, + ver, + ver_min, + }; + Ok((i, res)) +} + +pub fn parse_dcerpc_bind_iface_big(i: &[u8]) -> IResult<&[u8], DceRpcBindIface> { + let (i, _ctx_id) = le_u16(i)?; + let (i, _num_trans_items) = le_u8(i)?; + let (i, _) = take(1_usize)(i)?; // reserved + let (i, interface) = take(16_usize)(i)?; + let (i, ver_min) = be_u16(i)?; + let (i, ver) = be_u16(i)?; + let (i, _) = take(20_usize)(i)?; + let res = DceRpcBindIface { + iface:interface, + ver, + ver_min, + }; + Ok((i, res)) +} #[derive(Debug,PartialEq)] pub struct DceRpcBindRecord<'a> { @@ -115,33 +120,33 @@ pub struct DceRpcBindRecord<'a> { pub ifaces: Vec>, } -named!(pub parse_dcerpc_bind_record, - do_parse!( - _max_xmit_frag: le_u16 - >> _max_recv_frag: le_u16 - >> _assoc_group: take!(4) - >> num_ctx_items: le_u8 - >> take!(3) // reserved - >> ifaces: count!(parse_dcerpc_bind_iface, num_ctx_items as usize) - >> (DceRpcBindRecord { - num_ctx_items:num_ctx_items, - ifaces:ifaces, - }) -)); - -named!(pub parse_dcerpc_bind_record_big, - do_parse!( - _max_xmit_frag: be_u16 - >> _max_recv_frag: be_u16 - >> _assoc_group: take!(4) - >> num_ctx_items: le_u8 - >> take!(3) // reserved - >> ifaces: count!(parse_dcerpc_bind_iface_big, num_ctx_items as usize) - >> (DceRpcBindRecord { - num_ctx_items:num_ctx_items, - ifaces:ifaces, - }) -)); +pub fn parse_dcerpc_bind_record(i: &[u8]) -> IResult<&[u8], DceRpcBindRecord> { + let (i, _max_xmit_frag) = le_u16(i)?; + let (i, _max_recv_frag) = le_u16(i)?; + let (i, _assoc_group) = take(4_usize)(i)?; + let (i, num_ctx_items) = le_u8(i)?; + let (i, _) = take(3_usize)(i)?; // reserved + let (i, ifaces) = count(parse_dcerpc_bind_iface, num_ctx_items as usize)(i)?; + let record = DceRpcBindRecord { + num_ctx_items, + ifaces, + }; + Ok((i, record)) +} + +pub fn parse_dcerpc_bind_record_big(i: &[u8]) -> IResult<&[u8], DceRpcBindRecord> { + let (i, _max_xmit_frag) = be_u16(i)?; + let (i, _max_recv_frag) = be_u16(i)?; + let (i, _assoc_group) = take(4_usize)(i)?; + let (i, num_ctx_items) = le_u8(i)?; + let (i, _) = take(3_usize)(i)?; // reserved + let (i, ifaces) = count(parse_dcerpc_bind_iface_big, num_ctx_items as usize)(i)?; + let record = DceRpcBindRecord { + num_ctx_items, + ifaces, + }; + Ok((i, record)) +} #[derive(Debug,PartialEq)] pub struct DceRpcBindAckResult<'a> { @@ -151,19 +156,19 @@ pub struct DceRpcBindAckResult<'a> { pub syntax_version: u32, } -named!(pub parse_dcerpc_bindack_result, - do_parse!( - ack_result: le_u16 - >> ack_reason: le_u16 - >> transfer_syntax: take!(16) - >> syntax_version: le_u32 - >> (DceRpcBindAckResult { - ack_result:ack_result, - ack_reason:ack_reason, - transfer_syntax:transfer_syntax, - syntax_version:syntax_version, - }) -)); +pub fn parse_dcerpc_bindack_result(i: &[u8]) -> IResult<&[u8], DceRpcBindAckResult> { + let (i, ack_result) = le_u16(i)?; + let (i, ack_reason) = le_u16(i)?; + let (i, transfer_syntax) = take(16_usize)(i)?; + let (i, syntax_version) = le_u32(i)?; + let res = DceRpcBindAckResult { + ack_result, + ack_reason, + transfer_syntax, + syntax_version, + }; + Ok((i, res)) +} #[derive(Debug,PartialEq)] pub struct DceRpcBindAckRecord<'a> { @@ -171,22 +176,22 @@ pub struct DceRpcBindAckRecord<'a> { pub results: Vec>, } -named!(pub parse_dcerpc_bindack_record, - do_parse!( - _max_xmit_frag: le_u16 - >> _max_recv_frag: le_u16 - >> _assoc_group: take!(4) - >> sec_addr_len: le_u16 - >> take!(sec_addr_len) - >> cond!((sec_addr_len+2) % 4 != 0, take!(4 - (sec_addr_len+2) % 4)) - >> num_results: le_u8 - >> take!(3) // padding - >> results: count!(parse_dcerpc_bindack_result, num_results as usize) - >> (DceRpcBindAckRecord { - num_results:num_results, - results:results, - }) -)); +pub fn parse_dcerpc_bindack_record(i: &[u8]) -> IResult<&[u8], DceRpcBindAckRecord> { + let (i, _max_xmit_frag) = le_u16(i)?; + let (i, _max_recv_frag) = le_u16(i)?; + let (i, _assoc_group) = take(4_usize)(i)?; + let (i, sec_addr_len) = le_u16(i)?; + let (i, _) = take(sec_addr_len)(i)?; + let (i, _) = cond((sec_addr_len+2) % 4 != 0, take(4 - (sec_addr_len+2) % 4))(i)?; + let (i, num_results) = le_u8(i)?; + let (i, _) = take(3_usize)(i)?; // padding + let (i, results) = count(parse_dcerpc_bindack_result, num_results as usize)(i)?; + let record = DceRpcBindAckRecord { + num_results, + results, + }; + Ok((i, record)) +} #[derive(Debug,PartialEq)] pub struct DceRpcRecord<'a> { @@ -207,42 +212,42 @@ pub struct DceRpcRecord<'a> { } fn parse_dcerpc_flags1(i:&[u8]) -> IResult<&[u8],(u8,u8,u8)> { - bits!(i, - tuple!( - take_bits!(6u8), - take_bits!(1u8), // last (1) - take_bits!(1u8))) // first (2) + bits::<_, _, Error<(&[u8], usize)>, _, _>(tuple(( + take_bits(6u8), + take_bits(1u8), // last (1) + take_bits(1u8), + )))(i) } fn parse_dcerpc_flags2(i:&[u8]) -> IResult<&[u8],(u32,u32,u32)> { - bits!(i, - tuple!( - take_bits!(3u32), - take_bits!(1u32), // endianess - take_bits!(28u32))) -} - -named!(pub parse_dcerpc_record, - do_parse!( - version_major: le_u8 - >> version_minor: le_u8 - >> packet_type: le_u8 - >> packet_flags: parse_dcerpc_flags1 - >> data_rep: parse_dcerpc_flags2 - >> endian: value!(if data_rep.1 == 0 { Endianness::Big } else { Endianness::Little }) - >> frag_len: u16!(endian) - >> _auth: u16!(endian) - >> call_id: u32!(endian) - >> data:rest - >> (DceRpcRecord { - version_major:version_major, - version_minor:version_minor, - packet_type:packet_type, - first_frag:packet_flags.2==1, - last_frag:packet_flags.1==1, - frag_len: frag_len, - little_endian:data_rep.1==1, - call_id:call_id, - data:data, - }) -)); + bits::<_, _, Error<(&[u8], usize)>, _, _>(tuple(( + take_bits(3u32), + take_bits(1u32), // endianess + take_bits(28u32), + )))(i) +} + +pub fn parse_dcerpc_record(i: &[u8]) -> IResult<&[u8], DceRpcRecord> { + let (i, version_major) = le_u8(i)?; + let (i, version_minor) = le_u8(i)?; + let (i, packet_type) = le_u8(i)?; + let (i, packet_flags) = parse_dcerpc_flags1(i)?; + let (i, data_rep) = parse_dcerpc_flags2(i)?; + let endian = if data_rep.1 == 0 { Endianness::Big } else { Endianness::Little }; + let (i, frag_len) = u16(endian)(i)?; + let (i, _auth) = u16(endian)(i)?; + let (i, call_id) = u32(endian)(i)?; + let (i, data) = rest(i)?; + let record = DceRpcRecord { + version_major, + version_minor, + packet_type, + first_frag: packet_flags.2 == 1, + last_frag: packet_flags.1 == 1, + frag_len, + little_endian: data_rep.1 == 1, + call_id, + data, + }; + Ok((i, record)) +}