rust/dcerpc: convert parser to nom7 functions

pull/6996/head
Pierre Chifflier 4 years ago committed by Victor Julien
parent a3443845fb
commit 8dc3431d86

@ -18,9 +18,9 @@
use crate::applayer::*; use crate::applayer::*;
use crate::core::{self, *}; use crate::core::{self, *};
use crate::dcerpc::parser; use crate::dcerpc::parser;
use nom::error::ErrorKind; use nom7::error::{Error, ErrorKind};
use nom::number::Endianness; use nom7::number::Endianness;
use nom; use nom7::{Err, IResult, Needed};
use std; use std;
use std::cmp; use std::cmp;
use std::ffi::CString; use std::ffi::CString;
@ -575,7 +575,7 @@ impl DCERPCState {
} }
} }
pub fn search_dcerpc_record<'a>(&mut self, i: &'a[u8]) -> nom::IResult<&'a[u8], &'a[u8]> { pub fn search_dcerpc_record<'a>(&mut self, i: &'a[u8]) -> IResult<&'a[u8], &'a[u8]> {
let mut d = i; let mut d = i;
while d.len() >= 2 { while d.len() >= 2 {
if d[0] == 0x05 && d[1] == 0x00 { if d[0] == 0x05 && d[1] == 0x00 {
@ -583,7 +583,7 @@ impl DCERPCState {
} }
d = &d[1..]; d = &d[1..];
} }
Err(nom::Err::Incomplete(nom::Needed::Size(2 as usize - d.len()))) Err(Err::Incomplete(Needed::new(2 as usize - d.len())))
} }
/// Makes a call to the nom parser for parsing DCERPC Header. /// Makes a call to the nom parser for parsing DCERPC Header.
@ -613,12 +613,12 @@ impl DCERPCState {
self.header = Some(header); self.header = Some(header);
(input.len() - leftover_bytes.len()) as i32 (input.len() - leftover_bytes.len()) as i32
} }
Err(nom::Err::Incomplete(_)) => { Err(Err::Incomplete(_)) => {
// Insufficient data. // Insufficient data.
SCLogDebug!("Insufficient data while parsing DCERPC header"); SCLogDebug!("Insufficient data while parsing DCERPC header");
-1 -1
} }
Err(nom::Err::Error(([], ErrorKind::Eof))) => { Err(Err::Error(Error{code:ErrorKind::Eof, ..})) => {
SCLogDebug!("EoF reached while parsing DCERPC header"); SCLogDebug!("EoF reached while parsing DCERPC header");
-1 -1
} }
@ -652,7 +652,7 @@ impl DCERPCState {
} }
(input.len() - leftover_bytes.len()) as i32 (input.len() - leftover_bytes.len()) as i32
} }
Err(nom::Err::Incomplete(_)) => { Err(Err::Incomplete(_)) => {
// Insufficient data. // Insufficient data.
SCLogDebug!("Insufficient data while parsing DCERPC BIND CTXItem"); SCLogDebug!("Insufficient data while parsing DCERPC BIND CTXItem");
-1 -1
@ -692,7 +692,7 @@ impl DCERPCState {
// of bindctxitems) // of bindctxitems)
(input.len() - leftover_bytes.len()) as i32 + retval * numctxitems as i32 (input.len() - leftover_bytes.len()) as i32 + retval * numctxitems as i32
} }
Err(nom::Err::Incomplete(_)) => { Err(Err::Incomplete(_)) => {
// Insufficient data. // Insufficient data.
SCLogDebug!("Insufficient data while parsing DCERPC BIND header"); SCLogDebug!("Insufficient data while parsing DCERPC BIND header");
-1 -1
@ -727,7 +727,7 @@ impl DCERPCState {
} }
(input.len() - leftover_bytes.len()) as i32 (input.len() - leftover_bytes.len()) as i32
} }
Err(nom::Err::Incomplete(_)) => { Err(Err::Incomplete(_)) => {
// Insufficient data. // Insufficient data.
SCLogDebug!("Insufficient data while parsing DCERPC BINDACK"); SCLogDebug!("Insufficient data while parsing DCERPC BINDACK");
-1 -1
@ -877,7 +877,7 @@ impl DCERPCState {
); );
parsed parsed
} }
Err(nom::Err::Incomplete(_)) => { Err(Err::Incomplete(_)) => {
// Insufficient data. // Insufficient data.
SCLogDebug!("Insufficient data while parsing DCERPC REQUEST"); SCLogDebug!("Insufficient data while parsing DCERPC REQUEST");
-1 -1

@ -21,6 +21,7 @@ use crate::dcerpc::dcerpc::{
DCERPCTransaction, DCERPC_TYPE_REQUEST, DCERPC_TYPE_RESPONSE, PFCL1_FRAG, PFCL1_LASTFRAG, DCERPCTransaction, DCERPC_TYPE_REQUEST, DCERPC_TYPE_RESPONSE, PFCL1_FRAG, PFCL1_LASTFRAG,
rs_dcerpc_get_alstate_progress, ALPROTO_DCERPC, PARSER_NAME, rs_dcerpc_get_alstate_progress, ALPROTO_DCERPC, PARSER_NAME,
}; };
use nom7::Err;
use std; use std;
use std::ffi::CString; use std::ffi::CString;
use crate::dcerpc::parser; use crate::dcerpc::parser;
@ -189,7 +190,7 @@ impl DCERPCUDPState {
return AppLayerResult::err(); return AppLayerResult::err();
} }
} }
Err(nom::Err::Incomplete(_)) => { Err(Err::Incomplete(_)) => {
// Insufficient data. // Insufficient data.
SCLogDebug!("Insufficient data while parsing DCERPC request"); SCLogDebug!("Insufficient data while parsing DCERPC request");
return AppLayerResult::err(); return AppLayerResult::err();

@ -18,8 +18,12 @@ use crate::dcerpc::dcerpc::{
BindCtxItem, DCERPCBind, DCERPCBindAck, DCERPCBindAckResult, DCERPCHdr, DCERPCRequest, Uuid, BindCtxItem, DCERPCBind, DCERPCBindAck, DCERPCBindAckResult, DCERPCHdr, DCERPCRequest, Uuid,
}; };
use crate::dcerpc::dcerpc_udp::DCERPCHdrUdp; use crate::dcerpc::dcerpc_udp::DCERPCHdrUdp;
use nom::number::complete::{le_u16, le_u32, le_u8}; use nom7::bytes::streaming::take;
use nom::number::Endianness; use nom7::combinator::cond;
use nom7::number::complete::{le_u16, le_u32, le_u8, u16, u32};
use nom7::number::Endianness;
use nom7::multi::count;
use nom7::IResult;
fn uuid_to_vec(uuid: Uuid) -> Vec<u8> { fn uuid_to_vec(uuid: Uuid) -> Vec<u8> {
let mut uuidtmp = uuid; let mut uuidtmp = uuid;
@ -49,216 +53,192 @@ fn assemble_uuid(uuid: Uuid) -> Vec<u8> {
vect vect
} }
named!(pub parse_uuid<Uuid>, pub fn parse_uuid(i: &[u8]) -> IResult<&[u8], Uuid> {
do_parse!( let (i, time_low) = take(4_usize)(i)?;
time_low: take!(4) let (i, time_mid) = take(2_usize)(i)?;
>> time_mid: take!(2) let (i, time_hi_and_version) = take(2_usize)(i)?;
>> time_hi_and_version: take!(2) let (i, clock_seq_hi_and_reserved) = le_u8(i)?;
>> clock_seq_hi_and_reserved: le_u8 let (i, clock_seq_low) = le_u8(i)?;
>> clock_seq_low: le_u8 let (i, node) = take(6_usize)(i)?;
>> node: take!(6) let uuid = Uuid {
>> ( time_low: time_low.to_vec(),
Uuid { time_mid: time_mid.to_vec(),
time_low: time_low.to_vec(), time_hi_and_version: time_hi_and_version.to_vec(),
time_mid: time_mid.to_vec(), clock_seq_hi_and_reserved,
time_hi_and_version: time_hi_and_version.to_vec(), clock_seq_low,
clock_seq_hi_and_reserved: clock_seq_hi_and_reserved, node: node.to_vec(),
clock_seq_low: clock_seq_low, };
node: node.to_vec(), Ok((i, uuid))
} }
)
)
);
named!(pub parse_dcerpc_udp_header<DCERPCHdrUdp>, pub fn parse_dcerpc_udp_header(i: &[u8]) -> IResult<&[u8], DCERPCHdrUdp> {
do_parse!( let (i, rpc_vers) = le_u8(i)?;
rpc_vers: le_u8 let (i, pkt_type) = le_u8(i)?;
>> pkt_type: le_u8 let (i, flags1) = le_u8(i)?;
>> flags1: le_u8 let (i, flags2) = le_u8(i)?;
>> flags2: le_u8 let (i, drep) = take(3_usize)(i)?;
>> drep: take!(3) let endianness = if drep[0] == 0 { Endianness::Big } else { Endianness::Little };
>> endianness: value!(if drep[0] == 0 { Endianness::Big } else { Endianness::Little }) let (i, serial_hi) = le_u8(i)?;
>> serial_hi: le_u8 let (i, objectuuid) = take(16_usize)(i)?;
>> objectuuid: take!(16) let (i, interfaceuuid) = take(16_usize)(i)?;
>> interfaceuuid: take!(16) let (i, activityuuid) = take(16_usize)(i)?;
>> activityuuid: take!(16) let (i, server_boot) = u32(endianness)(i)?;
>> server_boot: u32!(endianness) let (i, if_vers) = u32(endianness)(i)?;
>> if_vers: u32!(endianness) let (i, seqnum) = u32(endianness)(i)?;
>> seqnum: u32!(endianness) let (i, opnum) = u16(endianness)(i)?;
>> opnum: u16!(endianness) let (i, ihint) = u16(endianness)(i)?;
>> ihint: u16!(endianness) let (i, ahint) = u16(endianness)(i)?;
>> ahint: u16!(endianness) let (i, fraglen) = u16(endianness)(i)?;
>> fraglen: u16!(endianness) let (i, fragnum) = u16(endianness)(i)?;
>> fragnum: u16!(endianness) let (i, auth_proto) = le_u8(i)?;
>> auth_proto: le_u8 let (i, serial_lo) = le_u8(i)?;
>> serial_lo: le_u8 let header = DCERPCHdrUdp {
>> ( rpc_vers,
DCERPCHdrUdp { pkt_type,
rpc_vers: rpc_vers, flags1,
pkt_type: pkt_type, flags2,
flags1: flags1, drep: drep.to_vec(),
flags2: flags2, serial_hi,
drep: drep.to_vec(), objectuuid: match parse_uuid(objectuuid) {
serial_hi: serial_hi, Ok((_, vect)) => assemble_uuid(vect),
objectuuid: match parse_uuid(objectuuid) { Err(_e) => {
Ok((_, vect)) => assemble_uuid(vect), SCLogDebug!("{}", _e);
Err(_e) => { vec![0]
SCLogDebug!("{}", _e); },
vec![0] },
}, interfaceuuid: match parse_uuid(interfaceuuid) {
}, Ok((_, vect)) => assemble_uuid(vect),
interfaceuuid: match parse_uuid(interfaceuuid) { Err(_e) => {
Ok((_, vect)) => assemble_uuid(vect), SCLogDebug!("{}", _e);
Err(_e) => { vec![0]
SCLogDebug!("{}", _e); },
vec![0] },
}, activityuuid: match parse_uuid(activityuuid){
}, Ok((_, vect)) => assemble_uuid(vect),
activityuuid: match parse_uuid(activityuuid){ Err(_e) => {
Ok((_, vect)) => assemble_uuid(vect), SCLogDebug!("{}", _e);
Err(_e) => { vec![0]
SCLogDebug!("{}", _e); },
vec![0] },
}, server_boot,
}, if_vers,
server_boot: server_boot, seqnum,
if_vers: if_vers, opnum,
seqnum: seqnum, ihint,
opnum: opnum, ahint,
ihint: ihint, fraglen,
ahint: ahint, fragnum,
fraglen: fraglen, auth_proto,
fragnum: fragnum, serial_lo,
auth_proto: auth_proto, };
serial_lo: serial_lo, Ok((i, header))
} }
)
)
);
named!(pub parse_dcerpc_bindack_result<DCERPCBindAckResult>, pub fn parse_dcerpc_bindack_result(i: &[u8]) -> IResult<&[u8], DCERPCBindAckResult> {
do_parse!( let (i, ack_result) = le_u16(i)?;
ack_result: le_u16 let (i, ack_reason) = le_u16(i)?;
>> ack_reason: le_u16 let (i, transfer_syntax) = take(16_usize)(i)?;
>> transfer_syntax: take!(16) let (i, syntax_version) = le_u32(i)?;
>> syntax_version: le_u32 let result = DCERPCBindAckResult {
>> ( ack_result,
DCERPCBindAckResult { ack_reason,
ack_result:ack_result, transfer_syntax: transfer_syntax.to_vec(),
ack_reason:ack_reason, syntax_version,
transfer_syntax:transfer_syntax.to_vec(), };
syntax_version:syntax_version, Ok((i, result))
} }
)
)
);
named!(pub parse_dcerpc_bindack<DCERPCBindAck>, pub fn parse_dcerpc_bindack(i: &[u8]) -> IResult<&[u8], DCERPCBindAck> {
do_parse!( let (i, _max_xmit_frag) = le_u16(i)?;
_max_xmit_frag: le_u16 let (i, _max_recv_frag) = le_u16(i)?;
>> _max_recv_frag: le_u16 let (i, _assoc_group) = take(4_usize)(i)?;
>> _assoc_group: take!(4) let (i, sec_addr_len) = le_u16(i)?;
>> sec_addr_len: le_u16 let (i, _) = take(sec_addr_len)(i)?;
>> take!(sec_addr_len) let (i, _) = cond((sec_addr_len + 2) % 4 != 0, |b| take(4 - (sec_addr_len + 2) % 4)(b))(i)?;
>> cond!((sec_addr_len + 2) % 4 != 0, take!(4 - (sec_addr_len + 2) % 4)) let (i, numctxitems) = le_u8(i)?;
>> numctxitems: le_u8 let (i, _) = take(3_usize)(i)?; // Padding
>> take!(3) // Padding let (i, ctxitems) = count(parse_dcerpc_bindack_result, numctxitems as usize)(i)?;
>> ctxitems: count!(parse_dcerpc_bindack_result, numctxitems as usize) let result = DCERPCBindAck {
>> ( accepted_uuid_list: Vec::new(),
DCERPCBindAck { sec_addr_len,
accepted_uuid_list: Vec::new(), numctxitems,
sec_addr_len: sec_addr_len, ctxitems,
numctxitems: numctxitems, };
ctxitems: ctxitems, Ok((i, result))
} }
)
)
);
named_args!(pub parse_bindctx_item(endianness: Endianness) <BindCtxItem>, pub fn parse_bindctx_item(i: &[u8], endianness: Endianness) -> IResult<&[u8], BindCtxItem> {
do_parse!( let (i, ctxid) = u16(endianness)(i)?;
ctxid: u16!(endianness) let (i, _num_trans_items) = le_u8(i)?;
>> _num_trans_items: le_u8 let (i, _) = take(1_usize)(i)?; // Reservid bit
>> take!(1) // Reservid bit let (i, uuid) = take(16_usize)(i)?;
>> uuid: take!(16) let (i, version) = u16(endianness)(i)?;
>> version: u16!(endianness) let (i, versionminor) = u16(endianness)(i)?;
>> versionminor: u16!(endianness) let (i, _) = take(20_usize)(i)?;
>> take!(20) let result = BindCtxItem {
>> ( ctxid,
BindCtxItem { // UUID parsing for TCP seems to change as per endianness
ctxid: ctxid, uuid: match parse_uuid(uuid) {
// UUID parsing for TCP seems to change as per endianness Ok((_, vect)) => match endianness {
uuid: match parse_uuid(uuid) { Endianness::Little => assemble_uuid(vect),
Ok((_, vect)) => match endianness { _ => uuid_to_vec(vect),
Endianness::Little => assemble_uuid(vect), },
_ => uuid_to_vec(vect), // Shouldn't happen
}, Err(_e) => {vec![0]},
// Shouldn't happen },
Err(_e) => {vec![0]}, version,
}, versionminor,
version: version, };
versionminor: versionminor, Ok((i, result))
} }
)
)
);
named!(pub parse_dcerpc_bind<DCERPCBind>, pub fn parse_dcerpc_bind(i: &[u8]) -> IResult<&[u8], DCERPCBind> {
do_parse!( let (i, _max_xmit_frag) = le_u16(i)?;
_max_xmit_frag: le_u16 let (i, _max_recv_frag) = le_u16(i)?;
>> _max_recv_frag: le_u16 let (i, _assoc_group_id) = le_u32(i)?;
>> _assoc_group_id: le_u32 let (i, numctxitems) = le_u8(i)?;
>> numctxitems: le_u8 let (i, _) = take(3_usize)(i)?;
>> take!(3) let result = DCERPCBind {
>> ( numctxitems,
DCERPCBind { uuid_list: Vec::new(),
numctxitems: numctxitems, };
uuid_list: Vec::new(), Ok((i, result))
} }
)
)
);
named!(pub parse_dcerpc_header<DCERPCHdr>, pub fn parse_dcerpc_header(i: &[u8]) -> IResult<&[u8], DCERPCHdr> {
do_parse!( let (i, rpc_vers) = le_u8(i)?;
rpc_vers: le_u8 let (i, rpc_vers_minor) = le_u8(i)?;
>> rpc_vers_minor: le_u8 let (i, hdrtype) = le_u8(i)?;
>> hdrtype: le_u8 let (i, pfc_flags) = le_u8(i)?;
>> pfc_flags: le_u8 let (i, packed_drep) = take(4_usize)(i)?;
>> packed_drep: take!(4) let endianness = if packed_drep[0] & 0x10 == 0 { Endianness::Big } else { Endianness::Little };
>> endianness: value!(if packed_drep[0] & 0x10 == 0 { Endianness::Big } else { Endianness::Little }) let (i, frag_length) = u16(endianness)(i)?;
>> frag_length: u16!(endianness) let (i, auth_length) = u16(endianness)(i)?;
>> auth_length: u16!(endianness) let (i, call_id) = u32(endianness)(i)?;
>> call_id: u32!(endianness) let header = DCERPCHdr {
>> ( rpc_vers,
DCERPCHdr { rpc_vers_minor,
rpc_vers: rpc_vers, hdrtype,
rpc_vers_minor: rpc_vers_minor, pfc_flags,
hdrtype: hdrtype, packed_drep: packed_drep.to_vec(),
pfc_flags: pfc_flags, frag_length,
packed_drep: packed_drep.to_vec(), auth_length,
frag_length: frag_length, call_id,
auth_length: auth_length, };
call_id: call_id, Ok((i, header))
} }
)
)
);
named_args!(pub parse_dcerpc_request(endianness: Endianness) <DCERPCRequest>, pub fn parse_dcerpc_request(i: &[u8], endianness: Endianness) -> IResult<&[u8], DCERPCRequest> {
do_parse!( let (i, _pad) = take(4_usize)(i)?;
_pad: take!(4) let (i, ctxid) = u16(endianness)(i)?;
>> ctxid: u16!(endianness) let (i, opnum) = u16(endianness)(i)?;
>> opnum: u16!(endianness) let req = DCERPCRequest {
>> ( ctxid,
DCERPCRequest { opnum,
ctxid: ctxid, first_request_seen: 1,
opnum: opnum, };
first_request_seen: 1, Ok((i, req))
} }
)
)
);
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {

Loading…
Cancel
Save