|
|
|
@ -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<DceRpcBindIface>,
|
|
|
|
|
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<DceRpcBindIface>,
|
|
|
|
|
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<DceRpcBindIface<'a>>,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
named!(pub parse_dcerpc_bind_record<DceRpcBindRecord>,
|
|
|
|
|
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<DceRpcBindRecord>,
|
|
|
|
|
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<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,
|
|
|
|
|
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<DceRpcBindAckResult<'a>>,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
named!(pub parse_dcerpc_bindack_record<DceRpcBindAckRecord>,
|
|
|
|
|
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<DceRpcRecord>,
|
|
|
|
|
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))
|
|
|
|
|
}
|
|
|
|
|