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