pull/16240/merge
Shivani Bhardwaj 13 hours ago committed by GitHub
commit a8b7293efd
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

@ -68,6 +68,18 @@ Example::
dcerpc.stub_data; content:"123456";
dcerpc.hdr
----------
Match on the DCERPC header. It is a 'sticky buffer'.
Multi-byte header fields appear in the byte order advertised in the header's
data representation.
Example::
dcerpc.hdr; content:"|10|"; offset:4; depth:1;
Additional information
----------------------

@ -36,7 +36,7 @@ use suricata_sys::sys::{
pub static mut DCERPC_MAX_STUB_SIZE: u32 = 1048576;
// Constant DCERPC UDP Header length
// Constant DCERPC TCP Header length
pub const DCERPC_HDR_LEN: u16 = 16;
// FIRST flag set on the packet
pub const DCERPC_UUID_ENTRY_FLAG_FF: u16 = 0x0001;
@ -205,6 +205,8 @@ pub struct DCERPCTransaction {
pub resp_lost: bool,
pub req_cmd: u8,
pub resp_cmd: u8,
pub req_hdr: Option<Vec<u8>>,
pub resp_hdr: Option<Vec<u8>>,
pub activityuuid: Vec<u8>,
pub seqnum: u32,
pub tx_data: AppLayerTxData,
@ -278,18 +280,39 @@ pub struct Uuid {
pub node: Vec<u8>,
}
#[derive(Debug)]
#[derive(Debug, Clone, Copy)]
pub struct DCERPCHdr {
pub rpc_vers: u8,
pub rpc_vers_minor: u8,
pub hdrtype: u8,
pub pfc_flags: u8,
pub packed_drep: Vec<u8>,
pub packed_drep: [u8; 4],
pub frag_length: u16,
pub auth_length: u16,
pub call_id: u32,
}
impl DCERPCHdr {
pub fn to_bytes(&self) -> [u8; DCERPC_HDR_LEN as usize] {
let mut b = [0u8; DCERPC_HDR_LEN as usize];
b[0] = self.rpc_vers;
b[1] = self.rpc_vers_minor;
b[2] = self.hdrtype;
b[3] = self.pfc_flags;
b[4..8].copy_from_slice(&self.packed_drep);
if self.packed_drep[0] & 0x10 != 0 {
b[8..10].copy_from_slice(&self.frag_length.to_le_bytes());
b[10..12].copy_from_slice(&self.auth_length.to_le_bytes());
b[12..16].copy_from_slice(&self.call_id.to_le_bytes());
} else {
b[8..10].copy_from_slice(&self.frag_length.to_be_bytes());
b[10..12].copy_from_slice(&self.auth_length.to_be_bytes());
b[12..16].copy_from_slice(&self.call_id.to_be_bytes());
}
b
}
}
#[derive(Debug)]
pub struct DCERPCBind {
pub numctxitems: u8,
@ -585,6 +608,7 @@ impl DCERPCState {
}
let mut tx = self.create_tx(hdr);
tx.req_cmd = hdr.hdrtype;
tx.req_hdr = Some(hdr.to_bytes().to_vec());
tx.req_done = true;
if let Some(flow) = self.flow {
sc_app_layer_parser_trigger_raw_stream_inspection(
@ -762,6 +786,7 @@ impl DCERPCState {
match transaction {
Some(ref mut tx) => {
tx.req_cmd = hdr_type;
tx.req_hdr = Some(hdr.to_bytes().to_vec());
tx.ctxid = request.ctxid;
tx.opnum = request.opnum;
tx.first_request_seen = request.first_request_seen;
@ -769,6 +794,7 @@ impl DCERPCState {
None => {
let mut tx = self.create_tx(hdr);
tx.req_cmd = hdr_type;
tx.req_hdr = Some(hdr.to_bytes().to_vec());
tx.ctxid = request.ctxid;
tx.opnum = request.opnum;
tx.first_request_seen = request.first_request_seen;
@ -949,10 +975,12 @@ impl DCERPCState {
self.get_tx_by_call_id(current_call_id, Direction::ToClient, hdrtype)
{
tx.resp_cmd = hdrtype;
tx.resp_hdr = Some(hdr.to_bytes().to_vec());
tx
} else {
let mut tx = self.create_tx(&hdr);
tx.resp_cmd = hdrtype;
tx.resp_hdr = Some(hdr.to_bytes().to_vec());
self.transactions.push_back(tx);
self.transactions.back_mut().unwrap()
};
@ -980,10 +1008,12 @@ impl DCERPCState {
match transaction {
Some(tx) => {
tx.resp_cmd = hdrtype;
tx.resp_hdr = Some(hdr.to_bytes().to_vec());
}
None => {
let mut tx = self.create_tx(&hdr);
tx.resp_cmd = hdrtype;
tx.resp_hdr = Some(hdr.to_bytes().to_vec());
self.transactions.push_back(tx);
}
};

@ -162,7 +162,9 @@ impl DCERPCUDPState {
});
}
pub fn handle_fragment_data(&mut self, hdr: &DCERPCHdrUdp, input: &[u8]) -> bool {
pub fn handle_fragment_data(
&mut self, hdr: &DCERPCHdrUdp, hdr_bytes: &[u8], input: &[u8],
) -> bool {
if hdr.pkt_type != DCERPC_TYPE_REQUEST && hdr.pkt_type != DCERPC_TYPE_RESPONSE {
SCLogDebug!("Unrecognized packet type");
return false;
@ -186,10 +188,12 @@ impl DCERPCUDPState {
tx.tx_data.0.updated_tc = true;
tx.tx_data.0.updated_ts = true;
let done = (hdr.flags1 & PFCL1_FRAG) == 0 || (hdr.flags1 & PFCL1_LASTFRAG) != 0;
let raw_hdr: Option<Vec<u8>> = Some(hdr_bytes.to_vec());
let max_size = cfg_max_stub_size() as usize;
match hdr.pkt_type {
DCERPC_TYPE_REQUEST => {
tx.req_hdr = raw_hdr;
tx.frag_cnt_ts = tx.frag_cnt_ts.saturating_add(1);
if input.len() + tx.stub_data_buffer_ts.len() < max_size {
tx.stub_data_buffer_ts.extend_from_slice(input);
@ -203,6 +207,7 @@ impl DCERPCUDPState {
return true;
}
DCERPC_TYPE_RESPONSE => {
tx.resp_hdr = raw_hdr;
tx.frag_cnt_tc = tx.frag_cnt_tc.saturating_add(1);
if input.len() + tx.stub_data_buffer_tc.len() < max_size {
tx.stub_data_buffer_tc.extend_from_slice(input);
@ -244,7 +249,12 @@ impl DCERPCUDPState {
);
return AppLayerResult::err();
}
if !self.handle_fragment_data(&header, &leftover_bytes[..header.fraglen as usize]) {
let hdr_len = DCERPC_UDP_HDR_LEN as usize;
if !self.handle_fragment_data(
&header,
&input[..hdr_len],
&leftover_bytes[..header.fraglen as usize],
) {
return AppLayerResult::err();
}
}

@ -439,10 +439,56 @@ unsafe extern "C" fn dcerpc_tx_get_stub_data(
return buffer;
}
unsafe extern "C" fn dcerpc_hdr_setup(
de_ctx: *mut DetectEngineCtx, s: *mut Signature, _str: *const c_char,
) -> c_int {
if SCDetectSignatureSetAppProto(s, ALPROTO_DCERPC) < 0 {
return -1;
}
if SCDetectBufferSetActiveList(de_ctx, s, G_DCERPC_HDR_BUFFER_ID) < 0 {
return -1;
}
return 0;
}
unsafe extern "C" fn dcerpc_tx_get_hdr(
det_ctx: *mut DetectEngineThreadCtx, transforms: *const DetectEngineTransforms,
_flow: *mut Flow, dir: u8, tx: *mut c_void, list_id: c_int,
) -> *mut InspectionBuffer {
let tx = cast_pointer!(tx, DCERPCTransaction);
let buffer = SCInspectionBufferGet(det_ctx, list_id);
if !(*buffer).initialized {
let hdr: Option<&[u8]> = if (dir & STREAM_TOSERVER) != 0 {
tx.req_hdr.as_deref()
} else {
tx.resp_hdr.as_deref()
};
if let Some(hdr) = hdr {
if hdr[4] & 0x10 != 0 {
(*buffer).flags |= DETECT_CI_FLAGS_DCE_LE;
} else {
(*buffer).flags |= DETECT_CI_FLAGS_DCE_BE;
}
SCInspectionBufferSetupAndApplyTransforms(
det_ctx,
list_id,
buffer,
hdr.as_ptr(),
hdr.len() as u32,
transforms,
);
} else {
return std::ptr::null_mut();
}
}
return buffer;
}
static mut G_DCERPC_OPNUM_KW_ID: u16 = 0;
static mut G_DCERPC_GENERIC_BUFFER_ID: c_int = 0;
static mut G_DCERPC_IFACE_KW_ID: u16 = 0;
static mut G_DCERPC_STUB_BUFFER_ID: c_int = 0;
static mut G_DCERPC_HDR_BUFFER_ID: c_int = 0;
#[no_mangle]
pub unsafe extern "C" fn SCDetectDcerpcRegister() {
@ -517,6 +563,22 @@ pub unsafe extern "C" fn SCDetectDcerpcRegister() {
stub_kw_id,
b"dce_stub_data\0".as_ptr() as *const libc::c_char,
);
let kw_hdr = SigTableElmtStickyBuffer {
name: String::from("dcerpc.hdr"),
desc: String::from("match on the DCERPC header per direction"),
url: String::from("/rules/dcerpc-keywords.html#dcerpc-hdr"),
setup: dcerpc_hdr_setup,
};
let _hdr_kw_id = helper_keyword_register_sticky_buffer(&kw_hdr);
G_DCERPC_HDR_BUFFER_ID = SCDetectRegisterMpmGeneric(
b"dcerpc.hdr\0".as_ptr() as *const libc::c_char,
b"dcerpc header\0".as_ptr() as *const libc::c_char,
ALPROTO_DCERPC,
STREAM_TOSERVER | STREAM_TOCLIENT,
Some(dcerpc_tx_get_hdr),
0,
);
}
#[cfg(test)]

@ -233,7 +233,12 @@ pub(super) fn parse_dcerpc_header(i: &[u8]) -> IResult<&[u8], DCERPCHdr> {
rpc_vers_minor,
hdrtype,
pfc_flags,
packed_drep: packed_drep.to_vec(),
packed_drep: [
packed_drep[0],
packed_drep[1],
packed_drep[2],
packed_drep[3],
],
frag_length,
auth_length,
call_id,

Loading…
Cancel
Save